diff --git a/DEPS b/DEPS index 0e1da20..cb04a1f 100644 --- a/DEPS +++ b/DEPS
@@ -175,11 +175,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': '89bf1547f3aa3ff3c142d197c14bbce1e199db2b', + 'skia_revision': '81158535ed1ba414458e2b8b7980b7d5a8f55bb8', # 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': '8c170824164c4917fb99a9c38b34609b152e949c', + 'v8_revision': '4c53f9a51444393133ff303952f1296603d44ab7', # 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. @@ -187,11 +187,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ANGLE # and whatever else without interference from each other. - 'angle_revision': '01dd6f6ca430a5c5bfd9d237b5569abd835694fc', + 'angle_revision': 'fca5a005aa880a51672c091fcb82f084b620670a', # 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': '6e3a387c01598240a7a8722ab8cbd1015ec1cd0a', + 'swiftshader_revision': '59465799210b3f4962af1a9dc44a4ffecb422c10', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. @@ -238,7 +238,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': '189074525f4700d6700feef3d2fd5ea07eb64985', + 'catapult_revision': '263d57d37615e12c492bdec884b23e46dbdd1fee', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other. @@ -246,7 +246,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling devtools-frontend # and whatever else without interference from each other. - 'devtools_frontend_revision': '451736382565ecf11f295b8220f4ef5d033e0e0e', + 'devtools_frontend_revision': 'b015b7d12040e53bb0c987a4db6c9cbb774bde41', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libprotobuf-mutator # and whatever else without interference from each other. @@ -310,7 +310,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'quiche_revision': '85240a12ed2b9ccb08ae449bca1bbf9eb93c8a12', + 'quiche_revision': '50ea92a176baa696e88b519609584214317745eb', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ios_webkit # and whatever else without interference from each other. @@ -864,7 +864,7 @@ # Build tools for Chrome OS. Note: This depends on third_party/pyelftools. 'src/third_party/chromite': { - 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '63b6be2bbc9985f8be563bff093acc2b3821ba35', + 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '5b94048566ab2a458316af49f35655586fe503b0', 'condition': 'checkout_linux', }, @@ -1483,7 +1483,7 @@ Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '53655df4cde60b121fc530842ba9a6d5dfec1ae1', 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + '26762d0425ffd15af9ddc3ae669373668827ea00', + Var('webrtc_git') + '/src.git' + '@' + 'f2dc05978f1dda877d811b81d1ee9cedb6d38be1', 'src/third_party/libgifcodec': Var('skia_git') + '/libgifcodec' + '@'+ Var('libgifcodec_revision'), @@ -1553,7 +1553,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@198da190b2a329168f2b86d8413cd0308f828d88', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@aca963f8ae300ae9658968d09ed2b8cd1f175e92', 'condition': 'checkout_src_internal', },
diff --git a/android_webview/tools/apk_merger.py b/android_webview/tools/apk_merger.py index 42b2379e..5acfc8a 100755 --- a/android_webview/tools/apk_merger.py +++ b/android_webview/tools/apk_merger.py
@@ -252,9 +252,9 @@ try: MergeApk(args, tmp_apk, tmp_dir_32, tmp_dir_64) - apksigner_path = os.path.join( - os.path.dirname(args.zipalign_path), 'apksigner') - finalize_apk.FinalizeApk(apksigner_path, args.zipalign_path, + apksigner_jar = os.path.join( + os.path.dirname(args.zipalign_path), 'lib', 'apksigner.jar') + finalize_apk.FinalizeApk(apksigner_jar, args.zipalign_path, tmp_apk, new_apk, args.keystore_path, args.key_password, args.key_name) finally:
diff --git a/ash/system/status_area_widget_delegate.cc b/ash/system/status_area_widget_delegate.cc index 87579a9..18468d6 100644 --- a/ash/system/status_area_widget_delegate.cc +++ b/ash/system/status_area_widget_delegate.cc
@@ -7,11 +7,11 @@ #include "ash/focus_cycler.h" #include "ash/root_window_controller.h" #include "ash/shelf/shelf.h" +#include "ash/shelf/shelf_layout_manager.h" #include "ash/shelf/shelf_widget.h" #include "ash/shell.h" #include "ash/system/status_area_widget.h" #include "ash/system/tray/tray_constants.h" -#include "ash/wm/tablet_mode/tablet_mode_controller.h" #include "chromeos/constants/chromeos_switches.h" #include "ui/compositor/layer.h" #include "ui/compositor/scoped_layer_animation_settings.h" @@ -86,6 +86,7 @@ set_owned_by_client(); // Deleted by DeleteDelegate(). ShelfConfig::Get()->AddObserver(this); + shelf_->shelf_layout_manager()->AddObserver(this); // Allow the launcher to surrender the focus to another window upon // navigation completion by the user. @@ -96,6 +97,7 @@ StatusAreaWidgetDelegate::~StatusAreaWidgetDelegate() { ShelfConfig::Get()->RemoveObserver(this); + shelf_->shelf_layout_manager()->RemoveObserver(this); } void StatusAreaWidgetDelegate::SetFocusCyclerForTesting( @@ -178,6 +180,21 @@ UpdateLayout(); } +void StatusAreaWidgetDelegate::OnHotseatStateChanged(HotseatState old_state, + HotseatState new_state) { + // Update the border of the last visible child so it has the right + // padding depending of the state of the shelf (See + // https://crbug.com/1025270). Don't layout as it will cause the whole + // transition to snap instead of animate (See https://crbug.com/1032770). + auto it = std::find_if(children().crbegin(), children().crend(), + [](const View* v) { return v->GetVisible(); }); + if (it == children().crend()) + return; + + View* last_visible_child = *it; + SetBorderOnChild(last_visible_child, /*is_child_on_edge=*/true); +} + void StatusAreaWidgetDelegate::UpdateLayout() { // Use a grid layout so that the trays can be centered in each cell, and // so that the widget gets laid out correctly when tray sizes change. @@ -257,13 +274,11 @@ // items also takes care of padding at the edge of the shelf. int right_edge = kPaddingBetweenWidgetsNewUi; - const bool tablet_mode = - Shell::Get()->tablet_mode_controller() && - Shell::Get()->tablet_mode_controller()->InTabletMode(); - - if (is_child_on_edge && !tablet_mode && - chromeos::switches::ShouldShowShelfHotseat()) { - right_edge = kPaddingBetweenWidgetAndRightScreenEdge; + if (is_child_on_edge && chromeos::switches::ShouldShowShelfHotseat()) { + right_edge = + shelf_->shelf_layout_manager()->hotseat_state() == HotseatState::kShown + ? kPaddingBetweenWidgetAndRightScreenEdge + : 0; } // Swap edges if alignment is not horizontal (bottom-to-top).
diff --git a/ash/system/status_area_widget_delegate.h b/ash/system/status_area_widget_delegate.h index f5f6779..16dc765 100644 --- a/ash/system/status_area_widget_delegate.h +++ b/ash/system/status_area_widget_delegate.h
@@ -8,6 +8,7 @@ #include "ash/ash_export.h" #include "ash/public/cpp/shelf_config.h" #include "ash/public/cpp/shelf_types.h" +#include "ash/shelf/shelf_layout_manager_observer.h" #include "ash/system/status_area_widget.h" #include "base/macros.h" #include "ui/gfx/image/image_skia.h" @@ -21,7 +22,8 @@ // The View for the status area widget. class ASH_EXPORT StatusAreaWidgetDelegate : public views::AccessiblePaneView, public views::WidgetDelegate, - public ShelfConfig::Observer { + public ShelfConfig::Observer, + public ShelfLayoutManagerObserver { public: explicit StatusAreaWidgetDelegate(Shelf* shelf); ~StatusAreaWidgetDelegate() override; @@ -59,6 +61,10 @@ // Overridden from ShelfConfig::Observer: void OnShelfConfigUpdated() override; + // ShelfLayoutManagerObserver: + void OnHotseatStateChanged(HotseatState old_state, + HotseatState new_state) override; + void set_default_last_focusable_child(bool default_last_focusable_child) { default_last_focusable_child_ = default_last_focusable_child; }
diff --git a/ash/wm/overview/overview_grid.cc b/ash/wm/overview/overview_grid.cc index 7077cc2f..0999dbc4 100644 --- a/ash/wm/overview/overview_grid.cc +++ b/ash/wm/overview/overview_grid.cc
@@ -44,7 +44,6 @@ #include "ash/wm/tablet_mode/tablet_mode_controller.h" #include "ash/wm/tablet_mode/tablet_mode_window_state.h" #include "ash/wm/window_util.h" -#include "ash/wm/work_area_insets.h" #include "ash/wm/workspace/backdrop_controller.h" #include "ash/wm/workspace/workspace_layout_manager.h" #include "ash/wm/workspace_controller.h" @@ -231,54 +230,6 @@ } } -// Returns the bounds for the overview window grid according to the split view -// state. If split view mode is active, the overview window should open on the -// opposite side of the default snap window. If |divider_changed| is true, maybe -// clamp the bounds to a minimum size and shift the bounds offscreen. -gfx::Rect GetGridBoundsInScreen(aura::Window* root_window, - bool divider_changed) { - const gfx::Rect work_area = - WorkAreaInsets::ForWindow(root_window)->ComputeStableWorkArea(); - SplitViewController* split_view_controller = - SplitViewController::Get(root_window); - if (!split_view_controller->InSplitViewMode()) - return work_area; - - SplitViewController::SnapPosition opposite_position = - (split_view_controller->default_snap_position() == - SplitViewController::LEFT) - ? SplitViewController::RIGHT - : SplitViewController::LEFT; - gfx::Rect bounds = split_view_controller->GetSnappedWindowBoundsInScreen( - opposite_position, /*window_for_minimum_size=*/nullptr); - if (!divider_changed) - return bounds; - - const bool horizontal = SplitViewController::IsLayoutHorizontal(); - const int min_length = - (horizontal ? work_area.width() : work_area.height()) / 3; - const int current_length = horizontal ? bounds.width() : bounds.height(); - - if (current_length > min_length) - return bounds; - - // Clamp bounds' length to the minimum length. - if (horizontal) - bounds.set_width(min_length); - else - bounds.set_height(min_length); - - if (SplitViewController::IsPhysicalLeftOrTop(opposite_position)) { - // If we are shifting to the left or top we need to update the origin as - // well. - const int offset = min_length - current_length; - bounds.Offset(horizontal ? gfx::Vector2d(-offset, 0) - : gfx::Vector2d(0, -offset)); - } - - return bounds; -} - gfx::Insets GetGridInsets(const gfx::Rect& grid_bounds) { const int horizontal_inset = gfx::ToFlooredInt(std::min(kOverviewInsetRatio * grid_bounds.width(), @@ -375,7 +326,7 @@ ShouldAllowSplitView() ? std::make_unique<SplitViewDragIndicators>(root_window) : nullptr), - bounds_(GetGridBoundsInScreen(root_window, /*divider_changed=*/false)) { + bounds_(GetGridBoundsInScreen(root_window)) { for (auto* window : windows) { if (window->GetRootWindow() != root_window) continue; @@ -646,12 +597,13 @@ overview_session_->window_drag_controller()->item()) { ignored_items.insert(overview_session_->window_drag_controller()->item()); } - const gfx::Rect grid_bounds = GetGridBoundsInScreenForSplitview( + const gfx::Rect grid_bounds = GetGridBoundsInScreen( root_window_, split_view_drag_indicators_ ? base::make_optional( split_view_drag_indicators_->current_window_dragging_state()) - : base::nullopt); + : base::nullopt, + /*divider_changed=*/false); SetBoundsAndUpdatePositions(grid_bounds, ignored_items, /*animate=*/true); } } @@ -712,8 +664,9 @@ } // Update the grid's bounds. - const gfx::Rect wanted_grid_bounds = GetGridBoundsInScreenForSplitview( - root_window_, base::make_optional(window_dragging_state)); + const gfx::Rect wanted_grid_bounds = GetGridBoundsInScreen( + root_window_, base::make_optional(window_dragging_state), + /*divider_changed=*/false); if (bounds_ != wanted_grid_bounds) { SetBoundsAndUpdatePositions(wanted_grid_bounds, {GetOverviewItemContaining(dragged_window)}, @@ -865,7 +818,7 @@ // Update the grid bounds and reposition windows. Since the grid bounds might // be updated based on the preview area during drag, but the window finally // didn't be snapped to the preview area. - SetBoundsAndUpdatePositions(GetGridBoundsInScreenForSplitview(root_window_), + SetBoundsAndUpdatePositions(GetGridBoundsInScreen(root_window_), /*ignored_items=*/{}, /*animate=*/true); } @@ -912,9 +865,8 @@ // updated in |OnSplitViewDividerPositionChanged|. if (SplitViewController::Get(root_window_)->InSplitViewMode()) return; - SetBoundsAndUpdatePositions( - GetGridBoundsInScreen(root_window_, /*divider_changed=*/false), - /*ignored_items=*/{}, /*animate=*/false); + SetBoundsAndUpdatePositions(GetGridBoundsInScreen(root_window_), + /*ignored_items=*/{}, /*animate=*/false); } void OverviewGrid::OnSplitViewStateChanged( @@ -952,9 +904,8 @@ // Update the cannot snap warnings and adjust the grid bounds. UpdateCannotSnapWarningVisibility(); - SetBoundsAndUpdatePositions( - GetGridBoundsInScreen(root_window_, /*divider_changed=*/false), - /*ignored_items=*/{}, /*animate=*/false); + SetBoundsAndUpdatePositions(GetGridBoundsInScreen(root_window_), + /*ignored_items=*/{}, /*animate=*/false); // Activate the overview focus window, to match the behavior of entering // overview mode in the beginning. @@ -962,9 +913,11 @@ } void OverviewGrid::OnSplitViewDividerPositionChanged() { - SetBoundsAndUpdatePositions(GetGridBoundsInScreen(root_window_, - /*divider_changed=*/true), - /*ignored_items=*/{}, /*animate=*/false); + SetBoundsAndUpdatePositions( + GetGridBoundsInScreen(root_window_, + /*window_dragging_state=*/base::nullopt, + /*divider_changed=*/true), + /*ignored_items=*/{}, /*animate=*/false); } void OverviewGrid::OnScreenCopiedBeforeRotation() {
diff --git a/ash/wm/overview/overview_grid_unittest.cc b/ash/wm/overview/overview_grid_unittest.cc index cc18049..028770c 100644 --- a/ash/wm/overview/overview_grid_unittest.cc +++ b/ash/wm/overview/overview_grid_unittest.cc
@@ -258,6 +258,9 @@ // Tests that only one window animates when entering overview from splitview // double snapped. +// TODO(sammiequon): The way this test is setup causes an unnatural state by +// calling |GetGridBoundsInScreen| with split view state both snapped. Find a +// way to re-enable this. TEST_F(OverviewGridTest, DISABLED_SnappedWindow) { auto window1 = CreateTestWindow(gfx::Rect(100, 100)); auto window2 = CreateTestWindow(gfx::Rect(100, 100));
diff --git a/ash/wm/overview/overview_utils.cc b/ash/wm/overview/overview_utils.cc index b71d54d8..e2451e1 100644 --- a/ash/wm/overview/overview_utils.cc +++ b/ash/wm/overview/overview_utils.cc
@@ -25,6 +25,7 @@ #include "ash/wm/window_state.h" #include "ash/wm/window_transient_descendant_iterator.h" #include "ash/wm/wm_event.h" +#include "ash/wm/work_area_insets.h" #include "base/no_destructor.h" #include "ui/aura/client/aura_constants.h" #include "ui/aura/window.h" @@ -222,12 +223,17 @@ } } -// Get the grid bounds if a window is snapped in splitview, or what they will be -// when snapped based on |target_root| and |indicator_state|. -gfx::Rect GetGridBoundsInScreenForSplitview( +gfx::Rect GetGridBoundsInScreen(aura::Window* target_root) { + return GetGridBoundsInScreen(target_root, + /*window_dragging_state=*/base::nullopt, + /*divider_changed=*/false); +} + +gfx::Rect GetGridBoundsInScreen( aura::Window* target_root, base::Optional<SplitViewDragIndicators::WindowDraggingState> - window_dragging_state) { + window_dragging_state, + bool divider_changed) { auto* split_view_controller = SplitViewController::Get(target_root); auto state = split_view_controller->state(); @@ -246,17 +252,58 @@ } } + gfx::Rect bounds; + gfx::Rect work_area = + WorkAreaInsets::ForWindow(target_root)->ComputeStableWorkArea(); + base::Optional<SplitViewController::SnapPosition> opposite_position = + base::nullopt; switch (state) { case SplitViewController::State::kLeftSnapped: - return split_view_controller->GetSnappedWindowBoundsInScreen( + bounds = split_view_controller->GetSnappedWindowBoundsInScreen( SplitViewController::RIGHT, /*window_for_minimum_size=*/nullptr); + opposite_position = base::make_optional(SplitViewController::RIGHT); + break; case SplitViewController::State::kRightSnapped: - return split_view_controller->GetSnappedWindowBoundsInScreen( + bounds = split_view_controller->GetSnappedWindowBoundsInScreen( SplitViewController::LEFT, /*window_for_minimum_size=*/nullptr); - default: - return screen_util:: - GetDisplayWorkAreaBoundsInScreenForActiveDeskContainer(target_root); + opposite_position = base::make_optional(SplitViewController::LEFT); + break; + case SplitViewController::State::kNoSnap: + bounds = work_area; + break; + case SplitViewController::State::kBothSnapped: + // When this function is called, SplitViewController should have already + // handled the state change. + NOTREACHED(); } + + if (!divider_changed) + return bounds; + + DCHECK(opposite_position); + const bool horizontal = SplitViewController::IsLayoutHorizontal(); + const int min_length = + (horizontal ? work_area.width() : work_area.height()) / 3; + const int current_length = horizontal ? bounds.width() : bounds.height(); + + if (current_length > min_length) + return bounds; + + // Clamp bounds' length to the minimum length. + if (horizontal) + bounds.set_width(min_length); + else + bounds.set_height(min_length); + + if (SplitViewController::IsPhysicalLeftOrTop(*opposite_position)) { + // If we are shifting to the left or top we need to update the origin as + // well. + const int offset = min_length - current_length; + bounds.Offset(horizontal ? gfx::Vector2d(-offset, 0) + : gfx::Vector2d(0, -offset)); + } + + return bounds; } base::Optional<gfx::RectF> GetSplitviewBoundsMaintainingAspectRatio( @@ -281,8 +328,9 @@ return base::nullopt; } - return base::make_optional(gfx::RectF(GetGridBoundsInScreenForSplitview( - root_window, base::make_optional(window_dragging_state)))); + return base::make_optional(gfx::RectF(GetGridBoundsInScreen( + root_window, base::make_optional(window_dragging_state), + /*divider_changed=*/false))); } bool ShouldUseTabletModeGridLayout() {
diff --git a/ash/wm/overview/overview_utils.h b/ash/wm/overview/overview_utils.h index 562fbda..893f04a 100644 --- a/ash/wm/overview/overview_utils.h +++ b/ash/wm/overview/overview_utils.h
@@ -83,11 +83,15 @@ void MaximizeIfSnapped(aura::Window* window); // Get the grid bounds if a window is snapped in splitview, or what they will be -// when snapped based on |target_root| and |indicator_state|. -gfx::Rect GetGridBoundsInScreenForSplitview( +// when snapped based on |target_root| and |indicator_state|. If +// |divider_changed| is true, maybe clamp the bounds to a minimum size and shift +// the bounds offscreen. +gfx::Rect GetGridBoundsInScreen(aura::Window* target_root); +gfx::Rect GetGridBoundsInScreen( aura::Window* target_root, base::Optional<SplitViewDragIndicators::WindowDraggingState> - window_dragging_state = base::nullopt); + window_dragging_state, + bool divider_changed); // Gets the bounds of a window if it were to be snapped or about to be snapped // in splitview. Returns nothing if we are not in tablet mode, or if we aren't
diff --git a/ash/wm/tablet_mode/tablet_mode_window_drag_delegate.cc b/ash/wm/tablet_mode/tablet_mode_window_drag_delegate.cc index 36ab0f1..6cd38ff1 100644 --- a/ash/wm/tablet_mode/tablet_mode_window_drag_delegate.cc +++ b/ash/wm/tablet_mode/tablet_mode_window_drag_delegate.cc
@@ -106,8 +106,7 @@ OverviewGrid* overview_grid = GetOverviewGrid(dragged_window_); if (overview_grid) { overview_grid->RemoveDropTarget(); - const gfx::Rect grid_bounds = - GetGridBoundsInScreenForSplitview(dragged_window_, base::nullopt); + const gfx::Rect grid_bounds = GetGridBoundsInScreen(dragged_window_); overview_grid->SetBoundsAndUpdatePositions( grid_bounds, /*ignored_items=*/{}, /*animate=*/true); }
diff --git a/build/android/gyp/apkbuilder.py b/build/android/gyp/apkbuilder.py index 280d5ce..0d9405b 100755 --- a/build/android/gyp/apkbuilder.py +++ b/build/android/gyp/apkbuilder.py
@@ -89,8 +89,8 @@ choices=['true', 'True', 'false', 'False'], help='Whether to uncompress native shared libraries. Argument must be ' 'a boolean value.') - parser.add_argument('--apksigner-path', - help='Path to the apksigner executable.') + parser.add_argument( + '--apksigner-jar', help='Path to the apksigner executable.') parser.add_argument('--zipalign-path', help='Path to the zipalign executable.') parser.add_argument('--key-path', @@ -112,11 +112,12 @@ options.secondary_native_libs = build_utils.ParseGnList( options.secondary_native_libs) - # --apksigner-path, --zipalign-path, --key-xxx arguments are + # --apksigner-jar, --zipalign-path, --key-xxx arguments are # required when building an APK, but not a bundle module. if options.format == 'apk': - required_args = ['apksigner_path', 'zipalign_path', 'key_path', - 'key_passwd', 'key_name'] + required_args = [ + 'apksigner_jar', 'zipalign_path', 'key_path', 'key_passwd', 'key_name' + ] for required in required_args: if not vars(options)[required]: raise Exception('Argument --%s is required for APKs.' % ( @@ -383,7 +384,7 @@ data=java_resource_jar.read(apk_path)) if options.format == 'apk': - finalize_apk.FinalizeApk(options.apksigner_path, options.zipalign_path, + finalize_apk.FinalizeApk(options.apksigner_jar, options.zipalign_path, f.name, f.name, options.key_path, options.key_passwd, options.key_name)
diff --git a/build/android/gyp/finalize_apk.py b/build/android/gyp/finalize_apk.py index 2440fe4..b6be025 100644 --- a/build/android/gyp/finalize_apk.py +++ b/build/android/gyp/finalize_apk.py
@@ -8,6 +8,8 @@ import subprocess import tempfile +from util import build_utils + def FinalizeApk(apksigner_path, zipalign_path, unsigned_apk_path, final_apk_path, key_path, key_passwd, key_name): @@ -19,14 +21,23 @@ zipalign_path, '-p', '-f', '4', unsigned_apk_path, staging_file.name]) subprocess.check_output([ - apksigner_path, 'sign', - '--in', staging_file.name, - '--out', staging_file.name, - '--ks', key_path, - '--ks-key-alias', key_name, - '--ks-pass', 'pass:' + key_passwd, + build_utils.JAVA_PATH, + '-jar', + apksigner_path, + 'sign', + '--in', + staging_file.name, + '--out', + staging_file.name, + '--ks', + key_path, + '--ks-key-alias', + key_name, + '--ks-pass', + 'pass:' + key_passwd, # Force SHA-1 (makes signing faster; insecure is fine for local builds). - '--min-sdk-version', '1', + '--min-sdk-version', + '1', ]) shutil.move(staging_file.name, final_apk_path) staging_file.delete = False
diff --git a/build/config/android/internal_rules.gni b/build/config/android/internal_rules.gni index ddde6c68..1e30826 100644 --- a/build/config/android/internal_rules.gni +++ b/build/config/android/internal_rules.gni
@@ -2577,7 +2577,7 @@ script = "//build/android/gyp/apkbuilder.py" depfile = "$target_gen_dir/$target_name.d" - _apksigner = "$android_sdk_build_tools/apksigner" + _apksigner = "$android_sdk_build_tools/lib/apksigner.jar" _zipalign = "$android_sdk_build_tools/zipalign" data_deps = [ "//tools/android/md5sum", @@ -2606,7 +2606,7 @@ rebase_path(depfile, root_build_dir), "--resource-apk=$_rebased_compiled_resources_path", "--output-apk=$_rebased_packaged_apk_path", - "--apksigner-path", + "--apksigner-jar", rebase_path(_apksigner, root_build_dir), "--zipalign-path", rebase_path(_zipalign, root_build_dir),
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1 index 36c61c4..ee91bb80 100644 --- a/build/fuchsia/linux.sdk.sha1 +++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@ -8892979714213714096 \ No newline at end of file +8892911758248661344 \ No newline at end of file
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1 index 89c374a..5433cae2 100644 --- a/build/fuchsia/mac.sdk.sha1 +++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@ -8892979713590755584 \ No newline at end of file +8892911759098097872 \ No newline at end of file
diff --git a/chrome/VERSION b/chrome/VERSION index 99f2afa..493dc084 100644 --- a/chrome/VERSION +++ b/chrome/VERSION
@@ -1,4 +1,4 @@ MAJOR=81 MINOR=0 -BUILD=4009 +BUILD=4010 PATCH=0
diff --git a/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceMediator.java b/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceMediator.java index 5d2bf16..a0d19511 100644 --- a/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceMediator.java +++ b/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceMediator.java
@@ -100,6 +100,8 @@ private StartSurface.StateObserver mStateObserver; @OverviewModeState private int mOverviewModeState; + @OverviewModeState + private int mPreviousOverviewModeState; private boolean mIsOmniboxFocused; @Nullable private TabModel mNormalTabModel; @@ -216,6 +218,7 @@ }; } mController.addOverviewModeObserver(this); + mPreviousOverviewModeState = OverviewModeState.NOT_SHOWN; mOverviewModeState = OverviewModeState.NOT_SHOWN; } @@ -239,12 +242,35 @@ return mController.overviewVisible(); } - @VisibleForTesting + @Override public void setOverviewState(@OverviewModeState int state) { - if (state == mOverviewModeState) return; + if (mPropertyModel == null || state == mOverviewModeState) return; + + // Cache previous state. + if (mOverviewModeState != OverviewModeState.NOT_SHOWN) { + mPreviousOverviewModeState = mOverviewModeState; + } mOverviewModeState = state; setOverviewStateInternal(); + + // Immediately transition from SHOWING to SHOWN state if overview is visible but state not + // SHOWN. + if (mPropertyModel.get(IS_SHOWING_OVERVIEW) + && mOverviewModeState != OverviewModeState.NOT_SHOWN) { + // Compute SHOWN state. + @OverviewModeState + int shownState = computeOverviewStateShown(); + + // Nothing to do here. + if (shownState == mOverviewModeState) return; + + // Cache previous state + mPreviousOverviewModeState = mOverviewModeState; + + mOverviewModeState = shownState; + setOverviewStateInternal(); + } notifyStateChange(); } @@ -269,7 +295,8 @@ setMVTilesVisibility(false); setFakeBoxVisibility(false); setSecondaryTasksSurfaceVisibility(true); - } else if (mOverviewModeState == OverviewModeState.SHOWN_TWO_PANES) { + + } else if (mOverviewModeState == OverviewModeState.SHOWN_TABSWITCHER_TWO_PANES) { RecordUserAction.record("StartSurface.TwoPanes"); String defaultOnUserActionString = mPropertyModel.get(IS_EXPLORE_SURFACE_VISIBLE) ? "ExploreSurface" @@ -287,7 +314,7 @@ .getDimensionPixelSize(R.dimen.ss_bottom_bar_height)); mPropertyModel.set(IS_BOTTOM_BAR_VISIBLE, !mIsIncognito); - } else if (mOverviewModeState == OverviewModeState.SHOWN_TASKS_ONLY) { + } else if (mOverviewModeState == OverviewModeState.SHOWN_TABSWITCHER_TASKS_ONLY) { RecordUserAction.record("StartSurface.TasksOnly"); setMVTilesVisibility(!mIsIncognito); setExploreSurfaceVisibility(false); @@ -296,7 +323,7 @@ if (mSecondaryTasksSurfaceController != null) setSecondaryTasksSurfaceVisibility(false); } - if (mOverviewModeState != OverviewModeState.NOT_SHOWN) { + if (isShownState(mOverviewModeState)) { setIncognitoModeDescriptionVisibility( mIsIncognito && mTabModelSelector.getModel(true).getCount() <= 0); } @@ -327,13 +354,15 @@ public void showOverview(boolean animate) { // TODO(crbug.com/982018): Animate the bottom bar together with the Tab Grid view. if (mPropertyModel != null) { - int state = computeOverviewStateShown(); // update incognito mIsIncognito = mTabModelSelector.isIncognitoSelected(); mPropertyModel.set(IS_INCOGNITO, mIsIncognito); - setOverviewState(state); + // set OverviewModeState + @OverviewModeState + int shownState = computeOverviewStateShown(); + setOverviewState(shownState); // Make sure FeedSurfaceCoordinator is built before the explore surface is showing by // default. @@ -357,13 +386,15 @@ if (mOverviewModeState == OverviewModeState.SHOWN_TABSWITCHER // Secondary tasks surface is used as the main surface in incognito mode. && !mIsIncognito) { - // TODO: differentiate between "more tabs" and tabswitcher - setOverviewState(OverviewModeState.SHOWN_HOMEPAGE); - return true; + // If we reached tabswitcher from HomePage. + if (mPreviousOverviewModeState == OverviewModeState.SHOWN_HOMEPAGE) { + setOverviewState(OverviewModeState.SHOWN_HOMEPAGE); + return true; + } } if (mPropertyModel != null && mPropertyModel.get(IS_EXPLORE_SURFACE_VISIBLE) - && mOverviewModeState == OverviewModeState.SHOWN_TWO_PANES) { + && mOverviewModeState == OverviewModeState.SHOWN_TABSWITCHER_TWO_PANES) { setExploreSurfaceVisibility(false); notifyStateChange(); return true; @@ -413,10 +444,10 @@ @Override public void finishedHiding() { + setOverviewState(OverviewModeState.NOT_SHOWN); for (StartSurface.OverviewModeObserver observer : mObservers) { observer.finishedHiding(); } - setOverviewState(OverviewModeState.NOT_SHOWN); } private void destroyFeedSurfaceCoordinator() { @@ -454,7 +485,7 @@ mPropertyModel.set(IS_EXPLORE_SURFACE_VISIBLE, isVisible); - if (mOverviewModeState == OverviewModeState.SHOWN_TWO_PANES) { + if (mOverviewModeState == OverviewModeState.SHOWN_TABSWITCHER_TWO_PANES) { // Update the 'BOTTOM_BAR_SELECTED_TAB_POSITION' property to reflect the change. This is // needed when clicking back button on the explore surface. mPropertyModel.set(BOTTOM_BAR_SELECTED_TAB_POSITION, isVisible ? 1 : 0); @@ -502,8 +533,8 @@ private boolean hasFakeSearchBox() { // No fake search box on the explore pane in two panes mode. if (mOverviewModeState == OverviewModeState.SHOWN_HOMEPAGE - || mOverviewModeState == OverviewModeState.SHOWN_TASKS_ONLY - || (mOverviewModeState == OverviewModeState.SHOWN_TWO_PANES + || mOverviewModeState == OverviewModeState.SHOWN_TABSWITCHER_TASKS_ONLY + || (mOverviewModeState == OverviewModeState.SHOWN_TABSWITCHER_TWO_PANES && !mPropertyModel.get(IS_EXPLORE_SURFACE_VISIBLE))) { return true; } @@ -516,7 +547,7 @@ if (mOverviewModeState == OverviewModeState.SHOWN_TABSWITCHER) return true; // Never show on explore pane. - if (mOverviewModeState == OverviewModeState.SHOWN_TWO_PANES + if (mOverviewModeState == OverviewModeState.SHOWN_TABSWITCHER_TWO_PANES && mPropertyModel.get(IS_EXPLORE_SURFACE_VISIBLE)) { return false; } @@ -569,10 +600,37 @@ } @OverviewModeState + private int computeOverviewStateShown() { - if (mSurfaceMode == SurfaceMode.SINGLE_PANE) return OverviewModeState.SHOWN_HOMEPAGE; - if (mSurfaceMode == SurfaceMode.TWO_PANES) return OverviewModeState.SHOWN_TWO_PANES; - if (mSurfaceMode == SurfaceMode.TASKS_ONLY) return OverviewModeState.SHOWN_TASKS_ONLY; + if (mSurfaceMode == SurfaceMode.SINGLE_PANE) { + if (mOverviewModeState == OverviewModeState.SHOWING_PREVIOUS) { + assert (isShownState(mPreviousOverviewModeState)); + return mPreviousOverviewModeState; + } else if (mOverviewModeState == OverviewModeState.SHOWING_START) { + return OverviewModeState.SHOWN_HOMEPAGE; + } else if (mOverviewModeState == OverviewModeState.SHOWING_TABSWITCHER) { + return OverviewModeState.SHOWN_TABSWITCHER; + } else if (mOverviewModeState == OverviewModeState.SHOWING_HOMEPAGE) { + return OverviewModeState.SHOWN_HOMEPAGE; + } else { + assert (isShownState(mOverviewModeState) + || mOverviewModeState == OverviewModeState.NOT_SHOWN); + return mOverviewModeState; + } + } + if (mSurfaceMode == SurfaceMode.TWO_PANES) { + return OverviewModeState.SHOWN_TABSWITCHER_TWO_PANES; + } + if (mSurfaceMode == SurfaceMode.TASKS_ONLY) { + return OverviewModeState.SHOWN_TABSWITCHER_TASKS_ONLY; + } return OverviewModeState.DISABLED; } + + private boolean isShownState(@OverviewModeState int state) { + return state == OverviewModeState.SHOWN_HOMEPAGE + || state == OverviewModeState.SHOWN_TABSWITCHER + || state == OverviewModeState.SHOWN_TABSWITCHER_TWO_PANES + || state == OverviewModeState.SHOWN_TABSWITCHER_TASKS_ONLY; + } }
diff --git a/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTest.java b/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTest.java index 811e49b6..c6b9b657 100644 --- a/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTest.java +++ b/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceTest.java
@@ -31,6 +31,7 @@ import org.chromium.base.test.util.Restriction; import org.chromium.chrome.browser.ChromeFeatureList; import org.chromium.chrome.browser.ChromeSwitches; +import org.chromium.chrome.browser.compositor.layouts.OverviewModeState; import org.chromium.chrome.browser.flags.FeatureUtilities; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.chrome.test.ChromeTabbedActivityTestRule; @@ -68,6 +69,12 @@ @CommandLineFlags.Add({BASE_PARAMS + "/tasksonly"}) public void testShowAndHideTasksOnlySurface() { TestThreadUtils.runOnUiThreadBlocking( + () + -> mActivityTestRule.getActivity() + .getStartSurface() + .getController() + .setOverviewState(OverviewModeState.SHOWING_TABSWITCHER)); + TestThreadUtils.runOnUiThreadBlocking( () -> mActivityTestRule.getActivity().getLayoutManager().showOverview(false)); assertTrue(mActivityTestRule.getActivity().getLayoutManager().overviewVisible()); @@ -89,6 +96,12 @@ @CommandLineFlags.Add({BASE_PARAMS + "/single"}) public void testShowAndHideSingleSurface() { TestThreadUtils.runOnUiThreadBlocking( + () + -> mActivityTestRule.getActivity() + .getStartSurface() + .getController() + .setOverviewState(OverviewModeState.SHOWING_HOMEPAGE)); + TestThreadUtils.runOnUiThreadBlocking( () -> mActivityTestRule.getActivity().getLayoutManager().showOverview(false)); assertTrue(mActivityTestRule.getActivity().getLayoutManager().overviewVisible()); @@ -136,6 +149,12 @@ @CommandLineFlags.Add({BASE_PARAMS + "/twopanes"}) public void testShowAndHideTwoPanesSurface() { TestThreadUtils.runOnUiThreadBlocking( + () + -> mActivityTestRule.getActivity() + .getStartSurface() + .getController() + .setOverviewState(OverviewModeState.SHOWING_TABSWITCHER)); + TestThreadUtils.runOnUiThreadBlocking( () -> mActivityTestRule.getActivity().getLayoutManager().showOverview(false)); assertTrue(mActivityTestRule.getActivity().getLayoutManager().overviewVisible());
diff --git a/chrome/android/features/start_surface/internal/junit/src/org/chromium/chrome/features/start_surface/StartSurfaceMediatorUnitTest.java b/chrome/android/features/start_surface/internal/junit/src/org/chromium/chrome/features/start_surface/StartSurfaceMediatorUnitTest.java index a737f32..6b5fdb5e 100644 --- a/chrome/android/features/start_surface/internal/junit/src/org/chromium/chrome/features/start_surface/StartSurfaceMediatorUnitTest.java +++ b/chrome/android/features/start_surface/internal/junit/src/org/chromium/chrome/features/start_surface/StartSurfaceMediatorUnitTest.java
@@ -169,7 +169,8 @@ mediator.showOverview(false); verify(mMainTabGridController).showOverview(eq(false)); verify(mFakeBoxDelegate).addUrlFocusChangeListener(mUrlFocusChangeListenerCaptor.capture()); - assertThat(mediator.getOverviewState(), equalTo(OverviewModeState.SHOWN_TASKS_ONLY)); + assertThat(mediator.getOverviewState(), + equalTo(OverviewModeState.SHOWN_TABSWITCHER_TASKS_ONLY)); assertThat(mPropertyModel.get(IS_INCOGNITO), equalTo(false)); assertThat(mPropertyModel.get(IS_VOICE_RECOGNITION_BUTTON_VISIBLE), equalTo(true)); assertThat(mPropertyModel.get(IS_EXPLORE_SURFACE_VISIBLE), equalTo(false)); @@ -216,7 +217,8 @@ mediator.showOverview(false); verify(mMainTabGridController).showOverview(eq(false)); verify(mFakeBoxDelegate).addUrlFocusChangeListener(mUrlFocusChangeListenerCaptor.capture()); - assertThat(mediator.getOverviewState(), equalTo(OverviewModeState.SHOWN_TWO_PANES)); + assertThat(mediator.getOverviewState(), + equalTo(OverviewModeState.SHOWN_TABSWITCHER_TWO_PANES)); assertThat(mPropertyModel.get(IS_INCOGNITO), equalTo(false)); assertThat(mPropertyModel.get(IS_VOICE_RECOGNITION_BUTTON_VISIBLE), equalTo(true)); assertThat(mPropertyModel.get(IS_EXPLORE_SURFACE_VISIBLE), equalTo(false)); @@ -341,6 +343,7 @@ StartSurfaceMediator mediator = createStartSurfaceMediator(SurfaceMode.SINGLE_PANE); doReturn(0).when(mNormalTabModel).getCount(); + mediator.setOverviewState(OverviewModeState.SHOWN_HOMEPAGE); mediator.showOverview(false); mediator.setOverviewState(OverviewModeState.SHOWN_HOMEPAGE); verify(mNormalTabModel).addObserver(mTabModelObserverCaptor.capture()); @@ -359,6 +362,7 @@ StartSurfaceMediator mediator = createStartSurfaceMediator(SurfaceMode.SINGLE_PANE); doReturn(2).when(mNormalTabModel).getCount(); + mediator.setOverviewState(OverviewModeState.SHOWING_HOMEPAGE); mediator.showOverview(false); mediator.setOverviewState(OverviewModeState.SHOWN_HOMEPAGE); verify(mNormalTabModel).addObserver(mTabModelObserverCaptor.capture()); @@ -386,8 +390,11 @@ StartSurfaceMediator mediator = createStartSurfaceMediator(SurfaceMode.SINGLE_PANE); doReturn(1).when(mNormalTabModel).getCount(); + mediator.setSecondaryTasksSurfacePropertyModel(mSecondaryTasksSurfacePropertyModel); + mediator.setOverviewState(OverviewModeState.SHOWING_HOMEPAGE); mediator.showOverview(false); + verify(mNormalTabModel).addObserver(mTabModelObserverCaptor.capture()); mediator.setOverviewState(OverviewModeState.SHOWN_HOMEPAGE); @@ -420,6 +427,7 @@ StartSurfaceMediator mediator = createStartSurfaceMediator(SurfaceMode.SINGLE_PANE); verify(mNormalTabModel, never()).addObserver(mTabModelObserverCaptor.capture()); + mediator.setOverviewState(OverviewModeState.SHOWING_HOMEPAGE); mediator.showOverview(false); verify(mNormalTabModel).addObserver(mTabModelObserverCaptor.capture()); @@ -439,6 +447,7 @@ verify(mTabModelSelector, never()).addObserver(mTabModelSelectorObserverCaptor.capture()); + mediator.setOverviewState(OverviewModeState.SHOWN_HOMEPAGE); mediator.showOverview(false); verify(mTabModelSelector).addObserver(mTabModelSelectorObserverCaptor.capture()); @@ -458,6 +467,7 @@ assertThat(mediator.getOverviewState(), equalTo(OverviewModeState.NOT_SHOWN)); doReturn(2).when(mNormalTabModel).getCount(); + mediator.setOverviewState(OverviewModeState.SHOWING_HOMEPAGE); mediator.showOverview(false); assertThat(mediator.getOverviewState(), equalTo(OverviewModeState.SHOWN_HOMEPAGE)); assertThat(mPropertyModel.get(IS_SHOWING_OVERVIEW), equalTo(true)); @@ -508,6 +518,7 @@ assertThat(mediator.getOverviewState(), equalTo(OverviewModeState.NOT_SHOWN)); doReturn(2).when(mNormalTabModel).getCount(); + mediator.setOverviewState(OverviewModeState.SHOWING_HOMEPAGE); mediator.showOverview(false); assertThat(mediator.getOverviewState(), equalTo(OverviewModeState.SHOWN_HOMEPAGE)); assertThat(mPropertyModel.get(IS_SHOWING_OVERVIEW), equalTo(true)); @@ -566,7 +577,8 @@ assertThat(mediator.getOverviewState(), equalTo(OverviewModeState.NOT_SHOWN)); mediator.showOverview(false); - assertThat(mediator.getOverviewState(), equalTo(OverviewModeState.SHOWN_TASKS_ONLY)); + assertThat(mediator.getOverviewState(), + equalTo(OverviewModeState.SHOWN_TABSWITCHER_TASKS_ONLY)); assertThat(mPropertyModel.get(IS_SHOWING_OVERVIEW), equalTo(true)); assertThat(mPropertyModel.get(IS_INCOGNITO), equalTo(true)); assertThat(mPropertyModel.get(IS_EXPLORE_SURFACE_VISIBLE), equalTo(false)); @@ -588,6 +600,7 @@ assertThat(mediator.getOverviewState(), equalTo(OverviewModeState.NOT_SHOWN)); doReturn(2).when(mNormalTabModel).getCount(); + mediator.setOverviewState(OverviewModeState.SHOWING_HOMEPAGE); mediator.showOverview(false); verify(mTabModelSelector).addObserver(mTabModelSelectorObserverCaptor.capture()); assertThat(mediator.getOverviewState(), equalTo(OverviewModeState.SHOWN_HOMEPAGE)); @@ -646,7 +659,8 @@ mediator.showOverview(false); verify(mTabModelSelector).addObserver(mTabModelSelectorObserverCaptor.capture()); - assertThat(mediator.getOverviewState(), equalTo(OverviewModeState.SHOWN_TASKS_ONLY)); + assertThat(mediator.getOverviewState(), + equalTo(OverviewModeState.SHOWN_TABSWITCHER_TASKS_ONLY)); assertThat(mPropertyModel.get(IS_SHOWING_OVERVIEW), equalTo(true)); assertThat(mPropertyModel.get(IS_INCOGNITO), equalTo(false)); assertThat(mPropertyModel.get(IS_EXPLORE_SURFACE_VISIBLE), equalTo(false)); @@ -659,7 +673,8 @@ mTabModelSelectorObserverCaptor.getValue().onTabModelSelected( mIncognitoTabModel, mNormalTabModel); - assertThat(mediator.getOverviewState(), equalTo(OverviewModeState.SHOWN_TASKS_ONLY)); + assertThat(mediator.getOverviewState(), + equalTo(OverviewModeState.SHOWN_TABSWITCHER_TASKS_ONLY)); assertThat(mPropertyModel.get(IS_SHOWING_OVERVIEW), equalTo(true)); assertThat(mPropertyModel.get(IS_INCOGNITO), equalTo(true)); assertThat(mPropertyModel.get(IS_EXPLORE_SURFACE_VISIBLE), equalTo(false)); @@ -672,7 +687,8 @@ mTabModelSelectorObserverCaptor.getValue().onTabModelSelected( mNormalTabModel, mIncognitoTabModel); - assertThat(mediator.getOverviewState(), equalTo(OverviewModeState.SHOWN_TASKS_ONLY)); + assertThat(mediator.getOverviewState(), + equalTo(OverviewModeState.SHOWN_TABSWITCHER_TASKS_ONLY)); assertThat(mPropertyModel.get(IS_SHOWING_OVERVIEW), equalTo(true)); assertThat(mPropertyModel.get(IS_INCOGNITO), equalTo(false)); assertThat(mPropertyModel.get(IS_EXPLORE_SURFACE_VISIBLE), equalTo(false)); @@ -695,6 +711,7 @@ assertThat(mediator.getOverviewState(), equalTo(OverviewModeState.NOT_SHOWN)); doReturn(2).when(mNormalTabModel).getCount(); + mediator.setOverviewState(OverviewModeState.SHOWING_HOMEPAGE); mediator.showOverview(false); verify(mTabModelSelector).addObserver(mTabModelSelectorObserverCaptor.capture()); assertThat(mediator.getOverviewState(), equalTo(OverviewModeState.SHOWN_HOMEPAGE)); @@ -731,6 +748,7 @@ doReturn(30).when(mChromeFullscreenManager).getBottomControlsHeight(); doReturn(2).when(mNormalTabModel).getCount(); + mediator.setOverviewState(OverviewModeState.SHOWING_HOMEPAGE); mediator.showOverview(false); assertThat(mPropertyModel.get(BOTTOM_BAR_HEIGHT), equalTo(30)); assertThat(mSecondaryTasksSurfacePropertyModel.get(BOTTOM_BAR_HEIGHT), equalTo(0)); @@ -820,6 +838,7 @@ doReturn(true).when(mLocationBarVoiceRecognitionHandler).isVoiceSearchEnabled(); StartSurfaceMediator mediator = createStartSurfaceMediator(SurfaceMode.SINGLE_PANE); + mediator.setOverviewState(OverviewModeState.SHOWING_HOMEPAGE); mediator.showOverview(false); verify(mTabModelSelector).addObserver(mTabModelSelectorObserverCaptor.capture()); @@ -858,6 +877,7 @@ doReturn(true).when(mLocationBarVoiceRecognitionHandler).isVoiceSearchEnabled(); StartSurfaceMediator mediator = createStartSurfaceMediator(SurfaceMode.SINGLE_PANE); + mediator.setOverviewState(OverviewModeState.SHOWN_HOMEPAGE); mediator.showOverview(false); verify(mTabModelSelector).addObserver(mTabModelSelectorObserverCaptor.capture()); @@ -953,7 +973,7 @@ assertThat(mediator.getOverviewState(), equalTo(OverviewModeState.NOT_SHOWN)); mediator.setSecondaryTasksSurfacePropertyModel(mSecondaryTasksSurfacePropertyModel); - + mediator.setOverviewState(OverviewModeState.SHOWING_HOMEPAGE); mediator.showOverview(false); verify(mMainTabGridController).showOverview(eq(false)); verify(mFakeBoxDelegate).addUrlFocusChangeListener(mUrlFocusChangeListenerCaptor.capture());
diff --git a/chrome/android/features/start_surface/public/java/src/org/chromium/chrome/features/start_surface/StartSurface.java b/chrome/android/features/start_surface/public/java/src/org/chromium/chrome/features/start_surface/StartSurface.java index 3ff3f80..322470ea 100644 --- a/chrome/android/features/start_surface/public/java/src/org/chromium/chrome/features/start_surface/StartSurface.java +++ b/chrome/android/features/start_surface/public/java/src/org/chromium/chrome/features/start_surface/StartSurface.java
@@ -100,6 +100,12 @@ void showOverview(boolean animate); /** + * Sets the state {@link OverviewModeState}. + * @param state the {@link OverviewModeState} to show. + */ + void setOverviewState(@OverviewModeState int state); + + /** * Called by the TabSwitcherLayout when the system back button is pressed. * @return Whether or not the TabSwitcher consumed the event. */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java index 3c85f725..ea59c4eb 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
@@ -692,7 +692,11 @@ } } - toggleOverview(); + if (isInOverviewMode() && !FeatureUtilities.isGridTabSwitcherEnabled()) { + hideOverview(); + } else { + showOverview(OverviewModeState.SHOWING_TABSWITCHER); + } }; OnClickListener newTabClickHandler = v -> { getTabModelSelector().getModel(false).commitAllTabClosures(); @@ -711,10 +715,20 @@ }; OnClickListener bookmarkClickHandler = v -> addOrEditBookmark(getActivityTab()); + Supplier<Boolean> showStartSurfaceSupplier = () -> { + if (ReturnToChromeExperimentsUtil.shouldShowStartSurfaceAsTheHomePage() + && !isTablet()) { + assert ReturnToChromeExperimentsUtil.shouldShowStartSurfaceAsTheHomePage(); + showOverview(OverviewModeState.SHOWING_HOMEPAGE); + return true; + } + return false; + }; + getToolbarManager().initializeWithNative(mTabModelSelectorImpl, getFullscreenManager().getBrowserVisibilityDelegate(), mOverviewModeController, mLayoutManager, tabSwitcherClickHandler, newTabClickHandler, - bookmarkClickHandler, null); + bookmarkClickHandler, null, showStartSurfaceSupplier); mLayoutManager.setToolbarManager(getToolbarManager()); @@ -999,12 +1013,12 @@ mStartSurface.getController().enableRecordingFirstMeaningfulPaint( getOnCreateTimestampMs()); } - toggleOverview(); + showOverview(OverviewModeState.SHOWING_START); return; } if (getActivityTab() == null && !isOverviewVisible) { - toggleOverview(); + showOverview(OverviewModeState.SHOWING_START); } } @@ -1853,7 +1867,7 @@ // the tab and go back to the start surface. if (type == TabLaunchType.FROM_START_SURFACE) { getCurrentTabModel().closeTab(currentTab); - toggleOverview(); + showOverview(OverviewModeState.SHOWING_PREVIOUS); return true; } @@ -2024,29 +2038,37 @@ } } - private void toggleOverview() { + private void showOverview(@OverviewModeState int state) { + assert (state == OverviewModeState.SHOWING_TABSWITCHER + || state == OverviewModeState.SHOWING_HOMEPAGE + || state == OverviewModeState.SHOWING_PREVIOUS + || state == OverviewModeState.SHOWING_START); + if (mStartSurface != null) mStartSurface.getController().setOverviewState(state); + + if (mOverviewModeController.overviewVisible()) return; + Tab currentTab = getActivityTab(); // If we don't have a current tab, show the overview mode. if (currentTab == null) { mOverviewModeController.showOverview(false); - return; - } - - if (!mOverviewModeController.overviewVisible()) { + } else { getCompositorViewHolder().hideKeyboard( () -> mOverviewModeController.showOverview(true)); updateAccessibilityState(false); TasksUma.recordTabLaunchType(getCurrentTabModel()); - } else { - Layout activeLayout = mLayoutManager.getActiveLayout(); - if (activeLayout instanceof StackLayout) { - ((StackLayout) activeLayout).commitOutstandingModelState(LayoutManager.time()); - } - if (getCurrentTabModel().getCount() != 0) { - // Don't hide overview if current tab stack is empty() - mOverviewModeController.hideOverview(true); - updateAccessibilityState(true); - } + } + } + + private void hideOverview() { + assert (mOverviewModeController.overviewVisible()); + Layout activeLayout = mLayoutManager.getActiveLayout(); + if (activeLayout instanceof StackLayout) { + ((StackLayout) activeLayout).commitOutstandingModelState(LayoutManager.time()); + } + if (getCurrentTabModel().getCount() != 0) { + // Don't hide overview if current tab stack is empty() + mOverviewModeController.hideOverview(true); + updateAccessibilityState(true); } } @@ -2216,6 +2238,11 @@ return getLayoutManager().getOverviewListLayout(); } + @VisibleForTesting + public StartSurface getStartSurface() { + return mStartSurface; + } + private ComposedBrowserControlsVisibilityDelegate getAppBrowserControlsVisibilityDelegate() { if (mAppBrowserControlsVisibilityDelegate == null) { mAppBrowserControlsVisibilityDelegate = new ComposedBrowserControlsVisibilityDelegate();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkUtils.java index e1b1ac4..0a73d06e 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkUtils.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkUtils.java
@@ -8,7 +8,6 @@ import android.content.ComponentName; import android.content.Context; import android.content.Intent; -import android.content.SharedPreferences; import android.net.Uri; import android.provider.Browser; import android.text.TextUtils; @@ -16,7 +15,6 @@ import androidx.annotation.VisibleForTesting; import org.chromium.base.BuildInfo; -import org.chromium.base.ContextUtils; import org.chromium.base.Log; import org.chromium.base.ThreadUtils; import org.chromium.base.metrics.RecordHistogram; @@ -27,6 +25,8 @@ import org.chromium.chrome.browser.IntentHandler; import org.chromium.chrome.browser.bookmarks.BookmarkBridge.BookmarkItem; import org.chromium.chrome.browser.document.ChromeLauncherActivity; +import org.chromium.chrome.browser.preferences.ChromePreferenceKeys; +import org.chromium.chrome.browser.preferences.SharedPreferencesManager; import org.chromium.chrome.browser.snackbar.Snackbar; import org.chromium.chrome.browser.snackbar.SnackbarManager; import org.chromium.chrome.browser.snackbar.SnackbarManager.SnackbarController; @@ -44,8 +44,6 @@ * A class holding static util functions for bookmark. */ public class BookmarkUtils { - private static final String PREF_LAST_USED_URL = "enhanced_bookmark_last_used_url"; - private static final String PREF_LAST_USED_PARENT = "enhanced_bookmark_last_used_parent_folder"; private static final String TAG = "BookmarkUtils"; /** @@ -200,8 +198,8 @@ * {@link #getLastUsedUrl(Context)} */ static void setLastUsedUrl(Context context, String url) { - ContextUtils.getAppSharedPreferences().edit() - .putString(PREF_LAST_USED_URL, url).apply(); + SharedPreferencesManager.getInstance().writeString( + ChromePreferenceKeys.BOOKMARKS_LAST_USED_URL, url); } /** @@ -209,16 +207,16 @@ */ @VisibleForTesting static String getLastUsedUrl(Context context) { - return ContextUtils.getAppSharedPreferences().getString( - PREF_LAST_USED_URL, UrlConstants.BOOKMARKS_URL); + return SharedPreferencesManager.getInstance().readString( + ChromePreferenceKeys.BOOKMARKS_LAST_USED_URL, UrlConstants.BOOKMARKS_URL); } /** * Save the last used {@link BookmarkId} as a folder to put new bookmarks to. */ static void setLastUsedParent(Context context, BookmarkId bookmarkId) { - ContextUtils.getAppSharedPreferences().edit() - .putString(PREF_LAST_USED_PARENT, bookmarkId.toString()).apply(); + SharedPreferencesManager.getInstance().writeString( + ChromePreferenceKeys.BOOKMARKS_LAST_USED_PARENT, bookmarkId.toString()); } /** @@ -226,11 +224,11 @@ * has never selected a parent folder to use. */ static BookmarkId getLastUsedParent(Context context) { - SharedPreferences preferences = ContextUtils.getAppSharedPreferences(); - if (!preferences.contains(PREF_LAST_USED_PARENT)) return null; + SharedPreferencesManager preferences = SharedPreferencesManager.getInstance(); + if (!preferences.contains(ChromePreferenceKeys.BOOKMARKS_LAST_USED_PARENT)) return null; return BookmarkId.getBookmarkIdFromString( - preferences.getString(PREF_LAST_USED_PARENT, null)); + preferences.readString(ChromePreferenceKeys.BOOKMARKS_LAST_USED_PARENT, null)); } /** Starts an {@link BookmarkEditActivity} for the given {@link BookmarkId}. */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/OverviewModeState.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/OverviewModeState.java index 2284810e..fe352d6 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/OverviewModeState.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/OverviewModeState.java
@@ -14,13 +14,26 @@ * OverviewModeBehavior.OverviewModeObserver}. */ @IntDef({OverviewModeState.NOT_SHOWN, OverviewModeState.SHOWN_HOMEPAGE, - OverviewModeState.SHOWN_TABSWITCHER, OverviewModeState.DISABLED}) + OverviewModeState.SHOWN_TABSWITCHER, OverviewModeState.SHOWN_TABSWITCHER_TWO_PANES, + OverviewModeState.SHOWN_TABSWITCHER_TASKS_ONLY, OverviewModeState.DISABLED, + OverviewModeState.SHOWING_TABSWITCHER, OverviewModeState.SHOWING_START, + OverviewModeState.SHOWING_HOMEPAGE, OverviewModeState.SHOWING_PREVIOUS}) @Retention(RetentionPolicy.SOURCE) public @interface OverviewModeState { int NOT_SHOWN = 0; + + // When overview is visible, it will be in one of the SHOWN states. int SHOWN_HOMEPAGE = 1; int SHOWN_TABSWITCHER = 2; - int SHOWN_TWO_PANES = 3; - int SHOWN_TASKS_ONLY = 4; + int SHOWN_TABSWITCHER_TWO_PANES = 3; + int SHOWN_TABSWITCHER_TASKS_ONLY = 4; + int DISABLED = 5; + + // SHOWING states are intermediary states that will immediately transition + // to one of the SHOWN states when overview is/becomes visible. + int SHOWING_TABSWITCHER = 6; + int SHOWING_START = 7; + int SHOWING_HOMEPAGE = 8; + int SHOWING_PREVIOUS = 9; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/features/toolbar/CustomTabToolbarCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/features/toolbar/CustomTabToolbarCoordinator.java index 31883c0d..711a0bc 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/features/toolbar/CustomTabToolbarCoordinator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/features/toolbar/CustomTabToolbarCoordinator.java
@@ -173,7 +173,7 @@ private void onCompositorContentInitialized(LayoutManager layoutDriver) { mToolbarManager.initializeWithNative(mTabController.getTabModelSelector(), mFullscreenManager.get().getBrowserVisibilityDelegate(), null, layoutDriver, null, - null, null, v -> onCloseButtonClick()); + null, null, v -> onCloseButtonClick(), null); mInitializedToolbarWithNative = true; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/flags/FeatureUtilities.java b/chrome/android/java/src/org/chromium/chrome/browser/flags/FeatureUtilities.java index 12abf76..012624c 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/flags/FeatureUtilities.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/flags/FeatureUtilities.java
@@ -403,6 +403,11 @@ private static void cacheStartSurfaceEnabled() { cacheFlag(ChromePreferenceKeys.FLAGS_CACHED_START_SURFACE_ENABLED, ChromeFeatureList.START_SURFACE_ANDROID); + String feature = ChromeFeatureList.getFieldTrialParamByFeature( + ChromeFeatureList.START_SURFACE_ANDROID, "start_surface_variation"); + SharedPreferencesManager.getInstance().writeBoolean( + ChromePreferenceKeys.START_SURFACE_SINGLE_PANE_ENABLED_KEY, + feature.equals("single")); } /** @@ -421,6 +426,14 @@ } } + /** + * @return Whether the Start Surface SinglePane is enabled. + */ + public static boolean isStartSurfaceSinglePaneEnabled() { + return isStartSurfaceEnabled() + && isFlagEnabled(ChromePreferenceKeys.START_SURFACE_SINGLE_PANE_ENABLED_KEY, false); + } + @VisibleForTesting static void cacheGridTabSwitcherEnabled() { SharedPreferencesManager sharedPreferencesManager = SharedPreferencesManager.getInstance();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tasks/ReturnToChromeExperimentsUtil.java b/chrome/android/java/src/org/chromium/chrome/browser/tasks/ReturnToChromeExperimentsUtil.java index db993e17..3e6001a 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tasks/ReturnToChromeExperimentsUtil.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tasks/ReturnToChromeExperimentsUtil.java
@@ -5,6 +5,7 @@ package org.chromium.chrome.browser.tasks; import android.app.Activity; +import android.text.TextUtils; import androidx.annotation.VisibleForTesting; @@ -16,6 +17,8 @@ import org.chromium.chrome.browser.ChromeFeatureList; import org.chromium.chrome.browser.flags.FeatureUtilities; import org.chromium.chrome.browser.locale.LocaleManager; +import org.chromium.chrome.browser.ntp.NewTabPage; +import org.chromium.chrome.browser.partnercustomizations.HomepageManager; import org.chromium.chrome.browser.tab.TabLaunchType; import org.chromium.chrome.browser.tabmodel.TabModel; import org.chromium.content_public.browser.LoadUrlParams; @@ -171,4 +174,16 @@ return chromeActivity; } + + /** + * Check whether we should show Start Surface as the home page. + * @return Whether Start Surface should be shown as the home page, otherwise false. + */ + public static boolean shouldShowStartSurfaceAsTheHomePage() { + // Note that we should only show StartSurface as the HomePage if Single Pane is enabled and + // HomePage is not customized. + String homePageUrl = HomepageManager.getHomepageUri(); + return FeatureUtilities.isStartSurfaceSinglePaneEnabled() + && (TextUtils.isEmpty(homePageUrl) || NewTabPage.isNTPUrl(homePageUrl)); + } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java index 883e4616..b743cb0 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
@@ -30,6 +30,7 @@ import org.chromium.base.MathUtils; import org.chromium.base.ObservableSupplier; import org.chromium.base.ObservableSupplierImpl; +import org.chromium.base.Supplier; import org.chromium.base.metrics.CachedMetrics.ActionEvent; import org.chromium.base.metrics.RecordHistogram; import org.chromium.base.metrics.RecordUserAction; @@ -249,6 +250,9 @@ private int mCurrentOrientation; + /** Runnable for the home button when Start Surface home page is enabled. */ + private Supplier<Boolean> mShowStartSurfaceSupplier; + /** * Creates a ToolbarManager object. * @@ -980,11 +984,14 @@ BrowserStateBrowserControlsVisibilityDelegate controlsVisibilityDelegate, OverviewModeBehavior overviewModeBehavior, LayoutManager layoutManager, OnClickListener tabSwitcherClickHandler, OnClickListener newTabClickHandler, - OnClickListener bookmarkClickHandler, OnClickListener customTabsBackClickHandler) { + OnClickListener bookmarkClickHandler, OnClickListener customTabsBackClickHandler, + Supplier<Boolean> showStartSurfaceSupplier) { assert !mInitializedWithNative; mTabModelSelector = tabModelSelector; + mShowStartSurfaceSupplier = showStartSurfaceSupplier; + OnLongClickListener tabSwitcherLongClickHandler = null; if (mTabGroupPopupUi != null) { @@ -1562,6 +1569,9 @@ RecordUserAction.record("MobileTopToolbarHomeButton"); } + if (mShowStartSurfaceSupplier.get()) { + return; + } Tab currentTab = mLocationBarModel.getTab(); if (currentTab == null) return; String homePageUrl = HomepageManager.getHomepageUri();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomToolbarCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomToolbarCoordinator.java index 7b26423..26ce4afc 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomToolbarCoordinator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/bottom/BottomToolbarCoordinator.java
@@ -16,6 +16,7 @@ import org.chromium.chrome.browser.ThemeColorProvider; import org.chromium.chrome.browser.compositor.layouts.OverviewModeBehavior; import org.chromium.chrome.browser.compositor.layouts.OverviewModeBehavior.OverviewModeObserver; +import org.chromium.chrome.browser.tasks.ReturnToChromeExperimentsUtil; import org.chromium.chrome.browser.toolbar.IncognitoStateProvider; import org.chromium.chrome.browser.toolbar.MenuButton; import org.chromium.chrome.browser.toolbar.TabCountProvider; @@ -94,11 +95,15 @@ mTabSwitcherModeCoordinator = new TabSwitcherBottomToolbarCoordinator(mTabSwitcherModeStub, topToolbarRoot, incognitoStateProvider, mThemeColorProvider, newTabClickListener, closeTabsClickListener, menuButtonHelper, tabCountProvider); - mOverviewModeBehavior = overviewModeBehavior; - mOverviewModeObserver = new BottomToolbarAnimationCoordinator( - mBrowsingModeCoordinator, mTabSwitcherModeCoordinator); - if (mOverviewModeBehavior != null) { - mOverviewModeBehavior.addOverviewModeObserver(mOverviewModeObserver); + // Do not change bottom bar if StartSurface Single Pane is enabled and HomePage is not + // customized. + if (!ReturnToChromeExperimentsUtil.shouldShowStartSurfaceAsTheHomePage()) { + mOverviewModeBehavior = overviewModeBehavior; + mOverviewModeObserver = new BottomToolbarAnimationCoordinator( + mBrowsingModeCoordinator, mTabSwitcherModeCoordinator); + if (mOverviewModeBehavior != null) { + mOverviewModeBehavior.addOverviewModeObserver(mOverviewModeObserver); + } } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarPhone.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarPhone.java index 9427eae..f9134e0b 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarPhone.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarPhone.java
@@ -1657,7 +1657,8 @@ if (mHomeButton == null) return; boolean hideHomeButton = !mIsHomeButtonEnabled || mIsBottomToolbarVisible - || FeatureUtilities.isStartSurfaceEnabled(); + || (FeatureUtilities.isStartSurfaceEnabled() + && !FeatureUtilities.isStartSurfaceSinglePaneEnabled()); if (hideHomeButton) { removeHomeButton(); } else {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninTest.java index 5b9f9815..d4a4060 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/SigninTest.java
@@ -4,8 +4,14 @@ package org.chromium.chrome.browser.signin; +import static android.support.test.espresso.Espresso.onView; +import static android.support.test.espresso.action.ViewActions.click; +import static android.support.test.espresso.matcher.RootMatchers.isDialog; +import static android.support.test.espresso.matcher.ViewMatchers.withId; + +import static org.hamcrest.Matchers.sameInstance; + import android.app.Instrumentation.ActivityMonitor; -import android.content.Context; import android.content.DialogInterface; import android.support.test.InstrumentationRegistry; import android.support.test.filters.MediumTest; @@ -28,7 +34,6 @@ import org.chromium.base.test.util.Restriction; import org.chromium.chrome.R; import org.chromium.chrome.browser.ChromeSwitches; -import org.chromium.chrome.browser.SyncFirstSetupCompleteSource; import org.chromium.chrome.browser.bookmarks.BookmarkBridge; import org.chromium.chrome.browser.preferences.Pref; import org.chromium.chrome.browser.preferences.PrefServiceBridge; @@ -37,18 +42,17 @@ import org.chromium.chrome.browser.settings.SettingsActivity; import org.chromium.chrome.browser.settings.sync.AccountManagementFragment; import org.chromium.chrome.browser.settings.sync.SignInPreference; -import org.chromium.chrome.browser.sync.ProfileSyncService; import org.chromium.chrome.browser.tab.TabImpl; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.chrome.test.ChromeTabbedActivityTestRule; import org.chromium.chrome.test.util.ActivityUtils; +import org.chromium.chrome.test.util.BookmarkTestUtil; import org.chromium.chrome.test.util.ChromeRestriction; import org.chromium.chrome.test.util.browser.signin.SigninTestUtil; import org.chromium.components.bookmarks.BookmarkId; import org.chromium.components.signin.ChromeSigninController; import org.chromium.components.signin.metrics.SignoutReason; import org.chromium.content_public.browser.test.util.TestThreadUtils; -import org.chromium.content_public.browser.test.util.TestTouchUtils; /** * Test suite for sign in tests. @@ -150,27 +154,13 @@ */ private static class TestBookmarkModelObserver extends BookmarkBridge.BookmarkModelObserver { private final Object mLock = new Object(); - private boolean mIsLoaded; private boolean mAdded; - public TestBookmarkModelObserver(BookmarkBridge bookmarks) { - mIsLoaded = bookmarks.isBookmarkModelLoaded(); + TestBookmarkModelObserver() { mAdded = false; } - public void waitForBookmarkModelToLoad() { - synchronized (mLock) { - while (!mIsLoaded) { - try { - mLock.wait(); - } catch (InterruptedException exception) { - // Ignore. - } - } - } - } - - public void waitForBookmarkAdded() { + void waitForBookmarkAdded() { synchronized (mLock) { while (!mAdded) { try { @@ -183,14 +173,6 @@ } @Override - public void bookmarkModelLoaded() { - synchronized (mLock) { - mIsLoaded = true; - mLock.notify(); - } - } - - @Override public void bookmarkNodeAdded(BookmarkBridge.BookmarkItem parent, int index) { synchronized (mLock) { mAdded = true; @@ -211,7 +193,6 @@ } } - private Context mContext; private SigninManager mSigninManager; private PrefServiceBridge mPrefService; private BookmarkBridge mBookmarks; @@ -224,7 +205,6 @@ SigninTestUtil.setUpAuthForTest(); mActivityTestRule.startMainActivityOnBlankPage(); - mContext = InstrumentationRegistry.getTargetContext(); final TestSignInAllowedObserver signinAllowedObserver = new TestSignInAllowedObserver(); TestThreadUtils.runOnUiThreadBlocking(() -> { @@ -241,11 +221,13 @@ Profile profile = ((TabImpl) mActivityTestRule.getActivity().getActivityTab()).getProfile(); mBookmarks = new BookmarkBridge(profile); - + mBookmarks.loadFakePartnerBookmarkShimForTesting(); + }); + BookmarkTestUtil.waitForBookmarkModelLoaded(); + TestThreadUtils.runOnUiThreadBlocking(() -> { // Add a test bookmark, to verify later if sign out cleared the bookmarks. - mTestBookmarkModelObserver = new TestBookmarkModelObserver(mBookmarks); + mTestBookmarkModelObserver = new TestBookmarkModelObserver(); mBookmarks.addObserver(mTestBookmarkModelObserver); - mTestBookmarkModelObserver.waitForBookmarkModelToLoad(); Assert.assertEquals(0, mBookmarks.getChildCount(mBookmarks.getMobileFolderId())); BookmarkId mTestBookmark = mBookmarks.addBookmark( mBookmarks.getMobileFolderId(), 0, "Test Bookmark", "http://google.com"); @@ -335,22 +317,8 @@ SigninActivity signinActivity = (SigninActivity) InstrumentationRegistry.getInstrumentation().waitForMonitor( monitor); - Button positiveButton = (Button) signinActivity.findViewById(R.id.positive_button); - // Press 'sign in'. - TestTouchUtils.performClickOnMainSync( - InstrumentationRegistry.getInstrumentation(), positiveButton); + onView(withId(R.id.positive_button)).perform(click()); InstrumentationRegistry.getInstrumentation().waitForIdleSync(); - // Press 'ok, got it' (the same button is reused). - TestTouchUtils.performClickOnMainSync( - InstrumentationRegistry.getInstrumentation(), positiveButton); - - // Sync doesn't actually start up until we finish the sync setup. This usually happens - // in the resume of the Main activity, but we forcefully do this here. - InstrumentationRegistry.getInstrumentation().waitForIdleSync(); - TestThreadUtils.runOnUiThreadBlocking( - () - -> ProfileSyncService.get().setFirstSetupComplete( - SyncFirstSetupCompleteSource.BASIC_FLOW)); settingsActivity.finish(); // Verify that signin succeeded. @@ -417,10 +385,10 @@ InstrumentationRegistry.getInstrumentation().waitForIdleSync(); DialogFragment fragment = ActivityUtils.waitForFragment(activity, tag); AlertDialog dialog = (AlertDialog) fragment.getDialog(); - Assert.assertTrue(dialog != null); + Assert.assertNotNull(dialog); Assert.assertTrue(dialog.isShowing()); Button button = dialog.getButton(DialogInterface.BUTTON_POSITIVE); Assert.assertNotNull("Could not find the accept button.", button); - TestTouchUtils.performClickOnMainSync(InstrumentationRegistry.getInstrumentation(), button); + onView(sameInstance(button)).inRoot(isDialog()).perform(click()); } }
diff --git a/chrome/android/profiles/newest.txt b/chrome/android/profiles/newest.txt index d95d01a..72673c6 100644 --- a/chrome/android/profiles/newest.txt +++ b/chrome/android/profiles/newest.txt
@@ -1 +1 @@ -chromeos-chrome-amd64-81.0.4005.0_rc-r1-merged.afdo.bz2 \ No newline at end of file +chromeos-chrome-amd64-81.0.4008.0_rc-r1-merged.afdo.bz2 \ No newline at end of file
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index e632e05..1c12092 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd
@@ -3720,15 +3720,9 @@ <message name="IDS_EXTENSION_ALERT_TITLE" desc="Titlebar of the extension notification alert"> Confirm Changes </message> - <message name="IDS_EXTENSION_ALERT_ITEM_EXTERNAL" desc="A statement that an external extension has been newly installed. End users have no idea what an 'external' extension is, so we simply call them extensions."> - The extension "<ph name="EXTENSION_NAME">$1<ex>Gmail Checker</ex></ph>" has been added. - </message> <message name="IDS_EXTENSION_ALERT_ITEM_BLACKLISTED" desc="A statement that an extension has been newly blacklisted. https://support.google.com/chrome/answer/1210215 contains the language on which we're basing the phrasing."> The extension "<ph name="EXTENSION_NAME">$1<ex>Gmail Checker</ex></ph>" was automatically disabled. </message> - <message name="IDS_APP_ALERT_ITEM_EXTERNAL" desc="A statement that an external packaged app has been newly installed. End users have no idea what an 'external' app is, so we simply call them apps."> - The app "<ph name="EXTENSION_NAME">$1<ex>Gmail</ex></ph>" has been added. - </message> <message name="IDS_APP_ALERT_ITEM_BLACKLISTED" desc="A statement that a packaged app has been newly blacklisted. https://support.google.com/chrome/answer/1210215 contains the language on which we're basing the phrasing."> The app "<ph name="EXTENSION_NAME">$1<ex>Gmail</ex></ph>" was automatically removed. </message>
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 6a1724b..24265cfd 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -2261,18 +2261,12 @@ {"webxr-ar-module", flag_descriptions::kWebXrArModuleName, flag_descriptions::kWebXrArModuleDescription, kOsAll, FEATURE_VALUE_TYPE(features::kWebXrArModule)}, - {"webxr-ar-dom-overlay", flag_descriptions::kWebXrArDOMOverlayName, - flag_descriptions::kWebXrArDOMOverlayDescription, kOsAndroid, - FEATURE_VALUE_TYPE(features::kWebXrArDOMOverlay)}, {"webxr-hit-test", flag_descriptions::kWebXrHitTestName, flag_descriptions::kWebXrHitTestDescription, kOsAll, FEATURE_VALUE_TYPE(features::kWebXrHitTest)}, - {"webxr-anchors", flag_descriptions::kWebXrAnchorsName, - flag_descriptions::kWebXrAnchorsDescription, kOsAll, - FEATURE_VALUE_TYPE(features::kWebXrAnchors)}, - {"webxr-plane-detection", flag_descriptions::kWebXrPlaneDetectionName, - flag_descriptions::kWebXrPlaneDetectionDescription, kOsAll, - FEATURE_VALUE_TYPE(features::kWebXrPlaneDetection)}, + {"webxr-incubations", flag_descriptions::kWebXrIncubationsName, + flag_descriptions::kWebXrIncubationsDescription, kOsAll, + FEATURE_VALUE_TYPE(features::kWebXrIncubations)}, {"webxr-orientation-sensor-device", flag_descriptions::kWebXrOrientationSensorDeviceName, flag_descriptions::kWebXrOrientationSensorDeviceDescription, kOsDesktop,
diff --git a/chrome/browser/chromeos/login/reset_browsertest.cc b/chrome/browser/chromeos/login/reset_browsertest.cc index eae7352..9e7bc9f 100644 --- a/chrome/browser/chromeos/login/reset_browsertest.cc +++ b/chrome/browser/chromeos/login/reset_browsertest.cc
@@ -449,12 +449,9 @@ } // TODO(http://crbug.com/990362): Times out on MSAN buildbots. -#if defined(MEMORY_SANITIZER) -#define MAYBE_RollbackAvailable DISABLED_RollbackAvailable -#else -#define MAYBE_RollbackAvailable RollbackAvailable -#endif -IN_PROC_BROWSER_TEST_F(ResetFirstAfterBootTestWithRollback, RollbackAvailable) { +// TODO(http://crbug.com/990362): Flaky failures. +IN_PROC_BROWSER_TEST_F(ResetFirstAfterBootTestWithRollback, + DISABLED_RollbackAvailable) { PrefService* prefs = g_browser_process->local_state(); // PRE test triggers start with Reset screen. @@ -553,13 +550,9 @@ } // TODO(http://crbug.com/1025926): Times out on MSAN buildbots. -#if defined(MEMORY_SANITIZER) -#define MAYBE_RevertAfterCancel DISABLED_RevertAfterCancel -#else -#define MAYBE_RevertAfterCancel RevertAfterCancel -#endif +// TODO(http://crbug.com/990362): Flaky failures. IN_PROC_BROWSER_TEST_F(ResetFirstAfterBootTestWithRollback, - MAYBE_RevertAfterCancel) { + DISABLED_RevertAfterCancel) { OobeScreenWaiter(ResetView::kScreenId).Wait(); EXPECT_TRUE(login_prompt_visible_observer_->signal_emitted());
diff --git a/chrome/browser/download/download_browsertest.cc b/chrome/browser/download/download_browsertest.cc index b5b4f12..c1e9516f 100644 --- a/chrome/browser/download/download_browsertest.cc +++ b/chrome/browser/download/download_browsertest.cc
@@ -827,7 +827,7 @@ : embedded_test_server()->GetURL( content::SlowDownloadHttpResponse::kUnknownSizeUrl)); GURL finish_url = embedded_test_server()->GetURL( - content::SlowDownloadHttpResponse::kFinishDownloadUrl); + content::SlowDownloadHttpResponse::kFinishSlowResponseUrl); // TODO(ahendrickson) -- |expected_title_in_progress| and // |expected_title_finished| need to be checked. @@ -876,8 +876,9 @@ return false; // Check the file contents. - size_t file_size = content::SlowDownloadHttpResponse::kFirstDownloadSize + - content::SlowDownloadHttpResponse::kSecondDownloadSize; + size_t file_size = + content::SlowDownloadHttpResponse::kFirstResponsePartSize + + content::SlowDownloadHttpResponse::kSecondResponsePartSize; std::string expected_contents(file_size, '*'); EXPECT_TRUE(VerifyFile(download_path, expected_contents, file_size)); @@ -2077,7 +2078,7 @@ // Finsih the download. GURL finish_url = embedded_test_server()->GetURL( - content::SlowDownloadHttpResponse::kFinishDownloadUrl); + content::SlowDownloadHttpResponse::kFinishSlowResponseUrl); ui_test_utils::NavigateToURL(browser(), finish_url); download_observer->WaitForFinished(); @@ -2107,8 +2108,8 @@ EXPECT_GE(end, row1.end_time); EXPECT_EQ(0, row1.received_bytes); // There's no ETag. So the intermediate // state is discarded. - EXPECT_EQ(content::SlowDownloadHttpResponse::kFirstDownloadSize + - content::SlowDownloadHttpResponse::kSecondDownloadSize, + EXPECT_EQ(content::SlowDownloadHttpResponse::kFirstResponsePartSize + + content::SlowDownloadHttpResponse::kSecondResponsePartSize, row1.total_bytes); EXPECT_EQ(history::DownloadState::INTERRUPTED, row1.state); EXPECT_EQ(history::ToHistoryDownloadInterruptReason(
diff --git a/chrome/browser/extensions/api/extension_action/browser_action_apitest.cc b/chrome/browser/extensions/api/extension_action/browser_action_apitest.cc index 850eeb2a..a0a030c 100644 --- a/chrome/browser/extensions/api/extension_action/browser_action_apitest.cc +++ b/chrome/browser/extensions/api/extension_action/browser_action_apitest.cc
@@ -769,9 +769,11 @@ } IN_PROC_BROWSER_TEST_F(BrowserActionApiTest, CloseBackgroundPage) { + ExtensionTestMessageListener listener("ready", /*will_reply=*/false); ASSERT_TRUE(LoadExtension( test_data_dir_.AppendASCII("browser_action/close_background"))); const Extension* extension = GetSingleLoadedExtension(); + ASSERT_TRUE(listener.WaitUntilSatisfied()); // There is a background page and a browser action with no badge text. extensions::ProcessManager* manager =
diff --git a/chrome/browser/extensions/api_binding_perf_browsertest.cc b/chrome/browser/extensions/api_binding_perf_browsertest.cc index f2ae95c3..d542b49 100644 --- a/chrome/browser/extensions/api_binding_perf_browsertest.cc +++ b/chrome/browser/extensions/api_binding_perf_browsertest.cc
@@ -47,19 +47,19 @@ DISALLOW_COPY_AND_ASSIGN(APIBindingPerfBrowserTest); }; -const char kSimpleContentScriptManifest[] = - "{" - " 'name': 'Perf test extension'," - " 'version': '0'," - " 'manifest_version': 2," - " 'content_scripts': [ {" - " 'all_frames': true," - " 'matches': [ '<all_urls>' ]," - " 'run_at': 'document_end'," - " 'js': [ 'content_script.js' ]" - " } ]," - " 'permissions': [ 'storage' ]" - "}"; +constexpr char kSimpleContentScriptManifest[] = + R"({ + "name": "Perf test extension", + "version": "0", + "manifest_version": 2, + "content_scripts": [ { + "all_frames": true, + "matches": [ "<all_urls>" ], + "run_at": "document_end", + "js": [ "content_script.js" ] + } ], + "permissions": [ "storage" ] + })"; IN_PROC_BROWSER_TEST_F(APIBindingPerfBrowserTest, LOCAL_TEST(ManyFramesWithNoContentScript)) { @@ -74,7 +74,7 @@ IN_PROC_BROWSER_TEST_F(APIBindingPerfBrowserTest, LOCAL_TEST(ManyFramesWithEmptyContentScript)) { TestExtensionDir extension_dir; - extension_dir.WriteManifestWithSingleQuotes(kSimpleContentScriptManifest); + extension_dir.WriteManifest(kSimpleContentScriptManifest); extension_dir.WriteFile(FILE_PATH_LITERAL("content_script.js"), "// This space intentionally left blank."); ASSERT_TRUE(LoadExtension(extension_dir.UnpackedPath())); @@ -90,7 +90,7 @@ IN_PROC_BROWSER_TEST_F(APIBindingPerfBrowserTest, LOCAL_TEST(ManyFramesWithStorageAndRuntime)) { TestExtensionDir extension_dir; - extension_dir.WriteManifestWithSingleQuotes(kSimpleContentScriptManifest); + extension_dir.WriteManifest(kSimpleContentScriptManifest); extension_dir.WriteFile(FILE_PATH_LITERAL("content_script.js"), "chrome.storage.onChanged.addListener;" "chrome.runtime.onMessage.addListener;");
diff --git a/chrome/browser/extensions/cross_origin_read_blocking_browsertest.cc b/chrome/browser/extensions/cross_origin_read_blocking_browsertest.cc index 4b1a657..a8aef05f 100644 --- a/chrome/browser/extensions/cross_origin_read_blocking_browsertest.cc +++ b/chrome/browser/extensions/cross_origin_read_blocking_browsertest.cc
@@ -38,6 +38,7 @@ #include "net/test/embedded_test_server/embedded_test_server.h" #include "net/test/embedded_test_server/http_request.h" #include "services/network/cross_origin_read_blocking.h" +#include "services/network/public/cpp/features.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "url/gurl.h" @@ -45,6 +46,15 @@ namespace extensions { +namespace { + +enum TestParam { + kAllowlisted = 1 << 0, + kOutOfBlinkCors = 1 << 1, +}; + +} // namespace + using CORBAction = network::CrossOriginReadBlocking::Action; class CrossOriginReadBlockingExtensionTest : public ExtensionBrowserTest { @@ -342,21 +352,28 @@ DISALLOW_COPY_AND_ASSIGN(CrossOriginReadBlockingExtensionTest); }; -enum class AllowlistingParam { - kAllowlisted, - kNotAllowlisted, -}; - class CrossOriginReadBlockingExtensionAllowlistingTest : public CrossOriginReadBlockingExtensionTest, - public ::testing::WithParamInterface<AllowlistingParam> { + public ::testing::WithParamInterface<TestParam> { public: using Base = CrossOriginReadBlockingExtensionTest; - CrossOriginReadBlockingExtensionAllowlistingTest() {} + CrossOriginReadBlockingExtensionAllowlistingTest() { + if (IsOutOfBlinkCorsEnabled()) { + scoped_feature_list_.InitAndEnableFeature( + network::features::kOutOfBlinkCors); + } else { + scoped_feature_list_.InitAndDisableFeature( + network::features::kOutOfBlinkCors); + } + } bool IsExtensionAllowlisted() { - return GetParam() == AllowlistingParam::kAllowlisted; + return (GetParam() & TestParam::kAllowlisted) != 0; + } + + bool IsOutOfBlinkCorsEnabled() { + return (GetParam() & TestParam::kOutOfBlinkCors) != 0; } const Extension* InstallExtension( @@ -439,6 +456,8 @@ } private: + base::test::ScopedFeatureList scoped_feature_list_; + DISALLOW_COPY_AND_ASSIGN(CrossOriginReadBlockingExtensionAllowlistingTest); }; @@ -501,8 +520,8 @@ } // Test that verifies the current, baked-in (but not necessarily desirable -// behavior) where an extension that has permission to inject a content script -// to any page can also fetch (without CORS!) any cross-origin resource. +// behavior) where a content script injected by an extension can bypass +// CORS (and CORB) for any hosts the extension has access to. // See also https://crbug.com/846346. IN_PROC_BROWSER_TEST_P(CrossOriginReadBlockingExtensionAllowlistingTest, FromProgrammaticContentScript_NoSniffXml) { @@ -531,6 +550,40 @@ "nosniff.xml - body\n"); } +// Test that verifies the current, baked-in (but not necessarily desirable +// behavior) where a content script injected by an extension can bypass +// CORS (and CORB) for any hosts the extension has access to. +// See also https://crbug.com/1034408 and https://crbug.com/846346. +IN_PROC_BROWSER_TEST_P(CrossOriginReadBlockingExtensionAllowlistingTest, + FromProgrammaticContentScript_RedirectToNoSniffXml) { + ASSERT_TRUE(embedded_test_server()->Start()); + ASSERT_TRUE(InstallExtension()); + + // Navigate to a fetch-initiator.com page. + GURL page_url = GetTestPageUrl("fetch-initiator.com"); + ui_test_utils::NavigateToURL(browser(), page_url); + ASSERT_EQ(page_url, + active_web_contents()->GetMainFrame()->GetLastCommittedURL()); + ASSERT_EQ(url::Origin::Create(page_url), + active_web_contents()->GetMainFrame()->GetLastCommittedOrigin()); + + // Inject a content script that performs a cross-origin fetch to + // cross-site.com. + base::HistogramTester histograms; + GURL cross_site_resource( + embedded_test_server()->GetURL("cross-site.com", "/nosniff.xml")); + GURL redirecting_url(embedded_test_server()->GetURL( + "other-with-permission.com", + std::string("/server-redirect?") + cross_site_resource.spec())); + std::string fetch_result = + FetchViaContentScript(redirecting_url, active_web_contents()); + + // Verify whether the fetch worked or not (expectations differ depending on + // various factors - see the body of VerifyFetchFromContentScript). + VerifyFetchFromContentScript(histograms, fetch_result, + "nosniff.xml - body\n"); +} + // Test that verifies CORS-allowed fetches work for targets that are not // covered by the extension permissions. IN_PROC_BROWSER_TEST_P(CrossOriginReadBlockingExtensionAllowlistingTest, @@ -1368,11 +1421,18 @@ EXPECT_EQ("cors-allowed-body", fetch_result); } -INSTANTIATE_TEST_SUITE_P(Allowlisted, +INSTANTIATE_TEST_SUITE_P(Allowlisted_OorCors, CrossOriginReadBlockingExtensionAllowlistingTest, - ::testing::Values(AllowlistingParam::kAllowlisted)); -INSTANTIATE_TEST_SUITE_P(NotAllowlisted, + ::testing::Values(TestParam::kAllowlisted | + TestParam::kOutOfBlinkCors)); +INSTANTIATE_TEST_SUITE_P(NotAllowlisted_OorCors, CrossOriginReadBlockingExtensionAllowlistingTest, - ::testing::Values(AllowlistingParam::kNotAllowlisted)); + ::testing::Values(TestParam::kOutOfBlinkCors)); +INSTANTIATE_TEST_SUITE_P(Allowlisted_InBlinkCors, + CrossOriginReadBlockingExtensionAllowlistingTest, + ::testing::Values(TestParam::kAllowlisted)); +INSTANTIATE_TEST_SUITE_P(NotAllowlisted_InBlinkCors, + CrossOriginReadBlockingExtensionAllowlistingTest, + ::testing::Values(0)); } // namespace extensions
diff --git a/chrome/browser/extensions/extension_error_controller.cc b/chrome/browser/extensions/extension_error_controller.cc index e080397..f676b80 100644 --- a/chrome/browser/extensions/extension_error_controller.cc +++ b/chrome/browser/extensions/extension_error_controller.cc
@@ -62,10 +62,6 @@ return browser_context_; } -const ExtensionSet& ExtensionErrorController::GetExternalExtensions() { - return external_extensions_; -} - const ExtensionSet& ExtensionErrorController::GetBlacklistedExtensions() { return blacklisted_extensions_; }
diff --git a/chrome/browser/extensions/extension_error_controller.h b/chrome/browser/extensions/extension_error_controller.h index 356f6652..53e3af4 100644 --- a/chrome/browser/extensions/extension_error_controller.h +++ b/chrome/browser/extensions/extension_error_controller.h
@@ -35,7 +35,6 @@ private: // ExtensionErrorUI::Delegate implementation: content::BrowserContext* GetContext() override; - const ExtensionSet& GetExternalExtensions() override; const ExtensionSet& GetBlacklistedExtensions() override; void OnAlertDetails() override; void OnAlertAccept() override; @@ -45,10 +44,6 @@ // extensions). void IdentifyAlertableExtensions(); - // TODO(rdevlin.cronin): We never seem to use |external_extensions_| here, - // but we do warn about them. Investigate more. - ExtensionSet external_extensions_; - // The extensions that are blacklisted and need user approval. ExtensionSet blacklisted_extensions_;
diff --git a/chrome/browser/extensions/extension_error_ui.h b/chrome/browser/extensions/extension_error_ui.h index 1ade18ed..e9872d9 100644 --- a/chrome/browser/extensions/extension_error_ui.h +++ b/chrome/browser/extensions/extension_error_ui.h
@@ -27,9 +27,6 @@ // Get the BrowserContext associated with this UI. virtual content::BrowserContext* GetContext() = 0; - // Get the set of external extensions to warn the user about. - virtual const ExtensionSet& GetExternalExtensions() = 0; - // Get the set of blacklisted extensions to warn the user about. virtual const ExtensionSet& GetBlacklistedExtensions() = 0;
diff --git a/chrome/browser/extensions/extension_error_ui_default.cc b/chrome/browser/extensions/extension_error_ui_default.cc index 984955ca..14ed11c 100644 --- a/chrome/browser/extensions/extension_error_ui_default.cc +++ b/chrome/browser/extensions/extension_error_ui_default.cc
@@ -6,38 +6,29 @@ #include "base/logging.h" #include "base/strings/string_util.h" -#include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_finder.h" #include "chrome/browser/ui/chrome_pages.h" #include "chrome/browser/ui/global_error/global_error_bubble_view_base.h" #include "chrome/grit/generated_resources.h" +#include "extensions/common/extension.h" +#include "extensions/common/extension_set.h" #include "ui/base/l10n/l10n_util.h" namespace extensions { namespace { -std::vector<base::string16> GenerateMessage(const ExtensionSet& external, - const ExtensionSet& forbidden) { - std::vector<base::string16> message(external.size() + forbidden.size()); - auto it = std::transform( - external.begin(), external.end(), message.begin(), - [](const auto& extension) { - int id = extension->is_app() ? IDS_APP_ALERT_ITEM_EXTERNAL - : IDS_EXTENSION_ALERT_ITEM_EXTERNAL; - base::string16 name = base::UTF8ToUTF16(extension->name()); - return l10n_util::GetStringFUTF16(id, name); - }); - std::transform(forbidden.begin(), forbidden.end(), it, - [](const auto& extension) { - int id = extension->is_app() - ? IDS_APP_ALERT_ITEM_BLACKLISTED - : IDS_EXTENSION_ALERT_ITEM_BLACKLISTED; - base::string16 name = base::UTF8ToUTF16(extension->name()); - return l10n_util::GetStringFUTF16(id, name); - }); +std::vector<base::string16> GenerateMessage(const ExtensionSet& forbidden) { + std::vector<base::string16> message; + message.reserve(forbidden.size()); + for (const auto& extension : forbidden) { + int id = extension->is_app() ? IDS_APP_ALERT_ITEM_BLACKLISTED + : IDS_EXTENSION_ALERT_ITEM_BLACKLISTED; + message.push_back( + l10n_util::GetStringFUTF16(id, base::UTF8ToUTF16(extension->name()))); + } return message; } @@ -69,8 +60,7 @@ } std::vector<base::string16> GetBubbleViewMessages() override { - return GenerateMessage(delegate_->GetExternalExtensions(), - delegate_->GetBlacklistedExtensions()); + return GenerateMessage(delegate_->GetBlacklistedExtensions()); } base::string16 GetBubbleViewAcceptButtonLabel() override {
diff --git a/chrome/browser/extensions/extension_error_ui_default.h b/chrome/browser/extensions/extension_error_ui_default.h index b790948..b7abcf4 100644 --- a/chrome/browser/extensions/extension_error_ui_default.h +++ b/chrome/browser/extensions/extension_error_ui_default.h
@@ -5,11 +5,11 @@ #ifndef CHROME_BROWSER_EXTENSIONS_EXTENSION_ERROR_UI_DEFAULT_H_ #define CHROME_BROWSER_EXTENSIONS_EXTENSION_ERROR_UI_DEFAULT_H_ -#include "base/compiler_specific.h" +#include <memory> + #include "base/macros.h" #include "chrome/browser/extensions/extension_error_ui.h" #include "chrome/browser/ui/global_error/global_error.h" -#include "extensions/common/extension.h" class Browser; class Profile;
diff --git a/chrome/browser/extensions/extension_error_ui_default_unittest.cc b/chrome/browser/extensions/extension_error_ui_default_unittest.cc index 2494f90..5c53b3b4 100644 --- a/chrome/browser/extensions/extension_error_ui_default_unittest.cc +++ b/chrome/browser/extensions/extension_error_ui_default_unittest.cc
@@ -17,9 +17,6 @@ public: // extensions::ExtensionErrorUI::Delegate: content::BrowserContext* GetContext() override { return &profile_; } - const extensions::ExtensionSet& GetExternalExtensions() override { - return external_; - } const extensions::ExtensionSet& GetBlacklistedExtensions() override { return forbidden_; } @@ -27,10 +24,6 @@ void OnAlertAccept() override {} void OnAlertClosed() override {} - void InsertExternal(scoped_refptr<const extensions::Extension> ext) { - external_.Insert(ext); - } - void InsertForbidden(scoped_refptr<const extensions::Extension> ext) { forbidden_.Insert(ext); } @@ -38,7 +31,6 @@ private: content::BrowserTaskEnvironment environment_; TestingProfile profile_; - extensions::ExtensionSet external_; extensions::ExtensionSet forbidden_; }; @@ -52,7 +44,6 @@ TEST(ExtensionErrorUIDefaultTest, BubbleMessageMentionsExtension) { TestErrorUIDelegate delegate; - delegate.InsertExternal(extensions::ExtensionBuilder("Foo").Build()); delegate.InsertForbidden(extensions::ExtensionBuilder("Bar").Build()); delegate.InsertForbidden(extensions::ExtensionBuilder("Baz").Build()); @@ -61,8 +52,7 @@ std::vector<base::string16> messages = bubble->GetBubbleViewMessages(); - ASSERT_EQ(3U, messages.size()); - EXPECT_TRUE(ContainsString(messages[0], "\"Foo\"")); - EXPECT_TRUE(ContainsString(messages[1], "\"Bar\"")); - EXPECT_TRUE(ContainsString(messages[2], "\"Baz\"")); + ASSERT_EQ(2u, messages.size()); + EXPECT_TRUE(ContainsString(messages[0], "\"Bar\"")); + EXPECT_TRUE(ContainsString(messages[1], "\"Baz\"")); }
diff --git a/chrome/browser/extensions/extension_keybinding_apitest.cc b/chrome/browser/extensions/extension_keybinding_apitest.cc index c8055b18..697a0fa 100644 --- a/chrome/browser/extensions/extension_keybinding_apitest.cc +++ b/chrome/browser/extensions/extension_keybinding_apitest.cc
@@ -24,6 +24,7 @@ #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/browser/ui/toolbar/toolbar_actions_bar.h" #include "chrome/browser/ui/toolbar/toolbar_actions_model.h" +#include "chrome/browser/ui/ui_features.h" #include "chrome/test/base/interactive_test_utils.h" #include "chrome/test/base/ui_test_utils.h" #include "content/public/browser/notification_service.h" @@ -355,6 +356,41 @@ SendKeyPressToAction(browser(), *extension, ui::VKEY_F, expect_dispatch); } +// Tests that a page action that is overflowed will still properly trigger when +// the keybinding is used. +IN_PROC_BROWSER_TEST_F(CommandsApiTest, OverflowedPageActionTriggers) { + base::AutoReset<bool> disable_toolbar_animations( + &ToolbarActionsBar::disable_animations_for_testing_, true); + + ASSERT_TRUE(embedded_test_server()->Start()); + ASSERT_TRUE(RunExtensionTest("keybinding/page_action")) << message_; + const Extension* extension = GetSingleLoadedExtension(); + ASSERT_TRUE(extension) << message_; + + // With the old toolbar, we need to explicitly overflow the extension. + if (!base::FeatureList::IsEnabled(features::kExtensionsToolbarMenu)) { + ToolbarActionsModel* toolbar_actions_model = + ToolbarActionsModel::Get(profile()); + toolbar_actions_model->SetVisibleIconCount(0); + } + std::unique_ptr<BrowserActionTestUtil> test_helper = + BrowserActionTestUtil::Create(browser()); + EXPECT_EQ(0, test_helper->VisibleBrowserActions()); + + ui_test_utils::NavigateToURL( + browser(), embedded_test_server()->GetURL("/extensions/test_file.txt")); + const int tab_id = SessionTabHelper::FromWebContents( + browser()->tab_strip_model()->GetActiveWebContents()) + ->session_id() + .id(); + SetActionVisibleOnTab(profile(), *extension, tab_id); + + ASSERT_TRUE(WaitForPageActionVisibilityChangeTo(1)); + + constexpr bool kExpectDispatch = true; + SendKeyPressToAction(browser(), *extension, ui::VKEY_F, kExpectDispatch); +} + IN_PROC_BROWSER_TEST_F(CommandsApiTest, PageActionKeyUpdated) { ASSERT_TRUE(embedded_test_server()->Start()); ASSERT_TRUE(RunExtensionTest("keybinding/page_action")) << message_;
diff --git a/chrome/browser/extensions/extension_loading_browsertest.cc b/chrome/browser/extensions/extension_loading_browsertest.cc index f8b5967..fc01c37 100644 --- a/chrome/browser/extensions/extension_loading_browsertest.cc +++ b/chrome/browser/extensions/extension_loading_browsertest.cc
@@ -44,22 +44,21 @@ ASSERT_TRUE(embedded_test_server()->Start()); TestExtensionDir extension_dir; - const char kManifestTemplate[] = - "{" - " 'name': 'Overrides New Tab'," - " 'version': '%d'," - " 'description': 'Overrides New Tab'," - " 'manifest_version': 2," - " 'background': {" - " 'persistent': false," - " 'scripts': ['event.js']" - " }," - " 'chrome_url_overrides': {" - " 'newtab': 'newtab.html'" - " }" - "}"; - extension_dir.WriteManifestWithSingleQuotes( - base::StringPrintf(kManifestTemplate, 1)); + constexpr char kManifestTemplate[] = + R"({ + "name": "Overrides New Tab", + "version": "%d", + "description": "Overrides New Tab", + "manifest_version": 2, + "background": { + "persistent": false, + "scripts": ["event.js"] + }, + "chrome_url_overrides": { + "newtab": "newtab.html" + } + })"; + extension_dir.WriteManifest(base::StringPrintf(kManifestTemplate, 1)); extension_dir.WriteFile(FILE_PATH_LITERAL("event.js"), ""); extension_dir.WriteFile(FILE_PATH_LITERAL("newtab.html"), "<h1>Overridden New Tab Page</h1>"); @@ -81,8 +80,7 @@ test_link_from_NTP); // Increase the extension's version. - extension_dir.WriteManifestWithSingleQuotes( - base::StringPrintf(kManifestTemplate, 2)); + extension_dir.WriteManifest(base::StringPrintf(kManifestTemplate, 2)); // Upgrade the extension. new_tab_extension = UpdateExtension( @@ -107,16 +105,15 @@ ASSERT_TRUE(embedded_test_server()->Start()); TestExtensionDir extension_dir; - const char kManifestTemplate[] = - "{" - " 'name': 'Overrides New Tab'," - " 'version': '%d'," - " 'description': 'Will override New Tab soon'," - " %s" // Placeholder for future NTP url override block. - " 'manifest_version': 2" - "}"; - extension_dir.WriteManifestWithSingleQuotes( - base::StringPrintf(kManifestTemplate, 1, "")); + constexpr char kManifestTemplate[] = + R"({ + "name": "Overrides New Tab", + "version": "%d", + "description": "Will override New Tab soon", + %s // Placeholder for future NTP url override block. + "manifest_version": 2 + })"; + extension_dir.WriteManifest(base::StringPrintf(kManifestTemplate, 1, "")); extension_dir.WriteFile(FILE_PATH_LITERAL("event.js"), ""); extension_dir.WriteFile(FILE_PATH_LITERAL("newtab.html"), "<h1>Overridden New Tab Page</h1>"); @@ -139,12 +136,12 @@ // Increase the extension's version and add the NTP url override which will // add the kNewTabPageOverride permission. - const char ntp_override_string[] = - " 'chrome_url_overrides': {" - " 'newtab': 'newtab.html'" - " },"; - extension_dir.WriteManifestWithSingleQuotes( - base::StringPrintf(kManifestTemplate, 2, ntp_override_string)); + constexpr char kNtpOverrideString[] = + R"("chrome_url_overrides": { + "newtab": "newtab.html" + },)"; + extension_dir.WriteManifest( + base::StringPrintf(kManifestTemplate, 2, kNtpOverrideString)); // Upgrade the extension, ensure that the upgrade 'worked' in the sense that // the extension is still present and not disabled and that it now has the @@ -168,17 +165,17 @@ TestExtensionDir extension_dir; const char manifest_contents[] = - "{" - " 'name': 'Test With Lazy Background Page'," - " 'version': '0'," - " 'manifest_version': 2," - " 'app': {" - " 'background': {" - " 'scripts': ['event.js']" - " }" - " }" - "}"; - extension_dir.WriteManifestWithSingleQuotes(manifest_contents); + R"({ + "name": "Test With Lazy Background Page", + "version": "0", + "manifest_version": 2, + "app": { + "background": { + "scripts": ["event.js"] + } + } + })"; + extension_dir.WriteManifest(manifest_contents); extension_dir.WriteFile(FILE_PATH_LITERAL("event.js"), ""); const Extension* extension = @@ -235,41 +232,41 @@ TestExtensionDir devtools_dir; TestExtensionDir inspect_dir; - const char kDevtoolsManifest[] = - "{" - " 'name': 'Devtools'," - " 'version': '1'," - " 'manifest_version': 2," - " 'devtools_page': 'devtools.html'" - "}"; + constexpr char kDevtoolsManifest[] = + R"({ + "name": "Devtools", + "version": "1", + "manifest_version": 2, + "devtools_page": "devtools.html" + })"; - const char kDevtoolsJs[] = - "setInterval(function() {" - " chrome.devtools.inspectedWindow.eval('1', function() {" - " });" - "}, 4);" - "chrome.test.sendMessage('devtools_page_ready');"; + constexpr char kDevtoolsJs[] = + R"(setInterval(function() { + chrome.devtools.inspectedWindow.eval('1', function() { + }); + }, 4); + chrome.test.sendMessage('devtools_page_ready');)"; - const char kTargetManifest[] = - "{" - " 'name': 'Inspect target'," - " 'version': '1'," - " 'manifest_version': 2," - " 'background': {" - " 'scripts': ['background.js']" - " }" - "}"; + constexpr char kTargetManifest[] = + R"({ + "name": "Inspect target", + "version": "1", + "manifest_version": 2, + "background": { + "scripts": ["background.js"] + } + })"; // A script to duck-type whether it runs in a background page. const char kTargetJs[] = "var is_valid = !!(chrome.tabs && chrome.tabs.create);"; - devtools_dir.WriteManifestWithSingleQuotes(kDevtoolsManifest); + devtools_dir.WriteManifest(kDevtoolsManifest); devtools_dir.WriteFile(FILE_PATH_LITERAL("devtools.js"), kDevtoolsJs); devtools_dir.WriteFile(FILE_PATH_LITERAL("devtools.html"), "<script src='devtools.js'></script>"); - inspect_dir.WriteManifestWithSingleQuotes(kTargetManifest); + inspect_dir.WriteManifest(kTargetManifest); inspect_dir.WriteFile(FILE_PATH_LITERAL("background.js"), kTargetJs); const Extension* devtools_ext = LoadExtension(devtools_dir.UnpackedPath()); ASSERT_TRUE(devtools_ext);
diff --git a/chrome/browser/extensions/fetch_apitest.cc b/chrome/browser/extensions/fetch_apitest.cc index 2196c55..f76f99b 100644 --- a/chrome/browser/extensions/fetch_apitest.cc +++ b/chrome/browser/extensions/fetch_apitest.cc
@@ -116,13 +116,14 @@ IN_PROC_BROWSER_TEST_F(ExtensionFetchTest, ExtensionCanFetchExtensionResource) { TestExtensionDir dir; - dir.WriteManifestWithSingleQuotes( - "{" - "'background': {'scripts': ['bg.js']}," - "'manifest_version': 2," - "'name': 'ExtensionCanFetchExtensionResource'," - "'version': '1'" - "}"); + constexpr char kManifest[] = + R"({ + "background": {"scripts": ["bg.js"]}, + "manifest_version": 2, + "name": "ExtensionCanFetchExtensionResource", + "version": "1" + })"; + dir.WriteManifest(kManifest); const Extension* extension = WriteFilesAndLoadTestExtension(&dir); ASSERT_TRUE(extension); @@ -135,14 +136,15 @@ IN_PROC_BROWSER_TEST_F(ExtensionFetchTest, ExtensionCanFetchHostedResourceWithHostPermissions) { TestExtensionDir dir; - dir.WriteManifestWithSingleQuotes( - "{" - "'background': {'scripts': ['bg.js']}," - "'manifest_version': 2," - "'name': 'ExtensionCanFetchHostedResourceWithHostPermissions'," - "'permissions': ['http://example.com/*']," - "'version': '1'" - "}"); + constexpr char kManifest[] = + R"({ + "background": {"scripts": ["bg.js"]}, + "manifest_version": 2, + "name": "ExtensionCanFetchHostedResourceWithHostPermissions", + "permissions": ["http://example.com/*"], + "version": "1" + })"; + dir.WriteManifest(kManifest); const Extension* extension = WriteFilesAndLoadTestExtension(&dir); ASSERT_TRUE(extension); @@ -156,13 +158,14 @@ ExtensionFetchTest, ExtensionCannotFetchHostedResourceWithoutHostPermissions) { TestExtensionDir dir; - dir.WriteManifestWithSingleQuotes( - "{" - "'background': {'scripts': ['bg.js']}," - "'manifest_version': 2," - "'name': 'ExtensionCannotFetchHostedResourceWithoutHostPermissions'," - "'version': '1'" - "}"); + constexpr char kManifest[] = + R"({ + "background": {"scripts": ["bg.js"]}, + "manifest_version": 2, + "name": "ExtensionCannotFetchHostedResourceWithoutHostPermissions", + "version": "1" + })"; + dir.WriteManifest(kManifest); const Extension* extension = WriteFilesAndLoadTestExtension(&dir); ASSERT_TRUE(extension); @@ -178,14 +181,15 @@ IN_PROC_BROWSER_TEST_F(ExtensionFetchTest, HostCanFetchWebAccessibleExtensionResource) { TestExtensionDir dir; - dir.WriteManifestWithSingleQuotes( - "{" - "'background': {'scripts': ['bg.js']}," - "'manifest_version': 2," - "'name': 'HostCanFetchWebAccessibleExtensionResource'," - "'version': '1'," - "'web_accessible_resources': ['text']" - "}"); + constexpr char kManifest[] = + R"({ + "background": {"scripts": ["bg.js"]}, + "manifest_version": 2, + "name": "HostCanFetchWebAccessibleExtensionResource", + "version": "1", + "web_accessible_resources": ["text"] + })"; + dir.WriteManifest(kManifest); const Extension* extension = WriteFilesAndLoadTestExtension(&dir); ASSERT_TRUE(extension); @@ -209,15 +213,15 @@ ExtensionFetchTest, HostCanFetchWebAccessibleExtensionResource_FetchFromServiceWorker) { TestExtensionDir dir; - dir.WriteManifestWithSingleQuotes( - "{" - "'background': {'scripts': ['bg.js']}," - "'manifest_version': 2," - "'name': 'HostCanFetchWebAccessibleExtensionResource_" - "FetchFromServiceWorker'," - "'version': '1'," - "'web_accessible_resources': ['text']" - "}"); + constexpr char kManifest[] = + R"({ + "background": {"scripts": ["bg.js"]}, + "manifest_version": 2, + "name": "FetchFromServiceWorker", + "version": "1", + "web_accessible_resources": ["text"] + })"; + dir.WriteManifest(kManifest); const Extension* extension = WriteFilesAndLoadTestExtension(&dir); ASSERT_TRUE(extension); @@ -235,13 +239,14 @@ IN_PROC_BROWSER_TEST_F(ExtensionFetchTest, HostCannotFetchNonWebAccessibleExtensionResource) { TestExtensionDir dir; - dir.WriteManifestWithSingleQuotes( - "{" - "'background': {'scripts': ['bg.js']}," - "'manifest_version': 2," - "'name': 'HostCannotFetchNonWebAccessibleExtensionResource'," - "'version': '1'" - "}"); + constexpr char kManifest[] = + R"({ + "background": {"scripts": ["bg.js"]}, + "manifest_version": 2, + "name": "HostCannotFetchNonWebAccessibleExtensionResource", + "version": "1" + })"; + dir.WriteManifest(kManifest); const Extension* extension = WriteFilesAndLoadTestExtension(&dir); ASSERT_TRUE(extension); @@ -267,14 +272,15 @@ GetQuotedTestServerURL("example.com", "/extensions/test_file.txt") .data()); TestExtensionDir dir; - dir.WriteManifestWithSingleQuotes( - "{" - "'background': {'scripts': ['bg.js']}," - "'manifest_version': 2," - "'name': 'FetchResponseType'," - "'permissions': ['http://example.com/*']," - "'version': '1'" - "}"); + constexpr char kManifest[] = + R"({ + "background": {"scripts": ["bg.js"]}, + "manifest_version": 2, + "name": "FetchResponseType", + "permissions": ["http://example.com/*"], + "version": "1" + })"; + dir.WriteManifest(kManifest); const Extension* extension = WriteFilesAndLoadTestExtension(&dir); ASSERT_TRUE(extension);
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index 800c6baa9..2bea577e 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -3702,16 +3702,6 @@ "expiry_milestone": 82 }, { - "name": "webxr-anchors", - "owners": [ "//third_party/blink/renderer/modules/xr/OWNERS", "xr-dev@chromium.org" ], - "expiry_milestone": 82 - }, - { - "name": "webxr-ar-dom-overlay", - "owners": [ "//third_party/blink/renderer/modules/xr/OWNERS", "xr-dev@chromium.org" ], - "expiry_milestone": 81 - }, - { "name": "webxr-ar-module", "owners": [ "//third_party/blink/renderer/modules/xr/OWNERS", "xr-dev@chromium.org" ], "expiry_milestone": 82 @@ -3722,13 +3712,13 @@ "expiry_milestone": 82 }, { - "name": "webxr-orientation-sensor-device", - "owners": [ "//device/vr/OWNERS", "xr-dev@chromium.org" ], + "name": "webxr-incubations", + "owners": [ "//third_party/blink/renderer/modules/xr/OWNERS", "xr-dev@chromium.org" ], "expiry_milestone": 82 }, { - "name": "webxr-plane-detection", - "owners": [ "//third_party/blink/renderer/modules/xr/OWNERS", "xr-dev@chromium.org" ], + "name": "webxr-orientation-sensor-device", + "owners": [ "//device/vr/OWNERS", "xr-dev@chromium.org" ], "expiry_milestone": 82 }, {
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index 66f48fc1..1fb54cc7 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -2345,21 +2345,13 @@ "Enables access to Augmented Reality features defined in the WebXR AR " "Module"; -const char kWebXrArDOMOverlayName[] = "WebXR AR DOM Overlay"; -const char kWebXrArDOMOverlayDescription[] = - "Enables experimental use of a DOM overlay in WebXR AR sessions"; - -const char kWebXrAnchorsName[] = "WebXR Anchors"; -const char kWebXrAnchorsDescription[] = - "Enables access to anchors via WebXR API."; - const char kWebXrHitTestName[] = "WebXR Hit Test"; const char kWebXrHitTestDescription[] = "Enables access to raycasting against estimated XR scene geometry."; -const char kWebXrPlaneDetectionName[] = "WebXR Plane Detection"; -const char kWebXrPlaneDetectionDescription[] = - "Enables access to planes detected in the user's environment."; +const char kWebXrIncubationsName[] = "WebXR Incubations"; +const char kWebXrIncubationsDescription[] = + "Enables experimental features for WebXR."; const char kZeroCopyName[] = "Zero-copy rasterizer"; const char kZeroCopyDescription[] =
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index 29d5632..416c70c 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -1379,17 +1379,11 @@ extern const char kWebXrArModuleName[]; extern const char kWebXrArModuleDescription[]; -extern const char kWebXrArDOMOverlayName[]; -extern const char kWebXrArDOMOverlayDescription[]; - extern const char kWebXrHitTestName[]; extern const char kWebXrHitTestDescription[]; -extern const char kWebXrAnchorsName[]; -extern const char kWebXrAnchorsDescription[]; - -extern const char kWebXrPlaneDetectionName[]; -extern const char kWebXrPlaneDetectionDescription[]; +extern const char kWebXrIncubationsName[]; +extern const char kWebXrIncubationsDescription[]; extern const char kZeroCopyName[]; extern const char kZeroCopyDescription[];
diff --git a/chrome/browser/metrics/process_memory_metrics_emitter_browsertest.cc b/chrome/browser/metrics/process_memory_metrics_emitter_browsertest.cc index cbeaee6..6e0c19d 100644 --- a/chrome/browser/metrics/process_memory_metrics_emitter_browsertest.cc +++ b/chrome/browser/metrics/process_memory_metrics_emitter_browsertest.cc
@@ -467,14 +467,14 @@ // Create an barebones extension with a background page for the given name. const Extension* CreateExtension(const std::string& name) { auto dir = std::make_unique<TestExtensionDir>(); - dir->WriteManifestWithSingleQuotes( - base::StringPrintf("{" - "'name': '%s'," - "'version': '1'," - "'manifest_version': 2," - "'background': {'page': 'bg.html'}" - "}", - name.c_str())); + constexpr char kManifestTemplate[] = + R"({ + "name": "%s", + "version": "1", + "manifest_version": 2, + "background": {"page": "bg.html"} + })"; + dir->WriteManifest(base::StringPrintf(kManifestTemplate, name.c_str())); dir->WriteFile(FILE_PATH_LITERAL("bg.html"), ""); const Extension* extension = LoadExtension(dir->UnpackedPath()); @@ -485,15 +485,17 @@ const Extension* CreateHostedApp(const std::string& name, const GURL& app_url) { - std::unique_ptr<TestExtensionDir> dir(new TestExtensionDir); - dir->WriteManifestWithSingleQuotes(base::StringPrintf( - "{" - "'name': '%s'," - "'version': '1'," - "'manifest_version': 2," - "'app': {'urls': ['%s'], 'launch': {'web_url': '%s'}}" - "}", - name.c_str(), app_url.spec().c_str(), app_url.spec().c_str())); + auto dir = std::make_unique<TestExtensionDir>(); + constexpr char kManifestTemplate[] = + R"({ + "name": "%s", + "version": "1", + "manifest_version": 2, + "app": {"urls": ["%s"], "launch": {"web_url": "%s"}} + })"; + dir->WriteManifest(base::StringPrintf(kManifestTemplate, name.c_str(), + app_url.spec().c_str(), + app_url.spec().c_str())); const Extension* extension = LoadExtension(dir->UnpackedPath()); EXPECT_TRUE(extension);
diff --git a/chrome/browser/optimization_guide/optimization_guide_navigation_data.cc b/chrome/browser/optimization_guide/optimization_guide_navigation_data.cc index acbec3d..756a80c5 100644 --- a/chrome/browser/optimization_guide/optimization_guide_navigation_data.cc +++ b/chrome/browser/optimization_guide/optimization_guide_navigation_data.cc
@@ -58,7 +58,8 @@ was_host_covered_by_fetch_at_commit_( other.was_host_covered_by_fetch_at_commit_), was_hint_for_host_attempted_to_be_fetched_( - other.was_hint_for_host_attempted_to_be_fetched_) { + other.was_hint_for_host_attempted_to_be_fetched_), + is_same_origin_navigation_(other.is_same_origin_navigation_) { if (other.has_page_hint_value()) { page_hint_ = std::make_unique<optimization_guide::proto::PageHint>( *other.page_hint());
diff --git a/chrome/browser/optimization_guide/optimization_guide_navigation_data.h b/chrome/browser/optimization_guide/optimization_guide_navigation_data.h index 1560845..352d93b 100644 --- a/chrome/browser/optimization_guide/optimization_guide_navigation_data.h +++ b/chrome/browser/optimization_guide/optimization_guide_navigation_data.h
@@ -139,6 +139,12 @@ was_hint_for_host_attempted_to_be_fetched; } + // Whether the initiation of the navigation was from a same origin URL or not. + bool is_same_origin_navigation() const { return is_same_origin_navigation_; } + void set_is_same_origin_navigation(bool is_same_origin_navigation) { + is_same_origin_navigation_ = is_same_origin_navigation; + } + private: // Records the hint cache and fetch coverage based on data currently held in // |this|. @@ -210,6 +216,9 @@ // during the navigation. base::Optional<bool> was_hint_for_host_attempted_to_be_fetched_; + // Whether the initiation of the navigation was from a same origin URL or not. + bool is_same_origin_navigation_ = false; + DISALLOW_ASSIGN(OptimizationGuideNavigationData); };
diff --git a/chrome/browser/optimization_guide/optimization_guide_web_contents_observer.cc b/chrome/browser/optimization_guide/optimization_guide_web_contents_observer.cc index 7ad063c..57487b71 100644 --- a/chrome/browser/optimization_guide/optimization_guide_web_contents_observer.cc +++ b/chrome/browser/optimization_guide/optimization_guide_web_contents_observer.cc
@@ -85,6 +85,12 @@ if (!navigation_handle->IsInMainFrame()) return; + content::WebContents* web_contents = navigation_handle->GetWebContents(); + bool is_same_origin = + web_contents && + web_contents->GetLastCommittedURL().SchemeIsHTTPOrHTTPS() && + url::IsSameOriginWith(navigation_handle->GetURL(), + web_contents->GetLastCommittedURL()); OptimizationGuideTopHostProvider::MaybeUpdateTopHostBlacklist( navigation_handle); @@ -100,6 +106,7 @@ GetOrCreateOptimizationGuideNavigationData(navigation_handle); nav_data->set_was_host_covered_by_fetch_at_navigation_start( was_host_covered_by_fetch); + nav_data->set_is_same_origin_navigation(is_same_origin); } void OptimizationGuideWebContentsObserver::DidRedirectNavigation(
diff --git a/chrome/browser/optimization_guide/prediction/prediction_manager.cc b/chrome/browser/optimization_guide/prediction/prediction_manager.cc index f0b2cca..d8e0f59 100644 --- a/chrome/browser/optimization_guide/prediction/prediction_manager.cc +++ b/chrome/browser/optimization_guide/prediction/prediction_manager.cc
@@ -10,6 +10,7 @@ #include "base/containers/flat_set.h" #include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_macros.h" +#include "base/metrics/histogram_macros_local.h" #include "base/rand_util.h" #include "base/sequenced_task_runner.h" #include "base/strings/stringprintf.h" @@ -288,8 +289,16 @@ engagement_service->GetScore(navigation_handle->GetURL())); } case proto::CLIENT_MODEL_FEATURE_SAME_ORIGIN_NAVIGATION: { - return static_cast<float>(url::IsSameOriginWith( - navigation_handle->GetURL(), navigation_handle->GetPreviousURL())); + OptimizationGuideNavigationData* nav_data = + OptimizationGuideNavigationData::GetFromNavigationHandle( + navigation_handle); + + bool is_same_origin = nav_data && nav_data->is_same_origin_navigation(); + + LOCAL_HISTOGRAM_BOOLEAN( + "OptimizationGuide.PredictionManager.IsSameOrigin", is_same_origin); + + return static_cast<float>(is_same_origin); } case proto::CLIENT_MODEL_FEATURE_FIRST_CONTENTFUL_PAINT_SESSION_MEAN: { if (session_fcp_.GetNumberOfSamples() == 0) {
diff --git a/chrome/browser/optimization_guide/prediction/prediction_manager_browsertest.cc b/chrome/browser/optimization_guide/prediction/prediction_manager_browsertest.cc index bbf52c4..03ee7591 100644 --- a/chrome/browser/optimization_guide/prediction/prediction_manager_browsertest.cc +++ b/chrome/browser/optimization_guide/prediction/prediction_manager_browsertest.cc
@@ -49,22 +49,20 @@ } // Retries fetching |histogram_name| until it contains at least |count| samples. -int RetryForHistogramUntilCountReached( +void RetryForHistogramUntilCountReached( const base::HistogramTester* histogram_tester, const std::string& histogram_name, int count) { - int total = 0; while (true) { base::ThreadPoolInstance::Get()->FlushForTesting(); base::RunLoop().RunUntilIdle(); - total = GetTotalHistogramSamples(histogram_tester, histogram_name); - if (total >= count) - return total; - content::FetchHistogramsFromChildProcesses(); SubprocessMetricsProvider::MergeHistogramDeltasForTesting(); - base::RunLoop().RunUntilIdle(); + + int total = GetTotalHistogramSamples(histogram_tester, histogram_name); + if (total >= count) + return; } } @@ -292,6 +290,12 @@ GURL https_url_with_content() { return https_url_with_content_; } GURL https_url_without_content() { return https_url_without_content_; } + protected: + // Feature that the model server should return in response to + // GetModelsRequest. + proto::ClientModelFeature client_model_feature_ = + optimization_guide::proto::CLIENT_MODEL_FEATURE_SITE_ENGAGEMENT_SCORE; + private: std::unique_ptr<net::test_server::HttpResponse> HandleGetModelsRequest( const net::test_server::HttpRequest& request) { @@ -305,8 +309,7 @@ std::unique_ptr<optimization_guide::proto::GetModelsResponse> get_models_response = BuildGetModelsResponse( {"example1.com", https_server_->GetURL("/").host()}, - {optimization_guide::proto:: - CLIENT_MODEL_FEATURE_SITE_ENGAGEMENT_SCORE}); + {client_model_feature_}); if (response_type_ == PredictionModelsFetcherRemoteResponseType:: kSuccessfulWithFeaturesAndNoModels) { get_models_response->clear_models(); @@ -469,12 +472,9 @@ // Wait until histograms have been updated before performing checks for // correct behavior based on the response. - EXPECT_GE( - RetryForHistogramUntilCountReached( - &histogram_tester, - "OptimizationGuide.PredictionModelFetcher.GetModelsResponse.Status", - 1), - 1); + RetryForHistogramUntilCountReached( + &histogram_tester, + "OptimizationGuide.PredictionModelFetcher.GetModelsResponse.Status", 1); histogram_tester.ExpectBucketCount( "OptimizationGuide.PredictionModelFetcher.GetModelsResponse.Status", @@ -499,23 +499,17 @@ // Wait until histograms have been updated before performing checks for // correct behavior based on the response. - EXPECT_GE( - RetryForHistogramUntilCountReached( - &histogram_tester, - "OptimizationGuide.PredictionModelFetcher.GetModelsResponse.Status", - 1), - 1); + RetryForHistogramUntilCountReached( + &histogram_tester, + "OptimizationGuide.PredictionModelFetcher.GetModelsResponse.Status", 1); - EXPECT_GE( - RetryForHistogramUntilCountReached( - &histogram_tester, - "OptimizationGuide.PredictionManager.HostModelFeaturesStored", 1), - 1); - EXPECT_GE( - RetryForHistogramUntilCountReached( - &histogram_tester, - "OptimizationGuide.PredictionManager.PredictionModelsStored", 1), - 1); + RetryForHistogramUntilCountReached( + &histogram_tester, + "OptimizationGuide.PredictionManager.HostModelFeaturesStored", 1); + + RetryForHistogramUntilCountReached( + &histogram_tester, + "OptimizationGuide.PredictionManager.PredictionModelsStored", 1); ui_test_utils::NavigateToURL(browser(), https_url_with_content()); @@ -534,4 +528,70 @@ 1); } +class PredictionManagerBrowserSameOriginTest + : public PredictionManagerBrowserTest { + public: + PredictionManagerBrowserSameOriginTest() = default; + ~PredictionManagerBrowserSameOriginTest() override = default; + + void SetUp() override { + client_model_feature_ = + optimization_guide::proto::CLIENT_MODEL_FEATURE_SAME_ORIGIN_NAVIGATION; + PredictionManagerBrowserTest::SetUp(); + } +}; + +// Regression test for https://crbug.com/1037945. Tests that the origin of the +// previous navigation is computed correctly. +IN_PROC_BROWSER_TEST_F(PredictionManagerBrowserSameOriginTest, + DISABLE_ON_WIN_MAC_CHROMEOS(IsSameOriginNavigation)) { + base::HistogramTester histogram_tester; + OptimizationGuideKeyedService* keyed_service = + OptimizationGuideKeyedServiceFactory::GetForProfile(browser()->profile()); + + PredictionManager* prediction_manager = keyed_service->GetPredictionManager(); + EXPECT_TRUE(prediction_manager); + RegisterWithKeyedService(); + + // Wait until histograms have been updated before performing checks for + // correct behavior based on the response. + RetryForHistogramUntilCountReached( + &histogram_tester, + "OptimizationGuide.PredictionModelFetcher.GetModelsResponse.Status", 1); + + RetryForHistogramUntilCountReached( + &histogram_tester, + "OptimizationGuide.PredictionManager.HostModelFeaturesStored", 1); + + RetryForHistogramUntilCountReached( + &histogram_tester, + "OptimizationGuide.PredictionManager.PredictionModelsStored", 1); + + ui_test_utils::NavigateToURL(browser(), https_url_with_content()); + RetryForHistogramUntilCountReached( + &histogram_tester, "OptimizationGuide.PredictionManager.IsSameOrigin", 1); + histogram_tester.ExpectUniqueSample( + "OptimizationGuide.PredictionManager.IsSameOrigin", false, 1); + + // Navigate to the same URL in the same tab. This should count as a + // same-origin navigation. + ui_test_utils::NavigateToURL(browser(), https_url_with_content()); + RetryForHistogramUntilCountReached( + &histogram_tester, "OptimizationGuide.PredictionManager.IsSameOrigin", 2); + histogram_tester.ExpectBucketCount( + "OptimizationGuide.PredictionManager.IsSameOrigin", false, 1); + histogram_tester.ExpectBucketCount( + "OptimizationGuide.PredictionManager.IsSameOrigin", true, 1); + + // Navigate to a cross-origin URL. This should count as a cross-origin + // navigation. + ui_test_utils::NavigateToURL(browser(), GURL("https://www.google.com/")); + RetryForHistogramUntilCountReached( + &histogram_tester, "OptimizationGuide.PredictionManager.IsSameOrigin", 3); + histogram_tester.ExpectBucketCount( + "OptimizationGuide.PredictionManager.IsSameOrigin", false, 2); + histogram_tester.ExpectBucketCount( + "OptimizationGuide.PredictionManager.IsSameOrigin", true, 1); +} + } // namespace optimization_guide
diff --git a/chrome/browser/optimization_guide/prediction/prediction_manager_unittest.cc b/chrome/browser/optimization_guide/prediction/prediction_manager_unittest.cc index 31580f2..f8ffc7ef 100644 --- a/chrome/browser/optimization_guide/prediction/prediction_manager_unittest.cc +++ b/chrome/browser/optimization_guide/prediction/prediction_manager_unittest.cc
@@ -1425,12 +1425,6 @@ navigation_handle->set_url(previous_url); navigation_handle->set_page_transition( ui::PageTransition::PAGE_TRANSITION_RELOAD); - ON_CALL(*navigation_handle, GetPreviousURL()) - .WillByDefault(testing::ReturnRef(previous_url)); - - if (IsSameOriginNavigationFeature()) { - EXPECT_CALL(*navigation_handle, GetPreviousURL()).Times(1); - } CreatePredictionManager({}); prediction_manager()->SetPredictionModelFetcherForTesting( @@ -1477,8 +1471,6 @@ navigation_handle->set_url(previous_url); navigation_handle->set_page_transition( ui::PageTransition::PAGE_TRANSITION_RELOAD); - ON_CALL(*navigation_handle, GetPreviousURL()) - .WillByDefault(testing::ReturnRef(previous_url)); pref_service()->SetDouble(optimization_guide::prefs::kSessionStatisticFCPMean, 200.0);
diff --git a/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceKeys.java b/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceKeys.java index 470ff5c..68dca20 100644 --- a/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceKeys.java +++ b/chrome/browser/preferences/android/java/src/org/chromium/chrome/browser/preferences/ChromePreferenceKeys.java
@@ -48,6 +48,10 @@ */ public static final String ACCESSIBILITY_TAB_SWITCHER = "accessibility_tab_switcher"; + public static final String BOOKMARKS_LAST_USED_URL = "enhanced_bookmark_last_used_url"; + public static final String BOOKMARKS_LAST_USED_PARENT = + "enhanced_bookmark_last_used_parent_folder"; + /** * Whether Chrome is set as the default browser. * Default value is false. @@ -342,6 +346,14 @@ * Default value is false. */ public static final String FLAGS_CACHED_START_SURFACE_ENABLED = "start_surface_enabled"; + + /** + * Whether or not the start surface single pane is enabled. + * Default value is false. + */ + public static final String START_SURFACE_SINGLE_PANE_ENABLED_KEY = + "start_surface_single_pane_enabled"; + /** * Key to cache whether SWAP_PIXEL_FORMAT_TO_FIX_CONVERT_FROM_TRANSLUCENT is enabled. */ @@ -468,6 +480,8 @@ // clang-format off return Arrays.asList( ACCESSIBILITY_TAB_SWITCHER, + BOOKMARKS_LAST_USED_URL, + BOOKMARKS_LAST_USED_PARENT, CHROME_DEFAULT_BROWSER, CONTENT_SUGGESTIONS_SHOWN, CONTEXTUAL_SEARCH_ALL_TIME_OPEN_COUNT, @@ -565,6 +579,7 @@ SIGNIN_PROMO_NTP_PROMO_SUPPRESSION_PERIOD_START, SIGNIN_PROMO_PERSONALIZED_DECLINED, SIGNIN_PROMO_SETTINGS_PERSONALIZED_DISMISSED, + START_SURFACE_SINGLE_PANE_ENABLED_KEY, TWA_DIALOG_NUMBER_OF_DISMISSALS_ON_CLEAR_DATA, TWA_DIALOG_NUMBER_OF_DISMISSALS_ON_UNINSTALL, TWA_DISCLOSURE_ACCEPTED_PACKAGES, @@ -622,6 +637,8 @@ // clang-format off return Arrays.asList( ACCESSIBILITY_TAB_SWITCHER, + BOOKMARKS_LAST_USED_URL, + BOOKMARKS_LAST_USED_PARENT, CHROME_DEFAULT_BROWSER, CONTENT_SUGGESTIONS_SHOWN, CONTEXTUAL_SEARCH_ALL_TIME_OPEN_COUNT, @@ -712,6 +729,7 @@ SIGNIN_PROMO_NTP_PROMO_SUPPRESSION_PERIOD_START, SIGNIN_PROMO_PERSONALIZED_DECLINED, SIGNIN_PROMO_SETTINGS_PERSONALIZED_DISMISSED, + START_SURFACE_SINGLE_PANE_ENABLED_KEY, TWA_DIALOG_NUMBER_OF_DISMISSALS_ON_CLEAR_DATA, TWA_DIALOG_NUMBER_OF_DISMISSALS_ON_UNINSTALL, TWA_DISCLOSURE_ACCEPTED_PACKAGES,
diff --git a/chrome/browser/prerender/prerender_browsertest.cc b/chrome/browser/prerender/prerender_browsertest.cc index 69c4025..6d18f89e 100644 --- a/chrome/browser/prerender/prerender_browsertest.cc +++ b/chrome/browser/prerender/prerender_browsertest.cc
@@ -242,7 +242,6 @@ // We'll crash the renderer after it's loaded. case FINAL_STATUS_RENDERER_CRASHED: case FINAL_STATUS_CANCELLED: - case FINAL_STATUS_DEVTOOLS_ATTACHED: case FINAL_STATUS_PAGE_BEING_CAPTURED: case FINAL_STATUS_NAVIGATION_UNCOMMITTED: case FINAL_STATUS_NON_EMPTY_BROWSING_INSTANCE: @@ -1145,20 +1144,6 @@ false); } -// Checks that the prerendering of a page is canceled correctly when a -// Javascript alert is called. -IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderAlertBeforeOnload) { - PrerenderTestURL("/prerender/prerender_alert_before_onload.html", - FINAL_STATUS_JAVASCRIPT_ALERT, 0); -} - -// Checks that the prerendering of a page is canceled correctly when a -// Javascript alert is called. -IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderAlertAfterOnload) { - PrerenderTestURL("/prerender/prerender_alert_after_onload.html", - FINAL_STATUS_JAVASCRIPT_ALERT, 1); -} - // Checks that plugins are not loaded while a page is being preloaded, but // are loaded when the page is displayed. IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderDelayLoadPlugin) {
diff --git a/chrome/browser/prerender/prerender_contents.cc b/chrome/browser/prerender/prerender_contents.cc index 11e7f40f..89fe0a3c 100644 --- a/chrome/browser/prerender/prerender_contents.cc +++ b/chrome/browser/prerender/prerender_contents.cc
@@ -134,15 +134,6 @@ return false; } - bool ShouldSuppressDialogs(WebContents* source) override { - // We still want to show the user the message when they navigate to this - // page, so cancel this prerender. - prerender_contents_->Destroy(FINAL_STATUS_JAVASCRIPT_ALERT); - // Always suppress JavaScript messages if they're triggered by a page being - // prerendered. - return true; - } - void RegisterProtocolHandler(WebContents* web_contents, const std::string& protocol, const GURL& url,
diff --git a/chrome/browser/prerender/prerender_final_status.h b/chrome/browser/prerender/prerender_final_status.h index 8d50045..e8206c1 100644 --- a/chrome/browser/prerender/prerender_final_status.h +++ b/chrome/browser/prerender/prerender_final_status.h
@@ -25,7 +25,7 @@ FINAL_STATUS_CREATE_NEW_WINDOW = 5, FINAL_STATUS_PROFILE_DESTROYED = 6, FINAL_STATUS_APP_TERMINATING = 7, - FINAL_STATUS_JAVASCRIPT_ALERT = 8, + // Obsolete: FINAL_STATUS_JAVASCRIPT_ALERT = 8, FINAL_STATUS_AUTH_NEEDED = 9, // Obsolete: FINAL_STATUS_HTTPS = 10, FINAL_STATUS_DOWNLOAD = 11, @@ -52,7 +52,7 @@ FINAL_STATUS_CANCELLED = 32, FINAL_STATUS_SSL_ERROR = 33, // Obsolete: FINAL_STATUS_CROSS_SITE_NAVIGATION_PENDING = 34, - FINAL_STATUS_DEVTOOLS_ATTACHED = 35, + // Obsolete: FINAL_STATUS_DEVTOOLS_ATTACHED = 35, // Obsolete: FINAL_STATUS_SESSION_STORAGE_NAMESPACE_MISMATCH = 36, // Obsolete: FINAL_STATUS_NO_USE_GROUP = 37, // Obsolete: FINAL_STATUS_MATCH_COMPLETE_DUMMY = 38,
diff --git a/chrome/browser/prerender/prerender_manager.cc b/chrome/browser/prerender/prerender_manager.cc index f2e61d21..f406a71 100644 --- a/chrome/browser/prerender/prerender_manager.cc +++ b/chrome/browser/prerender/prerender_manager.cc
@@ -51,7 +51,6 @@ #include "chrome/common/prerender_types.h" #include "components/content_settings/core/browser/cookie_settings.h" #include "content/public/browser/browser_thread.h" -#include "content/public/browser/devtools_agent_host.h" #include "content/public/browser/navigation_controller.h" #include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_process_host.h" @@ -129,19 +128,9 @@ ScheduleWebContentsForDeletion(/*timeout=*/false); } - bool ShouldSuppressDialogs(WebContents* source) override { - // Use this as a proxy for getting statistics on how often we fail to honor - // the beforeunload event. - DCHECK_EQ(tab_.get(), source); - suppressed_dialog_ = true; - return true; - } - private: void ScheduleWebContentsForDeletion(bool timeout) { UMA_HISTOGRAM_BOOLEAN("Prerender.TabContentsDeleterTimeout", timeout); - UMA_HISTOGRAM_BOOLEAN("Prerender.TabContentsDeleterSuppressedDialog", - suppressed_dialog_); tab_->SetDelegate(nullptr); manager_->ScheduleDeleteOldWebContents(std::move(tab_), this); // |this| is deleted at this point. @@ -149,7 +138,6 @@ PrerenderManager* const manager_; std::unique_ptr<WebContents> tab_; - bool suppressed_dialog_ = false; DISALLOW_COPY_AND_ASSIGN(OnCloseWebContentsDeleter); }; @@ -449,15 +437,6 @@ DCHECK(prerender_data->contents()->prerendering_has_started()); - // Don't use prerendered pages if debugger is attached to the tab. - // See http://crbug.com/98541 - if (content::DevToolsAgentHost::IsDebuggerAttached(web_contents)) { - histograms_->RecordFinalStatus(prerender_data->contents()->origin(), - FINAL_STATUS_DEVTOOLS_ATTACHED); - prerender_data->contents()->Destroy(FINAL_STATUS_DEVTOOLS_ATTACHED); - return nullptr; - } - // At this point, we've determined that we will use the prerender. content::RenderProcessHost* process_host = prerender_data->contents()->GetRenderViewHost()->GetProcess();
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/options/options.html b/chrome/browser/resources/chromeos/accessibility/chromevox/background/options/options.html index 67989fb5..4c49622 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/options/options.html +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/options/options.html
@@ -55,6 +55,23 @@ name="speakTextUnderMouse" aria-labelledby="speakMouseTextLabel"> </div> + <div class="option" id="capitalStrategyOption"> + <label id="capitalStrategyLabel" class="i18n" + msgid="options_capital_strategy_select_label"> + When reading capitals: + </label> + <select id="capitalStrategy" class="pref" + aria-labelledby="capitalStrategyLabel"> + <option id="announceCapitals" class="i18n" + msgid="options_announce_capitals"> + Speak "cap" before letter + </option> + <option id="increasePitch" class="i18n" msgid="options_increase_pitch"> + Increase pitch + </option> + </select> + </div> + <div class="option"> <label id="announceDownloadsLabel" class="i18n" msgid="options_announce_download">
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/options/options.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/options/options.js index 5da5e5c7..575f0c3 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/options/options.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/options/options.js
@@ -94,6 +94,13 @@ } } } + if (localStorage['capitalStrategy']) { + for (var i = 0, opt; opt = $('capitalStrategy').options[i]; ++i) { + if (opt.id == localStorage['capitalStrategy']) { + opt.setAttribute('selected', ''); + } + } + } chrome.commandLinePrivate.hasSwitch( 'enable-experimental-accessibility-chromevox-language-switching',
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/prefs.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/prefs.js index 1f751ae..309bf8b 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/prefs.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/prefs.js
@@ -73,6 +73,7 @@ // TODO(dtseng): Leaking state about multiple key maps here until we have a // class to manage multiple key maps. Also, this doesn't belong as a pref; // should just store in local storage. + 'capitalStrategy': 'increasePitch', 'currentKeyMap': KeyMap.DEFAULT_KEYMAP, 'cvoxKey': '', 'enableBrailleLogging': false,
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/common/abstract_tts.js b/chrome/browser/resources/chromeos/accessibility/chromevox/common/abstract_tts.js index db92037..4b26a8b 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/common/abstract_tts.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/common/abstract_tts.js
@@ -201,10 +201,15 @@ */ AbstractTts.prototype.preprocess = function(text, properties) { if (text.length == 1 && text >= 'A' && text <= 'Z') { - for (var prop in AbstractTts.PERSONALITY_CAPITAL) { - if (properties[prop] === undefined) { - properties[prop] = AbstractTts.PERSONALITY_CAPITAL[prop]; + // Describe capital letters according to user's setting. + if (localStorage['capitalStrategy'] == 'increasePitch') { + for (var prop in AbstractTts.PERSONALITY_CAPITAL) { + if (properties[prop] === undefined) { + properties[prop] = AbstractTts.PERSONALITY_CAPITAL[prop]; + } } + } else if (localStorage['capitalStrategy'] == 'announceCapitals') { + text = Msgs.getMsg('announce_capital_letter', [text]); } }
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/common/tts_background.js b/chrome/browser/resources/chromeos/accessibility/chromevox/common/tts_background.js index 0e5e880..064abae 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/common/tts_background.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/common/tts_background.js
@@ -207,6 +207,10 @@ TtsBackground.prototype.speak = function(textString, queueMode, properties) { goog.base(this, 'speak', textString, queueMode, properties); + // |textString| gets manipulated throughout this function. Save the original + // value for functions that may need it. + var originalTextString = textString; + if (this.ttsProperties[AbstractTts.VOLUME] === 0) { return this; } @@ -258,7 +262,7 @@ this.speakUsingQueue_(utterance, queueMode); // Attempt to queue phonetic speech with property['delay']. This ensures that // phonetic hints are delayed when we process them. - this.pronouncePhonetically_(textString, properties); + this.pronouncePhonetically_(originalTextString, properties); return this; };
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/common/tts_background_test.js b/chrome/browser/resources/chromeos/accessibility/chromevox/common/tts_background_test.js index 447611e..ae2d709 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/common/tts_background_test.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/common/tts_background_test.js
@@ -146,3 +146,19 @@ 'Please do the shopping at 3 a thing came up at work', preprocess('Please do the shopping at 3 a thing came up at work')); }); + +SYNC_TEST_F('ChromeVoxTtsBackgroundTest', 'AnnounceCapitalLetters', function() { + var tts = new TtsBackground(false); + var preprocess = tts.preprocess.bind(tts); + + assertEquals('A', preprocess('A')); + + // Only announce capital for solo capital letters. + localStorage['capitalStrategy'] = 'announceCapitals'; + assertEquals('Cap A', preprocess('A')); + assertEquals('Cap Z', preprocess('Z')); + + // Do not announce capital for the following inputs. + assertEquals('BB', preprocess('BB')); + assertEquals('A.', preprocess('A.')); +});
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/strings/chromevox_strings.grd b/chrome/browser/resources/chromeos/accessibility/chromevox/strings/chromevox_strings.grd index 6aab9e9..97edf0fcc 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/strings/chromevox_strings.grd +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/strings/chromevox_strings.grd
@@ -3796,6 +3796,18 @@ <message desc="The description of the openKeyboardShortcutsMenu key. Displayed in the ChromeVox menu" name="IDS_CHROMEVOX_OPEN_KEYBOARD_SHORTCUTS_MENU"> Open keyboard shortcuts menu </message> + <message desc="Describes the multi select option for how to describe capital letters." name="IDS_CHROMEVOX_OPTIONS_CAPITAL_STRATEGY_SELECT_LABEL"> + When reading capitals: + </message> + <message desc="Sets capital description strategy to announce presence of capital letters" name="IDS_CHROMEVOX_OPTIONS_ANNOUNCE_CAPITALS"> + Speak "cap" before letter + </message> + <message desc="Sets capital description strategy to increase pitch" name="IDS_CHROMEVOX_OPTIONS_INCREASE_PITCH"> + Increase pitch + </message> + <message desc="Used to describe capital letters" name="IDS_CHROMEVOX_ANNOUNCE_CAPITAL_LETTER"> + Cap <ph name="letter">$1<ex>A</ex></ph> + </message> </messages> </release> </grit>
diff --git a/chrome/browser/resources/chromeos/camera/BUILD.gn b/chrome/browser/resources/chromeos/camera/BUILD.gn index 9eab015..c15ecf2 100644 --- a/chrome/browser/resources/chromeos/camera/BUILD.gn +++ b/chrome/browser/resources/chromeos/camera/BUILD.gn
@@ -134,6 +134,8 @@ copy("chrome_camera_app_js_browser_proxy") { sources = [ + # TODO(b/129956426): Remove dependency used only in closure compiler check. + "src/js/browser_proxy/browser_proxy_interface.js", "src/js/browser_proxy/browser_proxy.js", ]
diff --git a/chrome/browser/resources/chromeos/camera/src/js/device/device_info_updater.js b/chrome/browser/resources/chromeos/camera/src/js/device/device_info_updater.js index 4e4360a..fc77b9d3 100644 --- a/chrome/browser/resources/chromeos/camera/src/js/device/device_info_updater.js +++ b/chrome/browser/resources/chromeos/camera/src/js/device/device_info_updater.js
@@ -2,44 +2,41 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -'use strict'; - -/** - * Namespace for the Camera app. - */ -var cca = cca || {}; - -/** - * Namespace for device. - */ -cca.device = cca.device || {}; +import {DeviceOperator} from '../mojo/device_operator.js'; +// eslint-disable-next-line no-unused-vars +import {ResolutionList} from '../type.js'; +import {Camera3DeviceInfo} from './camera3_device_info.js'; +import {PhotoConstraintsPreferrer, // eslint-disable-line no-unused-vars + VideoConstraintsPreferrer, // eslint-disable-line no-unused-vars +} from './constraints_preferrer.js'; +import {LegacyVCDError} from './error.js'; /** * Contains information of all cameras on the device and will updates its value * when any plugin/unplug external camera changes. */ -cca.device.DeviceInfoUpdater = class { +export class DeviceInfoUpdater { /** - * @param {!cca.device.PhotoConstraintsPreferrer} photoPreferrer - * @param {!cca.device.VideoConstraintsPreferrer} videoPreferrer + * @param {!PhotoConstraintsPreferrer} photoPreferrer + * @param {!VideoConstraintsPreferrer} videoPreferrer * @public * */ constructor(photoPreferrer, videoPreferrer) { /** - * @type {!cca.device.PhotoConstraintsPreferrer} + * @type {!PhotoConstraintsPreferrer} * @private */ this.photoPreferrer_ = photoPreferrer; /** - * @type {!cca.device.VideoConstraintsPreferrer} + * @type {!VideoConstraintsPreferrer} * @private */ this.videoPreferrer_ = videoPreferrer; /** * Listeners to be called after new camera information is available. - * @type {!Array<!function(!cca.device.DeviceInfoUpdater): Promise>} + * @type {!Array<!function(!DeviceInfoUpdater): Promise>} * @private */ this.deviceChangeListeners_ = []; @@ -68,7 +65,7 @@ /** * Camera3DeviceInfo of all available video devices. Is null on HALv1 device * without mojo api support. - * @type {!Promise<?Array<cca.device.Camera3DeviceInfo>>} + * @type {!Promise<?Array<Camera3DeviceInfo>>} * @private */ this.camera3DevicesInfo_ = this.queryMojoDevicesInfo_(); @@ -150,7 +147,7 @@ /** * Queries Camera3DeviceInfo of available devices through private mojo API. - * @return {!Promise<?Array<!cca.device.Camera3DeviceInfo>>} Camera3DeviceInfo + * @return {!Promise<?Array<!Camera3DeviceInfo>>} Camera3DeviceInfo * of available devices. Maybe null on HALv1 devices without supporting * private mojo api. * @throws {Error} Thrown when camera unplugging happens between enumerating @@ -158,17 +155,16 @@ * @private */ async queryMojoDevicesInfo_() { - if (!await cca.mojo.DeviceOperator.isSupported()) { + if (!await DeviceOperator.isSupported()) { return null; } const deviceInfos = await this.devicesInfo_; - return Promise.all( - deviceInfos.map((d) => cca.device.Camera3DeviceInfo.create(d))); + return Promise.all(deviceInfos.map((d) => Camera3DeviceInfo.create(d))); } /** * Registers listener to be called when state of available devices changes. - * @param {!function(!cca.device.DeviceInfoUpdater)} listener + * @param {!function(!DeviceInfoUpdater)} listener */ addDeviceChangeListener(listener) { this.deviceChangeListeners_.push(listener); @@ -178,9 +174,9 @@ * Requests to lock update of device information. This function is preserved * for device information reader to lock the update capability so as to ensure * getting consistent data between all information providers. - * @param {!function(!cca.device.DeviceInfoUpdater): Promise} callback Called - * after update capability is locked. Getting information from all - * providers in callback are guaranteed to be consistent. + * @param {!function(!DeviceInfoUpdater): Promise} callback Called after + * update capability is locked. Getting information from all providers in + * callback are guaranteed to be consistent. */ async lockDeviceInfo(callback) { await this.firstUpdate_; @@ -222,7 +218,7 @@ /** * Gets Camera3DeviceInfo for all available video devices. - * @return {!Promise<?Array<!cca.device.Camera3DeviceInfo>>} + * @return {!Promise<?Array<!Camera3DeviceInfo>>} */ async getCamera3DevicesInfo() { return this.camera3DevicesInfo_; @@ -231,17 +227,20 @@ /** * Gets supported photo and video resolutions for specified video device. * @param {string} deviceId Device id of the video device. - * @return {!Promise<!{photo: !cca.ResolutionList, video: - * !cca.ResolutionList}>} Supported photo and video resolutions. + * @return {!Promise<!{photo: !ResolutionList, video: !ResolutionList}>} + * Supported photo and video resolutions. * @throws {Error} May fail on HALv1 device without capability of querying * supported resolutions. */ async getDeviceResolutions(deviceId) { const devices = await this.getCamera3DevicesInfo(); if (!devices) { - throw new cca.device.LegacyVCDError(); + throw new LegacyVCDError(); } const info = devices.find((info) => info.deviceId === deviceId); return {photo: info.photoResols, video: info.videoResols}; } -}; +} + +/** @const */ +cca.device.DeviceInfoUpdater = DeviceInfoUpdater;
diff --git a/chrome/browser/resources/chromeos/camera/src/js/main.js b/chrome/browser/resources/chromeos/camera/src/js/main.js index 21a93df..b51adf2 100644 --- a/chrome/browser/resources/chromeos/camera/src/js/main.js +++ b/chrome/browser/resources/chromeos/camera/src/js/main.js
@@ -161,8 +161,9 @@ }); }) .then((external) => { - cca.assert(cca.models.FileSystem.externalDir !== null); - this.galleryButton_.initialize(cca.models.FileSystem.externalDir); + const externalDir = cca.models.FileSystem.getExternalDirectory(); + cca.assert(externalDir !== null); + this.galleryButton_.initialize(externalDir); cca.nav.open(cca.views.ViewName.CAMERA); }) .catch((error) => {
diff --git a/chrome/browser/resources/chromeos/camera/src/js/models/BUILD.gn b/chrome/browser/resources/chromeos/camera/src/js/models/BUILD.gn index 9dc708a..2e74d1e6 100644 --- a/chrome/browser/resources/chromeos/camera/src/js/models/BUILD.gn +++ b/chrome/browser/resources/chromeos/camera/src/js/models/BUILD.gn
@@ -21,7 +21,7 @@ js_library("filesystem") { deps = [ - "..:util", + "../browser_proxy:browser_proxy", ] }
diff --git a/chrome/browser/resources/chromeos/camera/src/js/models/filesystem.js b/chrome/browser/resources/chromeos/camera/src/js/models/filesystem.js index 224f4a3d..c611eda 100644 --- a/chrome/browser/resources/chromeos/camera/src/js/models/filesystem.js +++ b/chrome/browser/resources/chromeos/camera/src/js/models/filesystem.js
@@ -2,92 +2,129 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -'use strict'; - -/** - * Namespace for the Camera app. - */ -var cca = cca || {}; - -/** - * Namespace for models. - */ -cca.models = cca.models || {}; - -/** - * Creates the file system controller. - * @constructor - */ -cca.models.FileSystem = function() { - // End of properties, seal the object. - Object.seal(this); -}; +import {browserProxy} from '../browser_proxy/browser_proxy.js'; +import {assert} from '../chrome_util.js'; +import {Filenamer, IMAGE_PREFIX, VIDEO_PREFIX} from './filenamer.js'; /** * The prefix of thumbnail files. * @type {string} - * @const */ -cca.models.FileSystem.THUMBNAIL_PREFIX = 'thumb-'; +const THUMBNAIL_PREFIX = 'thumb-'; + +/** + * Checks if the entry's name has the video prefix. + * @param {!FileEntry} entry File entry. + * @return {boolean} Has the video prefix or not. + */ +export function hasVideoPrefix(entry) { + return entry.name.startsWith(VIDEO_PREFIX); +} + +/** + * Checks if the entry's name has the image prefix. + * @param {!FileEntry} entry File entry. + * @return {boolean} Has the image prefix or not. + */ +function hasImagePrefix(entry) { + return entry.name.startsWith(IMAGE_PREFIX); +} + +/** + * Checks if the entry's name has the thumbnail prefix. + * @param {!FileEntry} entry File entry. + * @return {boolean} Has the thumbnail prefix or not. + */ +function hasThumbnailPrefix(entry) { + return entry.name.startsWith(THUMBNAIL_PREFIX); +} /** * Directory in the internal file system. - * @type {DirectoryEntry} + * @type {?DirectoryEntry} */ -cca.models.FileSystem.internalDir = null; +let internalDir = null; /** * Temporary directory in the internal file system. - * @type {DirectoryEntry} + * @type {?DirectoryEntry} */ -cca.models.FileSystem.internalTempDir = null; +let internalTempDir = null; /** * Directory in the external file system. - * @type {DirectoryEntry} + * @type {?DirectoryEntry} */ -cca.models.FileSystem.externalDir = null; +let externalDir = null; + +/** + * Gets global external directory used by CCA. + * @return {?DirectoryEntry} + */ +export function getExternalDirectory() { + return externalDir; +} /** * Initializes the directory in the internal file system. - * @return {!Promise<DirectoryEntry>} Promise for the directory result. - * @private + * @return {!Promise<!DirectoryEntry>} Promise for the directory result. */ -cca.models.FileSystem.initInternalDir_ = function() { +function initInternalDir() { return new Promise((resolve, reject) => { webkitRequestFileSystem( window.PERSISTENT, 768 * 1024 * 1024 /* 768MB */, (fs) => resolve(fs.root), reject); }); -}; +} /** * Initializes the temporary directory in the internal file system. - * @return {!Promise<DirectoryEntry>} Promise for the directory result. - * @private + * @return {!Promise<!DirectoryEntry>} Promise for the directory result. */ -cca.models.FileSystem.initInternalTempDir_ = function() { +function initInternalTempDir() { return new Promise((resolve, reject) => { webkitRequestFileSystem( window.TEMPORARY, 768 * 1024 * 1024 /* 768MB */, (fs) => resolve(fs.root), reject); }); -}; +} + +/** + * Reads file entries from the directory. + * @param {?DirectoryEntry} dir Directory entry to be read. + * @return {!Promise<!Array<!FileEntry>>} Promise for the read file entries. + */ +function readDir(dir) { + return !dir ? Promise.resolve([]) : new Promise((resolve, reject) => { + const dirReader = dir.createReader(); + const entries = []; + const readEntries = () => { + dirReader.readEntries((inEntries) => { + if (inEntries.length === 0) { + resolve(entries); + return; + } + entries.push(...inEntries); + readEntries(); + }, reject); + }; + readEntries(); + }); +} /** * Initializes the directory in the external file system. * @return {!Promise<?DirectoryEntry>} Promise for the directory result. - * @private */ -cca.models.FileSystem.initExternalDir_ = function() { +function initExternalDir() { return new Promise((resolve) => { - cca.proxy.browserProxy.getVolumeList((volumes) => { + browserProxy.getVolumeList((volumes) => { if (volumes) { - for (var i = 0; i < volumes.length; i++) { - var volumeId = volumes[i].volumeId; + for (let i = 0; i < volumes.length; i++) { + const volumeId = volumes[i].volumeId; if (volumeId.indexOf('downloads:Downloads') !== -1 || volumeId.indexOf('downloads:MyFiles') !== -1) { - cca.proxy.browserProxy.requestFileSystem( + browserProxy.requestFileSystem( volumes[i], (fs) => resolve([fs && fs.root, volumeId])); return; } @@ -98,14 +135,117 @@ }) .then(([dir, volumeId]) => { if (volumeId && volumeId.indexOf('downloads:MyFiles') !== -1) { - return cca.models.FileSystem.readDir_(dir).then((entries) => { + return readDir(dir).then((entries) => { return entries.find( (entry) => entry.name === 'Downloads' && entry.isDirectory); }); } return dir; }); -}; +} + +/** + * Regulates the picture name to the desired format if it's in legacy formats. + * @param {!FileEntry} entry Picture entry whose name to be regulated. + * @return {string} Name in the desired format. + */ +function regulatePictureName(entry) { + if (hasVideoPrefix(entry) || hasImagePrefix(entry)) { + const match = entry.name.match(/(\w{3}_\d{8}_\d{6})(?:_(\d+))?(\..+)?$/); + if (match) { + const idx = match[2] ? ' (' + match[2] + ')' : ''; + const ext = match[3] ? match[3].replace(/\.webm$/, '.mkv') : ''; + return match[1] + idx + ext; + } + } else { + // Early pictures are in legacy file name format (crrev.com/c/310064). + const match = entry.name.match(/(\d+).(?:\d+)/); + if (match) { + return (new Filenamer(parseInt(match[1], 10))).newImageName(); + } + } + return entry.name; +} + +/** + * Gets the thumbnail name of the given picture. + * @param {!FileEntry} entry Picture's file entry. + * @return {string} Thumbnail name. + */ +function getThumbnailName(entry) { + const thumbnailName = THUMBNAIL_PREFIX + entry.name; + return (thumbnailName.substr(0, thumbnailName.lastIndexOf('.')) || + thumbnailName) + + '.jpg'; +} + +/** + * Parses and filters the internal entries to thumbnail and picture entries. + * @param {!Array<!FileEntry>} internalEntries Internal file entries. + * @param {!Object<string, !FileEntry>} thumbnailEntriesByName Result thumbanil + * entries mapped by thumbnail names, initially empty. + * @param {!Array<!FileEntry>=} pictureEntries Result picture entries, initially + * empty. + */ +function parseInternalEntries( + internalEntries, thumbnailEntriesByName, pictureEntries) { + let thumbnailEntries = []; + if (pictureEntries) { + for (let index = 0; index < internalEntries.length; index++) { + if (hasThumbnailPrefix(internalEntries[index])) { + thumbnailEntries.push(internalEntries[index]); + } else { + pictureEntries.push(internalEntries[index]); + } + } + } else { + thumbnailEntries = internalEntries.filter(hasThumbnailPrefix); + } + for (let index = 0; index < thumbnailEntries.length; index++) { + const thumbnailEntry = thumbnailEntries[index]; + thumbnailEntriesByName[thumbnailEntry.name] = thumbnailEntry; + } +} + +/** + * Migrates all picture-files from internal storage to external storage. + * @return {!Promise} Promise for the operation. + */ +function migratePictures() { + const migratePicture = (pictureEntry, thumbnailEntry) => { + const name = regulatePictureName(pictureEntry); + const targetDir = externalDir; + assert(targetDir !== null); + return getFile(targetDir, name, true).then((entry) => { + return new Promise((resolve, reject) => { + pictureEntry.copyTo(targetDir, entry.name, (result) => { + if (result.name !== pictureEntry.name && thumbnailEntry) { + // Thumbnails can be recreated later if failing to rename them here. + thumbnailEntry.moveTo(internalDir, getThumbnailName(result)); + } + pictureEntry.remove(() => {}); + resolve(); + }, reject); + }); + }); + }; + + return readDir(internalDir).then((internalEntries) => { + const pictureEntries = []; + const thumbnailEntriesByName = {}; + parseInternalEntries( + internalEntries, thumbnailEntriesByName, pictureEntries); + + const migrated = []; + for (let index = 0; index < pictureEntries.length; index++) { + const entry = pictureEntries[index]; + const thumbnailName = getThumbnailName(entry); + const thumbnailEntry = thumbnailEntriesByName[thumbnailName]; + migrated.push(migratePicture(entry, thumbnailEntry)); + } + return Promise.all(migrated); + }); +} /** * Initializes file systems, migrating pictures if needed. This function @@ -114,15 +254,15 @@ prompts users to migrate pictures if no acknowledgement yet. * @return {!Promise<boolean>} Promise for the external-fs result. */ -cca.models.FileSystem.initialize = function(promptMigrate) { - var checkAcked = new Promise((resolve) => { +export function initialize(promptMigrate) { + const checkAcked = new Promise((resolve) => { // ack 0: User has not yet acknowledged to migrate pictures. // ack 1: User acknowledges to migrate pictures to Downloads. - cca.proxy.browserProxy.localStorageGet( + browserProxy.localStorageGet( {ackMigratePictures: 0}, (values) => resolve(values.ackMigratePictures >= 1)); }); - var checkMigrated = new Promise((resolve) => { + const checkMigrated = new Promise((resolve) => { if (chrome.chromeosInfoPrivate) { chrome.chromeosInfoPrivate.get( ['cameraMediaConsolidated'], @@ -131,37 +271,35 @@ resolve(false); } }); - var ackMigrate = () => - cca.proxy.browserProxy.localStorageSet({ackMigratePictures: 1}); - var doneMigrate = () => chrome.chromeosInfoPrivate && + const ackMigrate = () => + browserProxy.localStorageSet({ackMigratePictures: 1}); + const doneMigrate = () => chrome.chromeosInfoPrivate && chrome.chromeosInfoPrivate.set('cameraMediaConsolidated', true); return Promise .all([ - cca.models.FileSystem.initInternalDir_(), - cca.models.FileSystem.initInternalTempDir_(), - cca.models.FileSystem.initExternalDir_(), + initInternalDir(), + initInternalTempDir(), + initExternalDir(), checkAcked, checkMigrated, ]) - .then(([internalDir, internalTempDir, externalDir, acked, migrated]) => { - cca.models.FileSystem.internalDir = internalDir; - cca.models.FileSystem.internalTempDir = internalTempDir; - cca.models.FileSystem.externalDir = externalDir; + .then((results) => { + let /** boolean */ acked; + let /** boolean */ migrated; + [internalDir, internalTempDir, externalDir, acked, migrated] = results; if (migrated && !externalDir) { throw new Error('External file system should be available.'); } // Check if acknowledge-prompt and migrate-pictures are needed. - if (migrated || !cca.models.FileSystem.externalDir) { + if (migrated || !externalDir) { return [false, false]; } // Check if any internal picture other than thumbnail needs migration. // Pictures taken by old Camera App may not have IMG_ or VID_ prefix. - var dir = cca.models.FileSystem.internalDir; - return cca.models.FileSystem.readDir_(dir) + return readDir(internalDir) .then((entries) => { - return entries.some( - (entry) => !cca.models.FileSystem.hasThumbnailPrefix_(entry)); + return entries.some((entry) => !hasThumbnailPrefix(entry)); }) .then((migrateNeeded) => { if (migrateNeeded) { @@ -183,118 +321,24 @@ }); }) .then((migrateNeeded) => { // Migrate pictures if needed. - const external = cca.models.FileSystem.externalDir !== null; - return !migrateNeeded ? external : - cca.models.FileSystem.migratePictures() - .then(doneMigrate) - .then(() => external); + const external = externalDir !== null; + return !migrateNeeded ? + external : + migratePictures().then(doneMigrate).then(() => external); }); -}; - -/** - * Reads file entries from the directory. - * @param {DirectoryEntry} dir Directory entry to be read. - * @return {!Promise<!Array<FileEntry>>} Promise for the read file entries. - * @private - */ -cca.models.FileSystem.readDir_ = function(dir) { - return !dir ? Promise.resolve([]) : new Promise((resolve, reject) => { - var dirReader = dir.createReader(); - var entries = []; - var readEntries = () => { - dirReader.readEntries((inEntries) => { - if (inEntries.length === 0) { - resolve(entries); - return; - } - entries = entries.concat(inEntries); - readEntries(); - }, reject); - }; - readEntries(); - }); -}; - -/** - * Migrates all picture-files from internal storage to external storage. - * @return {!Promise} Promise for the operation. - */ -cca.models.FileSystem.migratePictures = function() { - var internalDir = cca.models.FileSystem.internalDir; - var externalDir = cca.models.FileSystem.externalDir; - - var migratePicture = (pictureEntry, thumbnailEntry) => { - var name = cca.models.FileSystem.regulatePictureName(pictureEntry); - return cca.models.FileSystem.getFile(externalDir, name, true) - .then((entry) => { - return new Promise((resolve, reject) => { - pictureEntry.copyTo(externalDir, entry.name, (result) => { - if (result.name !== pictureEntry.name && thumbnailEntry) { - // Thumbnails can be recreated later if failing to rename them - // here. - thumbnailEntry.moveTo( - internalDir, - cca.models.FileSystem.getThumbnailName(result)); - } - pictureEntry.remove(() => {}); - resolve(); - }, reject); - }); - }); - }; - - return cca.models.FileSystem.readDir_(internalDir).then((internalEntries) => { - var pictureEntries = []; - var thumbnailEntriesByName = {}; - cca.models.FileSystem.parseInternalEntries_( - internalEntries, thumbnailEntriesByName, pictureEntries); - - var migrated = []; - for (var index = 0; index < pictureEntries.length; index++) { - var entry = pictureEntries[index]; - var thumbnailName = cca.models.FileSystem.getThumbnailName(entry); - var thumbnailEntry = thumbnailEntriesByName[thumbnailName]; - migrated.push(migratePicture(entry, thumbnailEntry)); - } - return Promise.all(migrated); - }); -}; - -/** - * Regulates the picture name to the desired format if it's in legacy formats. - * @param {FileEntry} entry Picture entry whose name to be regulated. - * @return {string} Name in the desired format. - */ -cca.models.FileSystem.regulatePictureName = function(entry) { - if (cca.models.FileSystem.hasVideoPrefix(entry) || - cca.models.FileSystem.hasImagePrefix_(entry)) { - var match = entry.name.match(/(\w{3}_\d{8}_\d{6})(?:_(\d+))?(\..+)?$/); - if (match) { - var idx = match[2] ? ' (' + match[2] + ')' : ''; - var ext = match[3] ? match[3].replace(/\.webm$/, '.mkv') : ''; - return match[1] + idx + ext; - } - } else { - // Early pictures are in legacy file name format (crrev.com/c/310064). - var match = entry.name.match(/(\d+).(?:\d+)/); - if (match) { - return (new cca.models.Filenamer(parseInt(match[1], 10))).newImageName(); - } - } - return entry.name; -}; +} /** * Saves the blob to the given file name. Name of the actually saved file * might be different from the given file name if the file already exists. - * @param {DirectoryEntry} dir Directory to be written into. + * @param {!DirectoryEntry} dir Directory to be written into. * @param {string} name Name of the file. * @param {!Blob} blob Data of the file to be saved. * @return {!Promise<?FileEntry>} Promise for the result. * @private */ -cca.models.FileSystem.saveToFile_ = function(dir, name, blob) { - return cca.models.FileSystem.getFile(dir, name, true).then((entry) => { +function saveToFile(dir, name, blob) { + return getFile(dir, name, true).then((entry) => { return new Promise((resolve, reject) => { entry.createWriter((fileWriter) => { fileWriter.onwriteend = () => resolve(entry); @@ -303,7 +347,7 @@ }, reject); }); }); -}; +} /** * Saves photo blob or metadata blob into predefined default location. @@ -311,69 +355,67 @@ * @param {string} filename Filename of the photo to be saved. * @return {!Promise<?FileEntry>} Promise for the result. */ -cca.models.FileSystem.saveBlob = function(blob, filename) { - const dir = - cca.models.FileSystem.externalDir || cca.models.FileSystem.internalDir; - return cca.models.FileSystem.saveToFile_(dir, filename, blob); -}; +export function saveBlob(blob, filename) { + const dir = externalDir || internalDir; + assert(dir !== null); + return saveToFile(dir, filename, blob); +} + /** * Gets metadata of the file. * @param {!FileEntry} file * @return {!Promise<!Object>} */ -cca.models.FileSystem.getMetadata = function(file) { +export function getMetadata(file) { return new Promise((resolve) => file.getMetadata(resolve)); -}; +} /** * Creates a file for saving temporary video recording result. * @return {!Promise<!FileEntry>} Newly created temporary file. * @throws {Error} If failed to create video temp file. */ -cca.models.FileSystem.createTempVideoFile = async function() { - const dir = - cca.models.FileSystem.externalDir || cca.models.FileSystem.internalDir; - const filename = new cca.models.Filenamer().newVideoName(); - const file = await cca.models.FileSystem.getFile(dir, filename, true); +export async function createTempVideoFile() { + const dir = externalDir || internalDir; + assert(dir !== null); + const filename = new Filenamer().newVideoName(); + const file = await getFile(dir, filename, true); if (file === null) { throw new Error('Failed to create video temp file.'); } return file; -}; +} /** - * @const {string} + * @type {string} */ -cca.models.FileSystem.PRIVATE_TEMPFILE_NAME = 'video-intent.mkv'; +const PRIVATE_TEMPFILE_NAME = 'video-intent.mkv'; /** * @return {!Promise<!FileEntry>} Newly created temporary file. * @throws {Error} If failed to create video temp file. */ -cca.models.FileSystem.createPrivateTempVideoFile = async function() { +export async function createPrivateTempVideoFile() { // TODO(inker): Handles running out of space case. - const dir = cca.models.FileSystem.internalTempDir; - const file = await cca.models.FileSystem.getFile( - dir, cca.models.FileSystem.PRIVATE_TEMPFILE_NAME, true); + const dir = internalTempDir; + assert(dir !== null); + const file = await getFile(dir, PRIVATE_TEMPFILE_NAME, true); if (file === null) { throw new Error('Failed to create private video temp file.'); } return file; -}; +} /** * Saves temporary video file to predefined default location. - * @param {FileEntry} tempfile Temporary video file to be saved. + * @param {!FileEntry} tempfile Temporary video file to be saved. * @param {string} filename Filename to be saved. - * @return {Promise<?FileEntry>} Saved video file. + * @return {!Promise<!FileEntry>} Saved video file. */ -cca.models.FileSystem.saveVideo = async function(tempfile, filename) { - var dir = - cca.models.FileSystem.externalDir || cca.models.FileSystem.internalDir; - if (!dir) { - return await null; - } +export async function saveVideo(tempfile, filename) { + const dir = externalDir || internalDir; + assert(dir !== null); // Non-null version for the Closure Compiler. let nonNullDir = dir; @@ -387,146 +429,18 @@ return new Promise( (resolve, reject) => tempfile.moveTo(nonNullDir, filename, resolve, reject)); -}; - -/** - * Gets the thumbnail name of the given picture. - * @param {FileEntry} entry Picture's file entry. - * @return {string} Thumbnail name. - */ -cca.models.FileSystem.getThumbnailName = function(entry) { - var thumbnailName = cca.models.FileSystem.THUMBNAIL_PREFIX + entry.name; - return (thumbnailName.substr(0, thumbnailName.lastIndexOf('.')) || - thumbnailName) + - '.jpg'; -}; - -/** - * Checks if the entry's name has the video prefix. - * @param {FileEntry} entry File entry. - * @return {boolean} Has the video prefix or not. - */ -cca.models.FileSystem.hasVideoPrefix = function(entry) { - return entry.name.startsWith(cca.models.Filenamer.VIDEO_PREFIX); -}; - -/** - * Checks if the entry's name has the image prefix. - * @param {FileEntry} entry File entry. - * @return {boolean} Has the image prefix or not. - * @private - */ -cca.models.FileSystem.hasImagePrefix_ = function(entry) { - return entry.name.startsWith(cca.models.Filenamer.IMAGE_PREFIX); -}; - -/** - * Checks if the entry's name has the thumbnail prefix. - * @param {FileEntry} entry File entry. - * @return {boolean} Has the thumbnail prefix or not. - * @private - */ -cca.models.FileSystem.hasThumbnailPrefix_ = function(entry) { - return entry.name.startsWith(cca.models.FileSystem.THUMBNAIL_PREFIX); -}; - -/** - * Parses and filters the internal entries to thumbnail and picture entries. - * @param {Array<FileEntry>} internalEntries Internal file entries. - * @param {Object<string, FileEntry>} thumbnailEntriesByName Result thumbanil - * entries mapped by thumbnail names, initially empty. - * @param {Array<FileEntry>=} pictureEntries Result picture entries, initially - * empty. - * @private - */ -cca.models.FileSystem.parseInternalEntries_ = function( - internalEntries, thumbnailEntriesByName, pictureEntries) { - var isThumbnail = cca.models.FileSystem.hasThumbnailPrefix_; - var thumbnailEntries = []; - if (pictureEntries) { - for (var index = 0; index < internalEntries.length; index++) { - if (isThumbnail(internalEntries[index])) { - thumbnailEntries.push(internalEntries[index]); - } else { - pictureEntries.push(internalEntries[index]); - } - } - } else { - thumbnailEntries = internalEntries.filter(isThumbnail); - } - for (var index = 0; index < thumbnailEntries.length; index++) { - var thumbnailEntry = thumbnailEntries[index]; - thumbnailEntriesByName[thumbnailEntry.name] = thumbnailEntry; - } -}; - -/** - * Gets the picture entries. - * @return {!Promise<!Array<!FileEntry>>} Promise for the picture entries. - */ -cca.models.FileSystem.getEntries = function() { - return cca.models.FileSystem.readDir_(cca.models.FileSystem.externalDir) - .then((entries) => { - return entries.filter((entry) => { - if (!cca.models.FileSystem.hasVideoPrefix(entry) && - !cca.models.FileSystem.hasImagePrefix_(entry)) { - return false; - } - return entry.name.match(/_(\d{8})_(\d{6})(?: \((\d+)\))?/); - }); - }); -}; - -/** - * Returns an URL for a picture. - * @param {FileEntry} entry File entry. - * @return {!Promise<string>} Promise for the result. - */ -cca.models.FileSystem.pictureURL = function(entry) { - return new Promise((resolve) => { - if (cca.models.FileSystem.externalDir) { - entry.file((file) => resolve(URL.createObjectURL(file))); - } else { - resolve(entry.toURL()); - } - }); -}; - -/** - * Gets the file by the given name, avoiding name conflicts if necessary. - * @param {DirectoryEntry} dir Directory to get the file from. - * @param {string} name File name. Result file may have a different name. - * @param {boolean} create True to create file, false otherwise. - * @return {!Promise<?FileEntry>} Promise for the result. - */ -cca.models.FileSystem.getFile = function(dir, name, create) { - return new Promise((resolve, reject) => { - var options = - create ? {create: true, exclusive: true} : {create: false}; - dir.getFile(name, options, resolve, reject); - }) - .catch((error) => { - if (create && error.name === 'InvalidModificationError') { - // Avoid name conflicts for creating files. - return cca.models.FileSystem.getFile( - dir, cca.models.FileSystem.incrementFileName_(name), create); - } else if (!create && error.name === 'NotFoundError') { - return null; - } - throw error; - }); -}; +} /** * Increments the file index of a given file name to avoid name conflicts. * @param {string} name File name. * @return {string} File name with incremented index. - * @private */ -cca.models.FileSystem.incrementFileName_ = function(name) { - var [base, ext] = ['', '']; - var idx = 0; - var match = name.match(/^([^.]+)(\..+)?$/); +function incrementFileName(name) { + let base = ''; + let ext = ''; + let idx = 0; + let match = name.match(/^([^.]+)(\..+)?$/); if (match) { base = match[1]; ext = match[2]; @@ -537,4 +451,81 @@ } } return base + ' (' + (idx + 1) + ')' + ext; -}; +} + +/** + * Gets the file by the given name, avoiding name conflicts if necessary. + * @param {!DirectoryEntry} dir Directory to get the file from. + * @param {string} name File name. Result file may have a different name. + * @param {boolean} create True to create file, false otherwise. + * @return {!Promise<?FileEntry>} Promise for the result. + */ +export function getFile(dir, name, create) { + return new Promise((resolve, reject) => { + const options = + create ? {create: true, exclusive: true} : {create: false}; + dir.getFile(name, options, resolve, reject); + }) + .catch((error) => { + if (create && error.name === 'InvalidModificationError') { + // Avoid name conflicts for creating files. + return getFile(dir, incrementFileName(name), create); + } else if (!create && error.name === 'NotFoundError') { + return null; + } + throw error; + }); +} + +/** + * Gets the picture entries. + * @return {!Promise<!Array<!FileEntry>>} Promise for the picture entries. + */ +export function getEntries() { + return readDir(externalDir).then((entries) => { + return entries.filter((entry) => { + if (!hasVideoPrefix(entry) && !hasImagePrefix(entry)) { + return false; + } + return entry.name.match(/_(\d{8})_(\d{6})(?: \((\d+)\))?/); + }); + }); +} + +/** + * Returns an URL for a picture. + * @param {!FileEntry} entry File entry. + * @return {!Promise<string>} Promise for the result. + */ +export function pictureURL(entry) { + return new Promise((resolve) => { + if (externalDir) { + entry.file((file) => resolve(URL.createObjectURL(file))); + } else { + resolve(entry.toURL()); + } + }); +} + +/** @const */ +cca.models.FileSystem.hasVideoPrefix = hasVideoPrefix; +/** @const */ +cca.models.FileSystem.getExternalDirectory = getExternalDirectory; +/** @const */ +cca.models.FileSystem.initialize = initialize; +/** @const */ +cca.models.FileSystem.saveBlob = saveBlob; +/** @const */ +cca.models.FileSystem.getMetadata = getMetadata; +/** @const */ +cca.models.FileSystem.createTempVideoFile = createTempVideoFile; +/** @const */ +cca.models.FileSystem.createPrivateTempVideoFile = createPrivateTempVideoFile; +/** @const */ +cca.models.FileSystem.saveVideo = saveVideo; +/** @const */ +cca.models.FileSystem.getFile = getFile; +/** @const */ +cca.models.FileSystem.getEntries = getEntries; +/** @const */ +cca.models.FileSystem.pictureURL = pictureURL;
diff --git a/chrome/browser/resources/chromeos/camera/src/js/namespace.js b/chrome/browser/resources/chromeos/camera/src/js/namespace.js index 5c50974..24571d9 100644 --- a/chrome/browser/resources/chromeos/camera/src/js/namespace.js +++ b/chrome/browser/resources/chromeos/camera/src/js/namespace.js
@@ -11,7 +11,9 @@ var cca = { device: {}, intent: {}, - models: {}, + models: { + FileSystem: {}, + }, mojo: {}, nav: {}, perf: {},
diff --git a/chrome/browser/resources/chromeos/camera/src/views/main.html b/chrome/browser/resources/chromeos/camera/src/views/main.html index 90aa4a9f..302358f 100644 --- a/chrome/browser/resources/chromeos/camera/src/views/main.html +++ b/chrome/browser/resources/chromeos/camera/src/views/main.html
@@ -25,10 +25,10 @@ <script type="module" src="../js/device/error.js"></script> <script type="module" src="../js/device/camera3_device_info.js"></script> <script type="module" src="../js/device/constraints_preferrer.js"></script> - <script defer src="../js/device/device_info_updater.js"></script> + <script type="module" src="../js/device/device_info_updater.js"></script> <script type="module" src="../js/models/filenamer.js"></script> <script defer src="../js/gallerybutton.js"></script> - <script defer src="../js/models/filesystem.js"></script> + <script type="module" src="../js/models/filesystem.js"></script> <script defer src="../js/models/result_saver.js"></script> <script defer src="../js/models/video_saver_interface.js"></script> <script defer src="../js/models/file_video_saver.js"></script>
diff --git a/chrome/browser/resources/print_preview/ui/highlight_utils.js b/chrome/browser/resources/print_preview/ui/highlight_utils.js index dfc0eb2f..a2668db 100644 --- a/chrome/browser/resources/print_preview/ui/highlight_utils.js +++ b/chrome/browser/resources/print_preview/ui/highlight_utils.js
@@ -40,20 +40,19 @@ if (query.test(textContent)) { // Don't highlight <select> nodes, yellow rectangles can't be // displayed within an <option>. - if (node.parentNode.nodeName !== 'OPTION') { - result.highlights.push(highlight(node, textContent.split(query))); - } else { - const selectNode = node.parentNode.parentNode; + if (node.parentNode.nodeName === 'OPTION') { // The bubble should be parented by the select node's parent. // Note: The bubble's ::after element, a yellow arrow, will not // appear correctly in print preview without SPv175 enabled. See // https://crbug.com/817058. const bubble = highlightControlWithBubble( - /** @type {!HTMLElement} */ (assert(selectNode.parentNode)), - textContent.match(query)[0]); + /** @type {!HTMLElement} */ (assert(node.parentNode.parentNode)), + textContent.match(query)[0], /*horizontallyCenter=*/ true); if (bubble) { result.bubbles.push(bubble); } + } else { + result.highlights.push(highlight(node, textContent.split(query))); } } });
diff --git a/chrome/browser/resources/settings/BUILD.gn b/chrome/browser/resources/settings/BUILD.gn index 21d65d4..1e7f5c5 100644 --- a/chrome/browser/resources/settings/BUILD.gn +++ b/chrome/browser/resources/settings/BUILD.gn
@@ -179,8 +179,10 @@ js_library("search_settings") { deps = [ + "//ui/webui/resources/js:assert", "//ui/webui/resources/js:cr", "//ui/webui/resources/js:search_highlight_utils", + "//ui/webui/resources/js:util", ] externs_list = [ "$externs_path/pending_polymer.js" ] }
diff --git a/chrome/browser/resources/settings/search_settings.js b/chrome/browser/resources/settings/search_settings.js index 60facec..24c584b 100644 --- a/chrome/browser/resources/settings/search_settings.js +++ b/chrome/browser/resources/settings/search_settings.js
@@ -103,11 +103,26 @@ bubbles.push(bubble); } - // Don't highlight <select> nodes, yellow rectangles can't be - // displayed within an <option>. - // TODO(dpapad): highlight <select> controls with a search bubble - // instead. - if (node.parentNode.nodeName != 'OPTION') { + if (node.parentNode.nodeName === 'OPTION') { + const select = node.parentNode.parentNode; + assert(select.nodeName === 'SELECT'); + + // TODO(crbug.com/355446): support showing bubbles inside subpages. + // Currently, they're incorrectly positioned and there's no great + // signal at which to know when to reposition them (because every + // page asynchronously loads/renders things differently). + const isSubpage = n => n.nodeName === 'SETTINGS-SUBPAGE'; + if (findAncestor(select, isSubpage, true)) { + return; + } + + const bubble = cr.search_highlight_utils.highlightControlWithBubble( + select, textContent.match(request.regExp)[0], + /*horizontallyCenter=*/ true); + if (bubble) { + bubbles.push(bubble); + } + } else { request.addTextObserver(node); highlights.push(cr.search_highlight_utils.highlight( node, textContent.split(request.regExp)));
diff --git a/chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_model_browsertest_win.cc b/chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_model_browsertest_win.cc index 62b2fa7c..6badcd77 100644 --- a/chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_model_browsertest_win.cc +++ b/chrome/browser/safe_browsing/settings_reset_prompt/settings_reset_prompt_model_browsertest_win.cc
@@ -54,48 +54,48 @@ // Extension manifests to override settings. const char kManifestNoOverride[] = - "{" - " 'name': 'Safe Extension'," - " 'version': '1'," - " 'manifest_version': 2" - "}"; + R"({ + "name": "Safe Extension", + "version": "1", + "manifest_version": 2 + })"; const char kManifestToOverrideHomepage[] = - "{" - " 'name': 'Homepage Extension'," - " 'version': '1'," - " 'manifest_version': 2," - " 'chrome_settings_overrides' : {" - " 'homepage': '%s'" - " }" - "}"; + R"({ + "name": "Homepage Extension", + "version": "1", + "manifest_version": 2, + "chrome_settings_overrides" : { + "homepage": "%s" + } + })"; const char kManifestToOverrideSearch[] = - "{" - " 'name': 'Search Extension'," - " 'version': '0.1'," - " 'manifest_version': 2," - " 'chrome_settings_overrides': {" - " 'search_provider': {" - " 'name': 'name'," - " 'keyword': 'keyword'," - " 'search_url': '%s'," - " 'favicon_url': 'http://someplace.com/favicon.ico'," - " 'encoding': 'UTF-8'," - " 'is_default': true" - " }" - " }" - "}"; + R"({ + "name": "Search Extension", + "version": "0.1", + "manifest_version": 2, + "chrome_settings_overrides": { + "search_provider": { + "name": "name", + "keyword": "keyword", + "search_url": "%s", + "favicon_url": "http://someplace.com/favicon.ico", + "encoding": "UTF-8", + "is_default": true + } + } + })"; const char kManifestToOverrideStartupUrls[] = - "{" - " 'name': 'Startup URLs Extension'," - " 'version': '1'," - " 'manifest_version': 2," - " 'chrome_settings_overrides' : {" - " 'startup_pages': ['%s']" - " }" - "}"; + R"({ + "name": "Startup URLs Extension", + "version": "1", + "manifest_version": 2, + "chrome_settings_overrides" : { + "startup_pages": ["%s"] + } + })"; class SettingsResetPromptModelBrowserTest : public extensions::ExtensionBrowserTest { @@ -183,7 +183,7 @@ void LoadManifest(const std::string& manifest, const Extension** out_extension) { extensions::TestExtensionDir extension_dir; - extension_dir.WriteManifestWithSingleQuotes(manifest); + extension_dir.WriteManifest(manifest); *out_extension = LoadExtension(extension_dir.UnpackedPath()); ASSERT_TRUE(*out_extension); }
diff --git a/chrome/browser/signin/signin_ui_util_unittest.cc b/chrome/browser/signin/signin_ui_util_unittest.cc index 45f2c90..d5477ab2 100644 --- a/chrome/browser/signin/signin_ui_util_unittest.cc +++ b/chrome/browser/signin/signin_ui_util_unittest.cc
@@ -471,8 +471,8 @@ active_contents->GetVisibleURL()); } -// TODO(https://crbug.com/1014790): Timeout on Mac10.12. -#if defined(OS_MACOSX) +// TODO(https://crbug.com/1014790): Timeout on Mac10.12 and Win7 x64. +#if defined(OS_MACOSX) || defined(OS_WIN) #define MAYBE_GetAccountsForDicePromos DISABLED_GetAccountsForDicePromos #else #define MAYBE_GetAccountsForDicePromos GetAccountsForDicePromos @@ -568,8 +568,8 @@ *profile_manager()->profile_attributes_storage(), profile())); } -// TODO(https://crbug.com/1014790): Timeout on Mac10.12. -#if defined(OS_MACOSX) +// TODO(https://crbug.com/1014790): Timeout on Mac10.12 and Win7 x64. +#if defined(OS_MACOSX) || defined(OS_WIN) #define MAYBE_ShouldShowAnimatedIdentityOnOpeningWindow_ReturnsFalseForSingleProfileSingleSignin \ DISABLED_ShouldShowAnimatedIdentityOnOpeningWindow_ReturnsFalseForSingleProfileSingleSignin #else
diff --git a/chrome/browser/ui/extensions/blocked_action_bubble_browsertest.cc b/chrome/browser/ui/extensions/blocked_action_bubble_browsertest.cc index b339dd3..9ba1e34 100644 --- a/chrome/browser/ui/extensions/blocked_action_bubble_browsertest.cc +++ b/chrome/browser/ui/extensions/blocked_action_bubble_browsertest.cc
@@ -2,7 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "base/feature_list.h" #include "base/macros.h" +#include "base/test/scoped_feature_list.h" #include "chrome/browser/extensions/extension_browsertest.h" #include "chrome/browser/extensions/scripting_permissions_modifier.h" #include "chrome/browser/ui/browser.h" @@ -12,6 +14,7 @@ #include "chrome/browser/ui/test/test_browser_dialog.h" #include "chrome/browser/ui/toolbar/toolbar_action_view_controller.h" #include "chrome/browser/ui/toolbar/toolbar_actions_bar.h" +#include "chrome/browser/ui/ui_features.h" #include "chrome/test/base/ui_test_utils.h" #include "content/public/browser/web_contents.h" #include "content/public/test/test_navigation_observer.h" @@ -28,6 +31,7 @@ void ShowUi(const std::string& name) override; private: + base::test::ScopedFeatureList scoped_feature_list_; base::AutoReset<bool> disable_toolbar_animations_; DISALLOW_COPY_AND_ASSIGN(ExtensionBlockedActionsBubbleTest); @@ -36,7 +40,11 @@ ExtensionBlockedActionsBubbleTest::ExtensionBlockedActionsBubbleTest() : disable_toolbar_animations_( &ToolbarActionsBar::disable_animations_for_testing_, - true) {} + true) { + // This code path only works for the old toolbar. The new toolbar is + // exercised in extensions_menu_view_browsertest.cc. + scoped_feature_list_.InitAndDisableFeature(features::kExtensionsToolbarMenu); +} ExtensionBlockedActionsBubbleTest::~ExtensionBlockedActionsBubbleTest() = default;
diff --git a/chrome/browser/ui/extensions/extension_action_view_controller.cc b/chrome/browser/ui/extensions/extension_action_view_controller.cc index 87f066a..362af42c9 100644 --- a/chrome/browser/ui/extensions/extension_action_view_controller.cc +++ b/chrome/browser/ui/extensions/extension_action_view_controller.cc
@@ -331,7 +331,7 @@ } bool ExtensionActionViewController::GetExtensionCommand( - extensions::Command* command) { + extensions::Command* command) const { DCHECK(command); if (!ExtensionIsValid()) return false; @@ -345,6 +345,29 @@ extension_->id(), CommandService::ACTIVE, command, NULL); } +bool ExtensionActionViewController::CanHandleAccelerators() const { + if (!ExtensionIsValid()) + return false; + +#if DCHECK_IS_ON() + { + extensions::Command command; + DCHECK(GetExtensionCommand(&command)); + } +#endif + + // Page action accelerators are enabled if and only if the page action is + // enabled ("visible" in legacy terms) on the given tab. Other actions can + // always accept accelerators. + // TODO(devlin): Have all actions behave similarly; this should likely mean + // always checking IsEnabled(). It's weird to use a keyboard shortcut on a + // disabled action (in most cases, this will result in opening the context + // menu). + if (extension_action_->action_type() == extensions::ActionInfo::TYPE_PAGE) + return IsEnabled(view_delegate_->GetCurrentWebContents()); + return true; +} + std::unique_ptr<IconWithBadgeImageSource> ExtensionActionViewController::GetIconImageSourceForTesting( content::WebContents* web_contents,
diff --git a/chrome/browser/ui/extensions/extension_action_view_controller.h b/chrome/browser/ui/extensions/extension_action_view_controller.h index 73e8e39c..1750607 100644 --- a/chrome/browser/ui/extensions/extension_action_view_controller.h +++ b/chrome/browser/ui/extensions/extension_action_view_controller.h
@@ -79,7 +79,14 @@ // Populates |command| with the command associated with |extension|, if one // exists. Returns true if |command| was populated. - bool GetExtensionCommand(extensions::Command* command); + bool GetExtensionCommand(extensions::Command* command) const; + + // Returns true if this controller can handle accelerators (i.e., keyboard + // commands) on the currently-active WebContents. + // This must only be called if the extension has an associated command. + // TODO(devlin): Move accelerator logic out of the platform delegate and into + // this class. + bool CanHandleAccelerators() const; const extensions::Extension* extension() const { return extension_.get(); } Browser* browser() { return browser_; }
diff --git a/chrome/browser/ui/extensions/extension_message_bubble_browsertest.cc b/chrome/browser/ui/extensions/extension_message_bubble_browsertest.cc index 2c0212a3..34e8695 100644 --- a/chrome/browser/ui/extensions/extension_message_bubble_browsertest.cc +++ b/chrome/browser/ui/extensions/extension_message_bubble_browsertest.cc
@@ -60,17 +60,18 @@ const std::string& settings_override_value) { DCHECK(!custom_extension_dir_); custom_extension_dir_ = std::make_unique<extensions::TestExtensionDir>(); - std::string manifest = base::StringPrintf( - "{\n" - " 'name': 'settings override',\n" - " 'version': '0.1',\n" - " 'manifest_version': 2,\n" - " 'description': 'controls settings',\n" - " 'chrome_settings_overrides': {\n" - " %s\n" - " }\n" - "}", settings_override_value.c_str()); - custom_extension_dir_->WriteManifestWithSingleQuotes(manifest); + constexpr char kManifestTemplate[] = + R"({ + "name": "settings override", + "version": "0.1", + "manifest_version": 2, + "description": "controls settings", + "chrome_settings_overrides": { + %s + } + })"; + custom_extension_dir_->WriteManifest( + base::StringPrintf(kManifestTemplate, settings_override_value.c_str())); ASSERT_TRUE(LoadExtension(custom_extension_dir_->UnpackedPath())); } @@ -279,7 +280,7 @@ void ExtensionMessageBubbleBrowserTest::TestControlledHomeBubbleShown() { browser()->profile()->GetPrefs()->SetBoolean(prefs::kShowHomeButton, true); - const char kHomePage[] = "'homepage': 'https://www.google.com'\n"; + const char kHomePage[] = R"("homepage": "https://www.google.com")"; AddSettingsOverrideExtension(kHomePage); CheckBubbleIsNotPresent(browser(), false, false); @@ -294,14 +295,14 @@ void ExtensionMessageBubbleBrowserTest::TestControlledSearchBubbleShown() { const char kSearchProvider[] = - "'search_provider': {\n" - " 'search_url': 'https://www.google.com/search?q={searchTerms}',\n" - " 'is_default': true,\n" - " 'favicon_url': 'https://www.google.com/favicon.icon',\n" - " 'keyword': 'TheGoogs',\n" - " 'name': 'Google',\n" - " 'encoding': 'UTF-8'\n" - "}\n"; + R"("search_provider": { + "search_url": "https://www.google.com/search?q={searchTerms}", + "is_default": true, + "favicon_url": "https://www.google.com/favicon.icon", + "keyword": "TheGoogs", + "name": "Google", + "encoding": "UTF-8" + })"; AddSettingsOverrideExtension(kSearchProvider); CheckBubbleIsNotPresent(browser(), false, false);
diff --git a/chrome/browser/ui/messages/android/java/res/layout/snackbar.xml b/chrome/browser/ui/messages/android/java/res/layout/snackbar.xml index 54a4a45..d77c874 100644 --- a/chrome/browser/ui/messages/android/java/res/layout/snackbar.xml +++ b/chrome/browser/ui/messages/android/java/res/layout/snackbar.xml
@@ -20,30 +20,32 @@ android:background="@drawable/infobar_shadow_top" /> <View - android:id="@+id/snackbar_shadow_left" + android:id="@id/snackbar_shadow_left" android:layout_width="@dimen/snackbar_shadow_height" android:layout_height="wrap_content" android:layout_alignParentStart="true" android:layout_alignTop="@id/snackbar_shadow_top" + android:layout_alignBottom="@+id/snackbar" android:background="@drawable/infobar_shadow_left" android:visibility="gone" /> <View - android:id="@+id/snackbar_shadow_right" + android:id="@id/snackbar_shadow_right" android:layout_width="@dimen/snackbar_shadow_height" android:layout_height="wrap_content" android:layout_alignParentEnd="true" android:layout_alignTop="@id/snackbar_shadow_top" + android:layout_alignBottom="@+id/snackbar" android:background="@drawable/infobar_shadow_left" android:scaleX="-1" android:visibility="gone" /> <LinearLayout - android:id="@+id/snackbar" + android:id="@id/snackbar" android:layout_width="match_parent" android:layout_height="wrap_content" android:minHeight="@dimen/snackbar_min_height" - android:layout_below="@+id/snackbar_shadow_top" + android:layout_below="@id/snackbar_shadow_top" android:layout_toEndOf="@id/snackbar_shadow_left" android:layout_toStartOf="@id/snackbar_shadow_right" android:orientation="horizontal" >
diff --git a/chrome/browser/ui/search/local_ntp_doodle_browsertest.cc b/chrome/browser/ui/search/local_ntp_doodle_browsertest.cc index 801fcb67..22d20bb4 100644 --- a/chrome/browser/ui/search/local_ntp_doodle_browsertest.cc +++ b/chrome/browser/ui/search/local_ntp_doodle_browsertest.cc
@@ -82,6 +82,26 @@ } } +// A simple class to add a test failure if any console message comes in for +// the given WebContents. +class FailOnConsoleMessage : public content::WebContentsObserver { + public: + explicit FailOnConsoleMessage(content::WebContents* web_contents) + : WebContentsObserver(web_contents) {} + FailOnConsoleMessage(const FailOnConsoleMessage& other) = delete; + FailOnConsoleMessage& operator=(const FailOnConsoleMessage& other) = delete; + ~FailOnConsoleMessage() override = default; + + private: + // content::WebContentsObserver: + void OnDidAddMessageToConsole(blink::mojom::ConsoleMessageLevel log_level, + const base::string16& message, + int32_t line_no, + const base::string16& source_id) override { + ADD_FAILURE() << "Unexpected console message: " << message; + } +}; + } // namespace class LocalNTPDoodleTest : public InProcessBrowserTest { @@ -218,8 +238,8 @@ } void WaitForFadeIn(content::WebContents* tab, const std::string& id) { - content::ConsoleObserverDelegate console_observer(tab, "WaitForFadeIn"); - tab->SetDelegate(&console_observer); + content::WebContentsConsoleObserver console_observer(tab); + console_observer.SetPattern("WaitForFadeIn"); bool result = false; if (!instant_test_utils::GetBoolFromJS( @@ -251,8 +271,8 @@ } void WaitForLogoSwap(content::WebContents* tab, const std::string& id) { - content::ConsoleObserverDelegate console_observer(tab, "WaitForFadeIn"); - tab->SetDelegate(&console_observer); + content::WebContentsConsoleObserver console_observer(tab); + console_observer.SetPattern("WaitForFadeIn"); bool result = false; if (!instant_test_utils::GetBoolFromJS( @@ -327,15 +347,14 @@ // Open a new blank tab, then go to NTP and listen for console messages. content::WebContents* active_tab = local_ntp_test_utils::OpenNewTab(browser(), GURL("about:blank")); - content::ConsoleObserverDelegate console_observer(active_tab, "*"); - active_tab->SetDelegate(&console_observer); + + FailOnConsoleMessage console_observer(active_tab); base::HistogramTester histograms; ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUINewTabURL)); EXPECT_THAT(GetDimension(active_tab, "fakebox", "top"), Eq(kFakeboxTopPx)); EXPECT_THAT(GetComputedOpacity(active_tab, "logo-default"), Eq(1.0)); EXPECT_THAT(GetComputedOpacity(active_tab, "logo-doodle"), Eq(0.0)); - EXPECT_THAT(console_observer.message(), IsEmpty()); histograms.ExpectTotalCount("NewTabPage.LogoShown", 0); histograms.ExpectTotalCount("NewTabPage.LogoShown.FromCache", 0); @@ -353,15 +372,13 @@ // Open a new blank tab, then go to NTP and listen for console messages. content::WebContents* active_tab = local_ntp_test_utils::OpenNewTab(browser(), GURL("about:blank")); - content::ConsoleObserverDelegate console_observer(active_tab, "*"); - active_tab->SetDelegate(&console_observer); + FailOnConsoleMessage console_observer(active_tab); base::HistogramTester histograms; ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUINewTabURL)); EXPECT_THAT(GetDimension(active_tab, "fakebox", "top"), Eq(kFakeboxTopPx)); EXPECT_THAT(GetComputedOpacity(active_tab, "logo-default"), Eq(1.0)); EXPECT_THAT(GetComputedOpacity(active_tab, "logo-doodle"), Eq(0.0)); - EXPECT_THAT(console_observer.message(), IsEmpty()); histograms.ExpectTotalCount("NewTabPage.LogoShown", 0); histograms.ExpectTotalCount("NewTabPage.LogoShown.FromCache", 0); @@ -384,8 +401,7 @@ // Open a new blank tab, then go to NTP and listen for console messages. content::WebContents* active_tab = local_ntp_test_utils::OpenNewTab(browser(), GURL("about:blank")); - content::ConsoleObserverDelegate console_observer(active_tab, "*"); - active_tab->SetDelegate(&console_observer); + FailOnConsoleMessage console_observer(active_tab); base::HistogramTester histograms; ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUINewTabURL)); @@ -399,7 +415,6 @@ EXPECT_THAT(GetElementProperty(active_tab, "logo-doodle-image", "title"), Eq<std::string>("Chromium")); // TODO(sfiera): check href by clicking on button. - EXPECT_THAT(console_observer.message(), IsEmpty()); histograms.ExpectTotalCount("NewTabPage.LogoShown", 1); histograms.ExpectBucketCount("NewTabPage.LogoShown", kLogoImpressionStatic, @@ -763,8 +778,7 @@ // Open a new blank tab, then go to NTP and listen for console messages. content::WebContents* active_tab = local_ntp_test_utils::OpenNewTab(browser(), GURL("about:blank")); - content::ConsoleObserverDelegate console_observer(active_tab, "*"); - active_tab->SetDelegate(&console_observer); + FailOnConsoleMessage console_observer(active_tab); base::HistogramTester histograms; ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUINewTabURL)); @@ -802,8 +816,7 @@ // Open a new blank tab, then go to NTP and listen for console messages. content::WebContents* active_tab = local_ntp_test_utils::OpenNewTab(browser(), GURL("about:blank")); - content::ConsoleObserverDelegate console_observer(active_tab, "*"); - active_tab->SetDelegate(&console_observer); + FailOnConsoleMessage console_observer(active_tab); ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUINewTabURL)); EXPECT_FALSE(ElementExists(active_tab, "ddlsb")); @@ -832,8 +845,7 @@ // Open a new blank tab, then go to NTP and listen for console messages. content::WebContents* active_tab = local_ntp_test_utils::OpenNewTab(browser(), GURL("about:blank")); - content::ConsoleObserverDelegate console_observer(active_tab, "*"); - active_tab->SetDelegate(&console_observer); + FailOnConsoleMessage console_observer(active_tab); ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUINewTabURL)); EXPECT_FALSE(ElementExists(active_tab, "ddlsb")); @@ -862,8 +874,7 @@ // Open a new blank tab, then go to NTP and listen for console messages. content::WebContents* active_tab = local_ntp_test_utils::OpenNewTab(browser(), GURL("about:blank")); - content::ConsoleObserverDelegate console_observer(active_tab, "*"); - active_tab->SetDelegate(&console_observer); + FailOnConsoleMessage console_observer(active_tab); ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUINewTabURL)); EXPECT_FALSE(DialogIsOpen(active_tab, "ddlsd")); @@ -1249,9 +1260,7 @@ // Open a new blank tab, then go to NTP and listen for console messages. content::WebContents* active_tab = local_ntp_test_utils::OpenNewTab(browser(), GURL("about:blank")); - content::WebContentsDelegate* original_delegate = active_tab->GetDelegate(); - content::ConsoleObserverDelegate console_observer(active_tab, "*"); - active_tab->SetDelegate(&console_observer); + FailOnConsoleMessage console_observer(active_tab); ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUINewTabURL)); ASSERT_THAT(GetComputedOpacity(active_tab, "logo-doodle"), Eq(1.0)); @@ -1260,9 +1269,6 @@ std::string response = WaitForDdllogResponse(active_tab, 1); EXPECT_EQ("target_url_params a=b&c=d", response); - // Before clicking on the Doodle, re-attach the original WebContentsDelegate, - // otherwise setting 'window.location' doesn't have any effect. - active_tab->SetDelegate(original_delegate); content::TestNavigationObserver nav_observer(active_tab); ASSERT_TRUE(content::ExecuteScript( active_tab, "document.getElementById('logo-doodle-button').click();")); @@ -1273,8 +1279,6 @@ ASSERT_TRUE(instant_test_utils::GetStringFromJS( active_tab, "document.location.href", &target_url)); EXPECT_EQ(on_click_url.spec() + "?a=b&c=d", target_url); - - EXPECT_THAT(console_observer.message(), IsEmpty()); } IN_PROC_BROWSER_TEST_F(LocalNTPDoodleTest, ShouldLogForAnimatedDoodle) { @@ -1305,9 +1309,7 @@ // Open a new blank tab, then go to NTP and listen for console messages. content::WebContents* active_tab = local_ntp_test_utils::OpenNewTab(browser(), GURL("about:blank")); - content::WebContentsDelegate* original_delegate = active_tab->GetDelegate(); - content::ConsoleObserverDelegate console_observer(active_tab, "*"); - active_tab->SetDelegate(&console_observer); + FailOnConsoleMessage console_observer(active_tab); ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUINewTabURL)); ASSERT_THAT(GetComputedOpacity(active_tab, "logo-doodle"), Eq(1.0)); @@ -1328,10 +1330,6 @@ std::string anim_response = WaitForDdllogResponse(active_tab, 2); EXPECT_EQ("target_url_params a=b&c=d", anim_response); - // Before clicking on the Doodle, re-attach the original WebContentsDelegate, - // otherwise setting 'window.location' doesn't seem to have any effect for - // some reason. - active_tab->SetDelegate(original_delegate); content::TestNavigationObserver nav_observer(active_tab); ASSERT_TRUE(content::ExecuteScript( active_tab, "document.getElementById('logo-doodle-button').click();")); @@ -1342,8 +1340,6 @@ ASSERT_TRUE(instant_test_utils::GetStringFromJS( active_tab, "document.location.href", &target_url)); EXPECT_EQ(on_click_url.spec() + "?a=b&c=d", target_url); - - EXPECT_THAT(console_observer.message(), IsEmpty()); } IN_PROC_BROWSER_TEST_F(LocalNTPDoodleTest, ShouldNotMoveFakeboxForIframeSizes) {
diff --git a/chrome/browser/ui/toolbar/toolbar_actions_bar_unittest.cc b/chrome/browser/ui/toolbar/toolbar_actions_bar_unittest.cc index b8d73f5..a20d6252 100644 --- a/chrome/browser/ui/toolbar/toolbar_actions_bar_unittest.cc +++ b/chrome/browser/ui/toolbar/toolbar_actions_bar_unittest.cc
@@ -619,13 +619,13 @@ extensions::ExtensionRegistry::Get(profile()); extensions::TestExtensionDir ext_dir; - const char kManifest[] = - "{" - " 'name': 'Test'," - " 'version': '1'," - " 'manifest_version': 2" - "}"; - ext_dir.WriteManifestWithSingleQuotes(kManifest); + constexpr char kManifest[] = + R"({ + "name": "Test", + "version": "1", + "manifest_version": 2 + })"; + ext_dir.WriteManifest(kManifest); scoped_refptr<extensions::UnpackedInstaller> installer = extensions::UnpackedInstaller::Create(service); @@ -657,15 +657,15 @@ // Replace the extension's valid manifest with one containing errors. In this // case, the error is that both the 'browser_action' and 'page_action' keys // are specified instead of only one. - const char kManifestWithErrors[] = - "{" - " 'name': 'Test'," - " 'version': '1'," - " 'manifest_version': 2," - " 'page_action' : {}," - " 'browser_action' : {}" - "}"; - ext_dir.WriteManifestWithSingleQuotes(kManifestWithErrors); + constexpr char kManifestWithErrors[] = + R"({ + "name": "Test", + "version": "1", + "manifest_version": 2, + "page_action" : {}, + "browser_action" : {} + })"; + ext_dir.WriteManifest(kManifestWithErrors); // Reload the extension again. Check that the updated extension cannot be // loaded due to the manifest errors.
diff --git a/chrome/browser/ui/views/extensions/extension_action_platform_delegate_views.cc b/chrome/browser/ui/views/extensions/extension_action_platform_delegate_views.cc index ecaa5c4..7d12a54 100644 --- a/chrome/browser/ui/views/extensions/extension_action_platform_delegate_views.cc +++ b/chrome/browser/ui/views/extensions/extension_action_platform_delegate_views.cc
@@ -117,11 +117,7 @@ bool ExtensionActionPlatformDelegateViews::AcceleratorPressed( const ui::Accelerator& accelerator) { - // We shouldn't be handling any accelerators if the view is hidden, unless - // this is a browser action. - DCHECK(controller_->extension_action()->action_type() == - ActionInfo::TYPE_BROWSER || - GetDelegateViews()->GetAsView()->GetVisible()); + DCHECK(controller_->CanHandleAccelerators()); // Normal priority shortcuts must be handled via standard browser commands to // be processed at the proper time. @@ -137,12 +133,7 @@ } bool ExtensionActionPlatformDelegateViews::CanHandleAccelerators() const { - // Page actions can only handle accelerators when they are visible. - // Browser actions can handle accelerators even when not visible, since they - // might be hidden in an overflow menu. - return controller_->extension_action()->action_type() == ActionInfo::TYPE_PAGE - ? GetDelegateViews()->GetAsView()->GetVisible() - : true; + return controller_->CanHandleAccelerators(); } void ExtensionActionPlatformDelegateViews::UnregisterCommand(
diff --git a/chrome/browser/ui/views/extensions/extensions_menu_view_browsertest.cc b/chrome/browser/ui/views/extensions/extensions_menu_view_browsertest.cc index 7b82f42e..f861dd60 100644 --- a/chrome/browser/ui/views/extensions/extensions_menu_view_browsertest.cc +++ b/chrome/browser/ui/views/extensions/extensions_menu_view_browsertest.cc
@@ -25,14 +25,18 @@ #include "chrome/common/webui_url_constants.h" #include "chrome/test/base/ui_test_utils.h" #include "content/public/test/test_navigation_observer.h" +#include "extensions/common/extension.h" +#include "extensions/test/test_extension_dir.h" #include "net/dns/mock_host_resolver.h" #include "ui/views/layout/animating_layout_manager.h" #include "ui/views/test/widget_test.h" class ExtensionsMenuViewBrowserTest : public DialogBrowserTest { protected: + Profile* profile() { return browser()->profile(); } + void LoadTestExtension(const std::string& extension) { - extensions::ChromeTestExtensionLoader loader(browser()->profile()); + extensions::ChromeTestExtensionLoader loader(profile()); base::FilePath test_data_dir; base::PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir); extensions_.push_back( @@ -50,6 +54,34 @@ } void ShowUi(const std::string& name) override { + ui_test_name_ = name; + + ClickExtensionsMenuButton(); + + if (name == "ReloadPageBubble") { + TriggerSingleExtensionButton(); + } + } + + bool VerifyUi() override { + DialogBrowserTest::VerifyUi(); + + if (ui_test_name_ == "ReloadPageBubble") { + // Clicking the extension should close the extensions menu, pop out the + // extension, and display the "reload this page" bubble. + ExtensionsToolbarContainer* const container = + BrowserView::GetBrowserViewForBrowser(browser()) + ->toolbar() + ->extensions_container(); + EXPECT_TRUE(container->action_bubble_public_for_testing()); + EXPECT_FALSE(container->GetPoppedOutAction()); + EXPECT_FALSE(ExtensionsMenuView::IsShowing()); + } + + return true; + } + + void ClickExtensionsMenuButton() { ui::MouseEvent click_event(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(), base::TimeTicks(), ui::EF_LEFT_MOUSE_BUTTON, 0); BrowserView::GetBrowserViewForBrowser(browser()) @@ -103,6 +135,7 @@ loop.Run(); } + std::string ui_test_name_; base::test::ScopedFeatureList scoped_feature_list_; std::vector<scoped_refptr<const extensions::Extension>> extensions_; }; @@ -118,6 +151,50 @@ ShowAndVerifyUi(); } +// Invokes the UI shown when a user has to reload a page in order to run an +// extension. +IN_PROC_BROWSER_TEST_F(ExtensionsMenuViewBrowserTest, + InvokeUi_ReloadPageBubble) { + ASSERT_TRUE(embedded_test_server()->Start()); + extensions::TestExtensionDir test_dir; + // Load an extension that injects scripts at "document_start", which requires + // reloading the page to inject if permissions are withheld. + test_dir.WriteManifest( + R"({ + "name": "Runs Script Everywhere", + "description": "An extension that runs script everywhere", + "manifest_version": 2, + "version": "0.1", + "content_scripts": [{ + "matches": ["*://*/*"], + "js": ["script.js"], + "run_at": "document_start" + }] + })"); + test_dir.WriteFile(FILE_PATH_LITERAL("script.js"), + "console.log('injected!');"); + + scoped_refptr<const extensions::Extension> extension = + extensions::ChromeTestExtensionLoader(profile()).LoadExtension( + test_dir.UnpackedPath()); + ASSERT_TRUE(extension); + + extensions::ScriptingPermissionsModifier(profile(), extension) + .SetWithholdHostPermissions(true); + + // Navigate to a page the extension wants to run on. + content::WebContents* tab = + browser()->tab_strip_model()->GetActiveWebContents(); + { + content::TestNavigationObserver observer(tab); + GURL url = embedded_test_server()->GetURL("example.com", "/title1.html"); + ui_test_utils::NavigateToURL(browser(), url); + EXPECT_TRUE(observer.last_navigation_succeeded()); + } + + ShowAndVerifyUi(); +} + IN_PROC_BROWSER_TEST_F(ExtensionsMenuViewBrowserTest, TriggerPopup) { LoadTestExtension("extensions/simple_with_popup"); ShowUi(""); @@ -150,7 +227,7 @@ } IN_PROC_BROWSER_TEST_F(ExtensionsMenuViewBrowserTest, - ActivationWithReloadNeeded_Accept) { + TriggeringExtensionClosesMenu) { LoadTestExtension("extensions/trigger_actions/browser_action"); ShowUi(""); VerifyUi(); @@ -215,8 +292,7 @@ ASSERT_TRUE(embedded_test_server()->Start()); LoadTestExtension("extensions/blocked_actions/content_scripts"); auto extension = extensions_.back(); - extensions::ScriptingPermissionsModifier modifier(browser()->profile(), - extension); + extensions::ScriptingPermissionsModifier modifier(profile(), extension); modifier.SetWithholdHostPermissions(true); ui_test_utils::NavigateToURL(
diff --git a/chrome/browser/vr/service/browser_xr_runtime.cc b/chrome/browser/vr/service/browser_xr_runtime.cc index aacde2a9..bafaf3e 100644 --- a/chrome/browser/vr/service/browser_xr_runtime.cc +++ b/chrome/browser/vr/service/browser_xr_runtime.cc
@@ -246,7 +246,7 @@ // Only support DOM overlay if the feature flag is enabled. if (feature == device::mojom::XRSessionFeature::DOM_OVERLAY_FOR_HANDHELD_AR) { - return base::FeatureList::IsEnabled(features::kWebXrArDOMOverlay); + return base::FeatureList::IsEnabled(features::kWebXrIncubations); } return ContainsFeature(kARCoreDeviceFeatures, feature); case device::mojom::XRDeviceId::ORIENTATION_DEVICE_ID:
diff --git a/chrome/renderer/autofill/password_autofill_agent_browsertest.cc b/chrome/renderer/autofill/password_autofill_agent_browsertest.cc index 9bd2d50..f90857b 100644 --- a/chrome/renderer/autofill/password_autofill_agent_browsertest.cc +++ b/chrome/renderer/autofill/password_autofill_agent_browsertest.cc
@@ -88,6 +88,8 @@ const char kCarolUsername[] = "Carol"; const char kCarolPassword[] = "test"; const char kCarolAlternateUsername[] = "RealCarolUsername"; +const char kEmptyUsername[] = ""; +const char kEmptyUsernamePassword[] = "empty"; const char kFormHTML[] = "<FORM id='LoginTestForm' action='http://www.bidule.com'>" @@ -348,6 +350,8 @@ username3_ = ASCIIToUTF16(kCarolUsername); password3_ = ASCIIToUTF16(kCarolPassword); alternate_username3_ = ASCIIToUTF16(kCarolAlternateUsername); + username4_ = ASCIIToUTF16(kEmptyUsername); + password4_ = ASCIIToUTF16(kEmptyUsernamePassword); FormFieldData username_field; username_field.name = ASCIIToUTF16(kUsernameName); @@ -366,6 +370,9 @@ PasswordAndMetadata password3; password3.password = password3_; fill_data_.additional_logins[username3_] = password3; + PasswordAndMetadata password4; + password3.password = password4_; + fill_data_.additional_logins[username4_] = password4; // We need to set the origin so it matches the frame URL and the action so // it matches the form action, otherwise we won't autocomplete. @@ -615,7 +622,8 @@ // suggestions, or only those starting with |username|. void CheckSuggestions(const std::string& username, bool show_all) { auto show_all_matches = [show_all](int options) { - return show_all == !!(options & autofill::SHOW_ALL); + return (show_all == ((options & autofill::SHOW_ALL) != 0)) || + (show_all == ((options & autofill::IS_PASSWORD_FIELD) != 0)); }; EXPECT_CALL(fake_driver_, @@ -775,10 +783,12 @@ base::string16 username1_; base::string16 username2_; base::string16 username3_; + base::string16 username4_; base::string16 password1_; base::string16 password2_; base::string16 password3_; base::string16 alternate_username3_; + base::string16 password4_; PasswordFormFillData fill_data_; WebInputElement username_element_; @@ -2364,7 +2374,7 @@ SimulateSuggestionChoiceOfUsernameAndPassword( password_element_, base::string16(), ASCIIToUTF16(kAlicePassword)); - CheckSuggestions(std::string(), false); + CheckSuggestions(std::string(), true); EXPECT_EQ(ASCIIToUTF16(kAlicePassword), password_element_.Value().Utf16()); EXPECT_TRUE(password_element_.IsAutofilled()); } @@ -2389,7 +2399,7 @@ SimulateSuggestionChoiceOfUsernameAndPassword( password_element_, base::string16(), ASCIIToUTF16(kAlicePassword)); - CheckSuggestions(std::string(), false); + CheckSuggestions(std::string(), true); EXPECT_EQ(ASCIIToUTF16(kAlicePassword), password_element_.Value().Utf16()); EXPECT_TRUE(password_element_.IsAutofilled()); } @@ -2647,7 +2657,7 @@ // Simulate a user clicking on the password element. This should produce a // message. autofill_agent_->FormControlElementClicked(password_element_, true); - CheckSuggestions("", false); + CheckSuggestions("", true); } // Tests that only the password field is autocompleted when the browser sends @@ -3152,9 +3162,9 @@ SimulateOnFillPasswordForm(fill_data_); SimulateElementClick("password1"); - CheckSuggestions(std::string(), false); + CheckSuggestions(std::string(), true); SimulateElementClick("password2"); - CheckSuggestions(std::string(), false); + CheckSuggestions(std::string(), true); } // Tests that password manager sees both autofill assisted and user entered @@ -3255,7 +3265,7 @@ // Simulate a user clicking on the password element. This should produce a // dropdown with suggestion of all available usernames. autofill_agent_->FormControlElementClicked(password_element_, false); - CheckSuggestions("", false); + CheckSuggestions("", true); } // Tests that a suggestion dropdown is shown on each password field. But when a @@ -3278,13 +3288,13 @@ // Simulate a user clicking on the password elements. This should produce // dropdowns with suggestion of all available usernames. SimulateElementClick("password"); - CheckSuggestions("", false); + CheckSuggestions("", true); SimulateElementClick("newpassword"); - CheckSuggestions("", false); + CheckSuggestions("", true); SimulateElementClick("confirmpassword"); - CheckSuggestions("", false); + CheckSuggestions("", true); // The user chooses to autofill the current password field. EXPECT_TRUE(password_autofill_agent_->FillSuggestion( @@ -3301,7 +3311,7 @@ // But when the user clicks on the autofilled password field again it should // still produce a suggestion dropdown. SimulateElementClick("password"); - CheckSuggestions("", false); + CheckSuggestions("", true); } TEST_F(PasswordAutofillAgentTest, ShowAutofillSignaturesFlag) { @@ -3345,7 +3355,7 @@ // Simulate a user clicking on the password element. This should produce a // dropdown with suggestion of all available usernames. autofill_agent_->FormControlElementClicked(password_element_, false); - CheckSuggestions("", false); + CheckSuggestions("", true); } // Checks that a same-document navigation form submission could have an empty @@ -3577,7 +3587,7 @@ password_autofill_agent_->FillPasswordForm(fill_data_); SimulateElementClick(kPasswordName); // Empty value because nothing was typed into the field. - CheckSuggestions("", false); + CheckSuggestions("", true); } // Tests that PSL matched password is not autofilled even when there is @@ -3823,6 +3833,26 @@ CheckUsernameSelection(3, 3); } +// Fill on account select for credentials with empty usernames: +// Do not refill usernames if non-empty username is already selected. +TEST_F(PasswordAutofillAgentTest, NoUsernameCredential) { + SimulateOnFillPasswordForm(fill_data_); + ClearUsernameAndPasswordFields(); + EXPECT_CALL(fake_driver_, ShowPasswordSuggestions); + SimulateSuggestionChoiceOfUsernameAndPassword(password_element_, + ASCIIToUTF16(kAliceUsername), + ASCIIToUTF16(kAlicePassword)); + CheckTextFieldsDOMState(kAliceUsername, true, kAlicePassword, true); + base::RunLoop().RunUntilIdle(); + + EXPECT_CALL(fake_driver_, ShowPasswordSuggestions); + SimulateSuggestionChoiceOfUsernameAndPassword( + password_element_, ASCIIToUTF16(kEmptyUsername), + ASCIIToUTF16(kEmptyUsernamePassword)); + + CheckTextFieldsDOMState(kAliceUsername, true, kEmptyUsernamePassword, true); +} + // Tests that any fields that have user input are not refilled on the next // call of FillPasswordForm. TEST_F(PasswordAutofillAgentTest, NoRefillOfUserInput) {
diff --git a/chrome/test/data/extensions/api_test/browser_action/close_background/background.js b/chrome/test/data/extensions/api_test/browser_action/close_background/background.js index a0dc78a..368f82b 100644 --- a/chrome/test/data/extensions/api_test/browser_action/close_background/background.js +++ b/chrome/test/data/extensions/api_test/browser_action/close_background/background.js
@@ -7,3 +7,5 @@ window.close(); }); }); + +chrome.test.sendMessage('ready');
diff --git a/chrome/test/data/prerender/prerender_alert_after_onload.html b/chrome/test/data/prerender/prerender_alert_after_onload.html deleted file mode 100644 index dd54cdbe..0000000 --- a/chrome/test/data/prerender/prerender_alert_after_onload.html +++ /dev/null
@@ -1,18 +0,0 @@ -<html> - <!-- - This test checks to make sure an alert after onLoad causes - prerendering to fail. - --> - <head> - <title>Prerender alert after onload cancellation</title> - - <script language="javascript" type="text/javascript"> - window.onload = function() { - // Delay the alert by an event loop iteration so the alert - // happens after the page has loaded, rather than just before. - setTimeout(alert, 0, "Testing prerender"); - }; - </script> - </head> - <body></body> -</html>
diff --git a/chrome/test/data/prerender/prerender_alert_before_onload.html b/chrome/test/data/prerender/prerender_alert_before_onload.html deleted file mode 100644 index a251f53..0000000 --- a/chrome/test/data/prerender/prerender_alert_before_onload.html +++ /dev/null
@@ -1,14 +0,0 @@ -<html> - <!-- - This test checks to make sure an alert before onLoad causes - prerendering to fail. - --> - <head> - <title>Prerender alert before onload cancellation</title> - - <script language="javascript" type="text/javascript"> - alert("Testing prerender"); - </script> - </head> - <body></body> -</html>
diff --git a/chrome/test/data/webui/settings/search_settings_test.js b/chrome/test/data/webui/settings/search_settings_test.js index 5fab6c8..bb0dfa1 100644 --- a/chrome/test/data/webui/settings/search_settings_test.js +++ b/chrome/test/data/webui/settings/search_settings_test.js
@@ -66,8 +66,8 @@ /** * Tests that a search hit within a <select> node causes the parent - * settings-section to be shown, but the DOM of the <select> is not - * modified. + * settings-section to be shown and the <select> to be highlighted by a + * bubble. */ test('<select> highlighting', function() { document.body.innerHTML = `<settings-section hidden-by-search> @@ -87,8 +87,8 @@ assertFalse(section.hiddenBySearch); const highlightWrapper = - select.querySelector('.search-highlight-wrapper'); - assertFalse(!!highlightWrapper); + section.querySelector('.search-highlight-wrapper'); + assertTrue(!!highlightWrapper); // Check that original DOM structure is present even after search // highlights are cleared.
diff --git a/chromeos/profiles/airmont.afdo.newest.txt b/chromeos/profiles/airmont.afdo.newest.txt index 0b06ad2..12307c8 100644 --- a/chromeos/profiles/airmont.afdo.newest.txt +++ b/chromeos/profiles/airmont.afdo.newest.txt
@@ -1 +1 @@ -chromeos-chrome-amd64-airmont-81-3987.0-1577100150-benchmark-81.0.4005.0-r1-redacted.afdo.xz \ No newline at end of file +chromeos-chrome-amd64-airmont-81-3987.0-1577100150-benchmark-81.0.4008.0-r1-redacted.afdo.xz \ No newline at end of file
diff --git a/chromeos/profiles/orderfile.newest.txt b/chromeos/profiles/orderfile.newest.txt index 2942390..7e384c3d 100644 --- a/chromeos/profiles/orderfile.newest.txt +++ b/chromeos/profiles/orderfile.newest.txt
@@ -1 +1 @@ -chromeos-chrome-orderfile-field-81-3987.0-1576497268-benchmark-81.0.4001.0-r1.orderfile.xz \ No newline at end of file +chromeos-chrome-orderfile-field-81-3987.0-1577099071-benchmark-81.0.4005.0-r1.orderfile.xz \ No newline at end of file
diff --git a/components/autofill/content/renderer/password_autofill_agent.cc b/components/autofill/content/renderer/password_autofill_agent.cc index 3dc9820..b3c6777 100644 --- a/components/autofill/content/renderer/password_autofill_agent.cc +++ b/components/autofill/content/renderer/password_autofill_agent.cc
@@ -142,16 +142,17 @@ // |current_username| as a prefix. bool CanShowSuggestion(const PasswordFormFillData& fill_data, const base::string16& current_username, - bool show_all) { + bool show_all, + bool is_password_field) { base::string16 current_username_lower = base::i18n::ToLower(current_username); - if (show_all || + if (show_all || is_password_field || base::StartsWith(base::i18n::ToLower(fill_data.username_field.value), current_username_lower, base::CompareCase::SENSITIVE)) { return true; } for (const auto& login : fill_data.additional_logins) { - if (show_all || + if (show_all || is_password_field || base::StartsWith(base::i18n::ToLower(login.first), current_username_lower, base::CompareCase::SENSITIVE)) { @@ -602,6 +603,7 @@ if (IsUsernameAmendable(username_element, element->IsPasswordFieldForAutofill()) && + !(username.empty() && element->IsPasswordFieldForAutofill()) && username_element.Value().Utf16() != username) { FillField(&username_element, username); } @@ -880,12 +882,7 @@ if (touch_to_fill_state_ == TouchToFillState::kIsShowing) return true; - // Chrome should never show more than one account for a password element since - // this implies that the username element cannot be modified. Thus even if - // |show_all| is true, check if the element in question is a password element - // for the call to ShowSuggestionPopup. - return ShowSuggestionPopup(*password_info, element, - show_all && !element.IsPasswordFieldForAutofill(), + return ShowSuggestionPopup(*password_info, element, show_all, element.IsPasswordFieldForAutofill()); } @@ -1443,11 +1440,15 @@ ? base::string16() : user_input.Value().Utf16()); + username_query_prefix_ = username_string; + if (!CanShowSuggestion(password_info.fill_data, username_string, show_all, + show_on_password_field)) { + return false; + } GetPasswordManagerDriver()->ShowPasswordSuggestions( field.text_direction, username_string, options, render_frame()->ElementBoundsInWindow(user_input)); - username_query_prefix_ = username_string; - return CanShowSuggestion(password_info.fill_data, username_string, show_all); + return true; } void PasswordAutofillAgent::CleanupOnDocumentShutdown() {
diff --git a/components/exo/wayland/zcr_color_space.cc b/components/exo/wayland/zcr_color_space.cc index 2b54086..2c5f855 100644 --- a/components/exo/wayland/zcr_color_space.cc +++ b/components/exo/wayland/zcr_color_space.cc
@@ -85,7 +85,7 @@ // ZCR_COLOR_SPACE_V1_TRANSFER_FUNCTION_ARIB_STD_B67 gfx::ColorSpace::TransferID::ARIB_STD_B67, // ZCR_COLOR_SPACE_V1_TRANSFER_FUNCTION_SMPTEST2084_NON_HDR - gfx::ColorSpace::TransferID::SMPTEST2084_NON_HDR, + gfx::ColorSpace::TransferID::SMPTEST2084, // ZCR_COLOR_SPACE_V1_TRANSFER_FUNCTION_IEC61966_2_1_HDR gfx::ColorSpace::TransferID::IEC61966_2_1_HDR, // ZCR_COLOR_SPACE_V1_TRANSFER_FUNCTION_LINEAR_HDR
diff --git a/components/viz/common/gl_scaler.cc b/components/viz/common/gl_scaler.cc index 78b5725..c75e71f3 100644 --- a/components/viz/common/gl_scaler.cc +++ b/components/viz/common/gl_scaler.cc
@@ -210,12 +210,6 @@ transform = gfx::ColorTransform::NewColorTransform( scaling_color_space_, params_.output_color_space, gfx::ColorTransform::Intent::INTENT_PERCEPTUAL); - if (!transform->CanGetShaderSource()) { - NOTIMPLEMENTED() << "color transform from " - << scaling_color_space_.ToString() << " to " - << params_.output_color_space.ToString(); - return false; - } } ScalerStage* const final_stage = chain.get(); final_stage->set_shader_program( @@ -247,12 +241,6 @@ transform = gfx::ColorTransform::NewColorTransform( params_.source_color_space, scaling_color_space_, gfx::ColorTransform::Intent::INTENT_PERCEPTUAL); - if (!transform->CanGetShaderSource()) { - NOTIMPLEMENTED() << "color transform from " - << params_.source_color_space.ToString() << " to " - << scaling_color_space_.ToString(); - return false; - } input_stage->set_shader_program( GetShaderProgram(input_stage->shader(), intermediate_texture_type, transform.get(), kNoSwizzle));
diff --git a/components/viz/common/quads/render_pass_io.cc b/components/viz/common/quads/render_pass_io.cc index 445b328..9266b8f 100644 --- a/components/viz/common/quads/render_pass_io.cc +++ b/components/viz/common/quads/render_pass_io.cc
@@ -610,7 +610,6 @@ MATCH_ENUM_CASE(TransferID, SMPTEST2084) MATCH_ENUM_CASE(TransferID, SMPTEST428_1) MATCH_ENUM_CASE(TransferID, ARIB_STD_B67) - MATCH_ENUM_CASE(TransferID, SMPTEST2084_NON_HDR) MATCH_ENUM_CASE(TransferID, IEC61966_2_1_HDR) MATCH_ENUM_CASE(TransferID, LINEAR_HDR) MATCH_ENUM_CASE(TransferID, CUSTOM) @@ -689,7 +688,6 @@ MATCH_ENUM_CASE(TransferID, SMPTEST2084) MATCH_ENUM_CASE(TransferID, SMPTEST428_1) MATCH_ENUM_CASE(TransferID, ARIB_STD_B67) - MATCH_ENUM_CASE(TransferID, SMPTEST2084_NON_HDR) MATCH_ENUM_CASE(TransferID, IEC61966_2_1_HDR) MATCH_ENUM_CASE(TransferID, LINEAR_HDR) MATCH_ENUM_CASE(TransferID, CUSTOM)
diff --git a/components/viz/service/BUILD.gn b/components/viz/service/BUILD.gn index 9188155..135c8bd4 100644 --- a/components/viz/service/BUILD.gn +++ b/components/viz/service/BUILD.gn
@@ -18,8 +18,6 @@ "display/bsp_tree.h", "display/bsp_walk_action.cc", "display/bsp_walk_action.h", - "display/color_lut_cache.cc", - "display/color_lut_cache.h", "display/damage_frame_annotator.cc", "display/damage_frame_annotator.h", "display/direct_renderer.cc",
diff --git a/components/viz/service/display/color_lut_cache.cc b/components/viz/service/display/color_lut_cache.cc deleted file mode 100644 index e1c1312d6..0000000 --- a/components/viz/service/display/color_lut_cache.cc +++ /dev/null
@@ -1,135 +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. - -#include "components/viz/service/display/color_lut_cache.h" - -#include <stdint.h> -#include <cmath> -#include <vector> - -#include "base/stl_util.h" -#include "gpu/command_buffer/client/gles2_interface.h" -#include "third_party/khronos/GLES2/gl2ext.h" -#include "ui/gfx/color_transform.h" -#include "ui/gfx/half_float.h" - -// After a LUT has not been used for this many frames, we release it. -const uint32_t kMaxFramesUnused = 10; - -ColorLUTCache::ColorLUTCache(gpu::gles2::GLES2Interface* gl, - bool texture_half_float_linear) - : lut_cache_(0), - gl_(gl), - texture_half_float_linear_(texture_half_float_linear) {} - -ColorLUTCache::~ColorLUTCache() { - GLuint textures[10]; - size_t n = 0; - for (const auto& cache_entry : lut_cache_) { - textures[n++] = cache_entry.second.lut.texture; - if (n == base::size(textures)) { - gl_->DeleteTextures(n, textures); - n = 0; - } - } - if (n) - gl_->DeleteTextures(n, textures); -} - -namespace { - -void FloatToLUT(const float* f, gfx::HalfFloat* out, size_t num) { - gfx::FloatToHalfFloat(f, out, num); -} - -void FloatToLUT(float* f, unsigned char* out, size_t num) { - for (size_t i = 0; i < num; i++) { - out[i] = std::min<int>(255, std::max<int>(0, floorf(f[i] * 255.0f + 0.5f))); - } -} - -} // namespace - -template <typename T> -unsigned int ColorLUTCache::MakeLUT(const gfx::ColorTransform* transform, - int lut_samples) { - int lut_entries = lut_samples * lut_samples * lut_samples; - float inverse = 1.0f / (lut_samples - 1); - std::vector<T> lut(lut_entries * 4); - std::vector<gfx::ColorTransform::TriStim> samples(lut_samples); - T* lutp = lut.data(); - float one = 1.0f; - T alpha; - FloatToLUT(&one, &alpha, 1); - for (int v = 0; v < lut_samples; v++) { - for (int u = 0; u < lut_samples; u++) { - for (int y = 0; y < lut_samples; y++) { - samples[y].set_x(y * inverse); - samples[y].set_y(u * inverse); - samples[y].set_z(v * inverse); - } - transform->Transform(samples.data(), samples.size()); - T* lutp2 = lutp + lut_samples; - FloatToLUT(reinterpret_cast<float*>(samples.data()), lutp2, - lut_samples * 3); - for (int i = 0; i < lut_samples; i++) { - *(lutp++) = *(lutp2++); - *(lutp++) = *(lutp2++); - *(lutp++) = *(lutp2++); - *(lutp++) = alpha; - } - } - } - - GLuint previously_bound_texture = 0; - GLuint lut_texture = 0; - gl_->GetIntegerv(GL_TEXTURE_BINDING_2D, - reinterpret_cast<GLint*>(&previously_bound_texture)); - gl_->GenTextures(1, &lut_texture); - gl_->BindTexture(GL_TEXTURE_2D, lut_texture); - gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - gl_->TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, lut_samples, - lut_samples * lut_samples, 0, GL_RGBA, - sizeof(T) == 1 ? GL_UNSIGNED_BYTE : GL_HALF_FLOAT_OES, - lut.data()); - gl_->BindTexture(GL_TEXTURE_2D, previously_bound_texture); - return lut_texture; -} - -ColorLUTCache::LUT ColorLUTCache::GetLUT(const gfx::ColorTransform* transform) { - auto iter = lut_cache_.Get(transform); - if (iter != lut_cache_.end()) { - iter->second.last_used_frame = current_frame_; - return iter->second.lut; - } - - LUT lut; - // If input is HDR, and the output is full range, we're going to need - // to produce values outside of 0-1, so we'll need to make a half-float - // LUT. Also, we'll need to build a larger lut to maintain accuracy. - // All LUT sizes should be odd as some transforms have a knee at 0.5. - if (transform->GetDstColorSpace().FullRangeEncodedValues() && - transform->GetSrcColorSpace().IsHDR() && texture_half_float_linear_) { - lut.size = 37; - lut.texture = MakeLUT<uint16_t>(transform, lut.size); - } else { - lut.size = 17; - lut.texture = MakeLUT<unsigned char>(transform, lut.size); - } - lut_cache_.Put(transform, CacheVal(lut, current_frame_)); - return lut; -} - -void ColorLUTCache::Swap() { - current_frame_++; - while (!lut_cache_.empty() && - current_frame_ - lut_cache_.rbegin()->second.last_used_frame > - kMaxFramesUnused) { - gl_->DeleteTextures(1, &lut_cache_.rbegin()->second.lut.texture); - lut_cache_.ShrinkToSize(lut_cache_.size() - 1); - } -}
diff --git a/components/viz/service/display/color_lut_cache.h b/components/viz/service/display/color_lut_cache.h deleted file mode 100644 index b437d2b..0000000 --- a/components/viz/service/display/color_lut_cache.h +++ /dev/null
@@ -1,61 +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 COMPONENTS_VIZ_SERVICE_DISPLAY_COLOR_LUT_CACHE_H_ -#define COMPONENTS_VIZ_SERVICE_DISPLAY_COLOR_LUT_CACHE_H_ - -#include <map> - -#include "base/containers/mru_cache.h" -#include "base/macros.h" -#include "components/viz/service/viz_service_export.h" -#include "ui/gfx/color_space.h" - -namespace gfx { -class ColorTransform; -} - -namespace gpu { -namespace gles2 { -class GLES2Interface; -} -} // namespace gpu - -class VIZ_SERVICE_EXPORT ColorLUTCache { - public: - explicit ColorLUTCache(gpu::gles2::GLES2Interface* gl, - bool texture_half_float_linear); - ~ColorLUTCache(); - - struct LUT { - unsigned int texture; - int size; - }; - - LUT GetLUT(const gfx::ColorTransform* transform); - - // End of frame, assume all LUTs handed out are no longer used. - void Swap(); - - private: - template <typename T> - unsigned int MakeLUT(const gfx::ColorTransform* transform, int lut_samples); - - typedef const gfx::ColorTransform* CacheKey; - - struct CacheVal { - CacheVal(LUT lut, uint32_t last_used_frame) - : lut(lut), last_used_frame(last_used_frame) {} - LUT lut; - uint32_t last_used_frame; - }; - - base::MRUCache<CacheKey, CacheVal> lut_cache_; - uint32_t current_frame_; - gpu::gles2::GLES2Interface* gl_; - bool texture_half_float_linear_; - DISALLOW_COPY_AND_ASSIGN(ColorLUTCache); -}; - -#endif // COMPONENTS_VIZ_SERVICE_DISPLAY_COLOR_LUT_CACHE_H_
diff --git a/components/viz/service/display/gl_renderer.cc b/components/viz/service/display/gl_renderer.cc index f4b2fc3..43c5e25 100644 --- a/components/viz/service/display/gl_renderer.cc +++ b/components/viz/service/display/gl_renderer.cc
@@ -350,10 +350,6 @@ copier_(output_surface->context_provider(), &texture_deleter_), sync_queries_(gl_), bound_geometry_(NO_BINDING), - color_lut_cache_(gl_, - output_surface_->context_provider() - ->ContextCapabilities() - .texture_half_float_linear), current_task_runner_(std::move(current_task_runner)) { DCHECK(gl_); DCHECK(context_support_); @@ -3128,7 +3124,6 @@ awaiting_release_overlay_textures_.erase(it); } } - color_lut_cache_.Swap(); } void GLRenderer::BindFramebufferToOutputSurface() { @@ -3294,14 +3289,6 @@ }; gl_->Uniform4fv(current_program_->viewport_location(), 1, viewport); } - if (current_program_->lut_texture_location() != -1) { - ColorLUTCache::LUT lut = color_lut_cache_.GetLUT(color_transform); - gl_->ActiveTexture(GL_TEXTURE5); - gl_->BindTexture(GL_TEXTURE_2D, lut.texture); - gl_->Uniform1i(current_program_->lut_texture_location(), 5); - gl_->Uniform1f(current_program_->lut_size_location(), lut.size); - gl_->ActiveTexture(GL_TEXTURE0); - } if (has_output_color_matrix) { DCHECK_NE(current_program_->output_color_matrix_location(), -1);
diff --git a/components/viz/service/display/gl_renderer.h b/components/viz/service/display/gl_renderer.h index 7c4d7b5a..4f5e911 100644 --- a/components/viz/service/display/gl_renderer.h +++ b/components/viz/service/display/gl_renderer.h
@@ -20,7 +20,6 @@ #include "components/viz/common/quads/solid_color_draw_quad.h" #include "components/viz/common/quads/tile_draw_quad.h" #include "components/viz/common/quads/yuv_video_draw_quad.h" -#include "components/viz/service/display/color_lut_cache.h" #include "components/viz/service/display/direct_renderer.h" #include "components/viz/service/display/gl_renderer_copier.h" #include "components/viz/service/display/gl_renderer_draw_cache.h" @@ -442,7 +441,6 @@ bool force_drawing_frame_framebuffer_unflipped_ = false; BoundGeometry bound_geometry_; - ColorLUTCache color_lut_cache_; unsigned offscreen_stencil_renderbuffer_id_ = 0; gfx::Size offscreen_stencil_renderbuffer_size_;
diff --git a/components/viz/service/display/gl_renderer_unittest.cc b/components/viz/service/display/gl_renderer_unittest.cc index 94bd87f..7dc43111 100644 --- a/components/viz/service/display/gl_renderer_unittest.cc +++ b/components/viz/service/display/gl_renderer_unittest.cc
@@ -375,7 +375,7 @@ NON_PREMULTIPLIED_ALPHA, true, true, false, false)); - // Iterate over alpha plane, nv12, and color_lut parameters. + // Iterate over alpha plane and nv12 parameters. UVTextureMode uv_modes[2] = {UV_TEXTURE_MODE_UV, UV_TEXTURE_MODE_U_V}; YUVAlphaTextureMode a_modes[2] = {YUV_NO_ALPHA_TEXTURE, YUV_HAS_ALPHA_TEXTURE};
diff --git a/components/viz/service/display/program_binding.cc b/components/viz/service/display/program_binding.cc index c0d5c66f..0c246b05 100644 --- a/components/viz/service/display/program_binding.cc +++ b/components/viz/service/display/program_binding.cc
@@ -164,11 +164,9 @@ color_transform_ = nullptr; if (transform->IsIdentity()) { color_conversion_mode_ = COLOR_CONVERSION_MODE_NONE; - } else if (transform->CanGetShaderSource()) { + } else { color_conversion_mode_ = COLOR_CONVERSION_MODE_SHADER; color_transform_ = transform; - } else { - color_conversion_mode_ = COLOR_CONVERSION_MODE_LUT; } }
diff --git a/components/viz/service/display/program_binding.h b/components/viz/service/display/program_binding.h index e3ae7eb..19bf651d 100644 --- a/components/viz/service/display/program_binding.h +++ b/components/viz/service/display/program_binding.h
@@ -305,10 +305,6 @@ int a_texture_location() const { return fragment_shader_.a_texture_location_; } - int lut_texture_location() const { - return fragment_shader_.lut_texture_location_; - } - int lut_size_location() const { return fragment_shader_.lut_size_location_; } int resource_multiplier_location() const { return fragment_shader_.resource_multiplier_location_; }
diff --git a/components/viz/service/display/renderer_pixeltest.cc b/components/viz/service/display/renderer_pixeltest.cc index 0edb550..5a0932d 100644 --- a/components/viz/service/display/renderer_pixeltest.cc +++ b/components/viz/service/display/renderer_pixeltest.cc
@@ -4899,8 +4899,6 @@ // Allow a difference of 2 bytes in comparison for shader-based transforms, // and 4 bytes for LUT-based transforms (determined empirically). cc::FuzzyPixelComparator comparator(false, 100.f, 0.f, 2.f, 2, 0); - if (!transform->CanGetShaderSource()) - comparator = cc::FuzzyPixelComparator(false, 100.f, 0.f, 6.f, 6, 0); EXPECT_TRUE( this->RunPixelTest(&pass_list, &expected_output_colors, comparator)); }
diff --git a/components/viz/service/display/shader.cc b/components/viz/service/display/shader.cc index a86ed5b..879cb8f 100644 --- a/components/viz/service/display/shader.cc +++ b/components/viz/service/display/shader.cc
@@ -450,10 +450,6 @@ uniforms.push_back("color"); break; } - if (color_conversion_mode_ == COLOR_CONVERSION_MODE_LUT) { - uniforms.push_back("lut_texture"); - uniforms.push_back("lut_size"); - } if (has_output_color_matrix_) uniforms.emplace_back("output_color_matrix"); @@ -516,10 +512,6 @@ color_location_ = locations[index++]; break; } - if (color_conversion_mode_ == COLOR_CONVERSION_MODE_LUT) { - lut_texture_location_ = locations[index++]; - lut_size_location_ = locations[index++]; - } if (has_output_color_matrix_) output_color_matrix_location_ = locations[index++]; @@ -1038,29 +1030,6 @@ // Apply color conversion. switch (color_conversion_mode_) { - case COLOR_CONVERSION_MODE_LUT: - HDR("uniform sampler2D lut_texture;"); - HDR("uniform float lut_size;"); - HDR("vec4 LUT(sampler2D sampler, vec3 pos, float size) {"); - HDR(" pos *= size - 1.0;"); - HDR(" // Select layer"); - HDR(" float layer = min(floor(pos.z), size - 2.0);"); - HDR(" // Compress the xy coordinates so they stay within"); - HDR(" // [0.5 .. 31.5] / N (assuming a LUT size of 17^3)"); - HDR(" pos.xy = (pos.xy + vec2(0.5)) / size;"); - HDR(" pos.y = (pos.y + layer) / size;"); - HDR(" return mix(LutLookup(sampler, pos.xy),"); - HDR(" LutLookup(sampler, pos.xy + vec2(0, 1.0 / size)),"); - HDR(" pos.z - layer);"); - HDR("}"); - // Un-premultiply by alpha. - if (premultiply_alpha_mode_ != NON_PREMULTIPLIED_ALPHA) { - SRC("// un-premultiply alpha"); - SRC("if (texColor.a > 0.0) texColor.rgb /= texColor.a;"); - } - SRC("texColor.rgb = LUT(lut_texture, texColor.xyz, lut_size).xyz;"); - SRC("texColor.rgb *= texColor.a;"); - break; case COLOR_CONVERSION_MODE_SHADER: header += color_transform_->GetShaderSource(); // Un-premultiply by alpha.
diff --git a/components/viz/service/display/shader.h b/components/viz/service/display/shader.h index 9638bb1..6d154b62 100644 --- a/components/viz/service/display/shader.h +++ b/components/viz/service/display/shader.h
@@ -130,10 +130,6 @@ enum ColorConversionMode { // No color conversion is performed. COLOR_CONVERSION_MODE_NONE, - // Conversion is done directly from input RGB space (or YUV space if - // applicable) to output RGB space, via a 3D texture represented as a 2D - // texture. - COLOR_CONVERSION_MODE_LUT, // Conversion is done analytically in the shader. COLOR_CONVERSION_MODE_SHADER, }; @@ -312,10 +308,6 @@ int resource_multiplier_location_ = -1; int resource_offset_location_ = -1; - // LUT YUV to color-converted RGB. - int lut_texture_location_ = -1; - int lut_size_location_ = -1; - private: friend class Program;
diff --git a/components/viz/service/display/skia_renderer.cc b/components/viz/service/display/skia_renderer.cc index 91712c7..6d6857d8 100644 --- a/components/viz/service/display/skia_renderer.cc +++ b/components/viz/service/display/skia_renderer.cc
@@ -2157,10 +2157,6 @@ std::unique_ptr<gfx::ColorTransform> transform = gfx::ColorTransform::NewColorTransform( adjusted_src, dst, gfx::ColorTransform::Intent::INTENT_PERCEPTUAL); - // TODO(backer): Support lookup table transforms (e.g. - // COLOR_CONVERSION_MODE_LUT). - if (!transform->CanGetShaderSource()) - return nullptr; const char* hdr = R"( uniform half offset;
diff --git a/content/browser/devtools/protocol/devtools_protocol_browsertest.cc b/content/browser/devtools/protocol/devtools_protocol_browsertest.cc index fdb6d40..b57c047 100644 --- a/content/browser/devtools/protocol/devtools_protocol_browsertest.cc +++ b/content/browser/devtools/protocol/devtools_protocol_browsertest.cc
@@ -2383,7 +2383,7 @@ std::unique_ptr<DownloadTestObserver> observer2(CreateWaiter(shell(), 1)); EXPECT_TRUE(NavigateToURL( shell(), embedded_test_server()->GetURL( - content::SlowDownloadHttpResponse::kFinishDownloadUrl))); + content::SlowDownloadHttpResponse::kFinishSlowResponseUrl))); observer2->WaitForFinished(); // Wait for the third request. EXPECT_EQ( 1u, observer2->NumDownloadsSeenInState(download::DownloadItem::COMPLETE)); @@ -2397,8 +2397,9 @@ // source file. base::FilePath file1(download1->GetTargetFilePath()); ASSERT_EQ(file1.DirName().MaybeAsASCII(), download1_path); - size_t file_size1 = content::SlowDownloadHttpResponse::kFirstDownloadSize + - content::SlowDownloadHttpResponse::kSecondDownloadSize; + size_t file_size1 = + content::SlowDownloadHttpResponse::kFirstResponsePartSize + + content::SlowDownloadHttpResponse::kSecondResponsePartSize; std::string expected_contents(file_size1, '*'); ASSERT_TRUE(VerifyFile(file1, expected_contents, file_size1));
diff --git a/content/browser/download/download_browsertest.cc b/content/browser/download/download_browsertest.cc index 0a0bc8a..fd4ea2b93 100644 --- a/content/browser/download/download_browsertest.cc +++ b/content/browser/download/download_browsertest.cc
@@ -879,7 +879,7 @@ host_resolver()->AddRule(kOriginOne, real_host); host_resolver()->AddRule(kOriginTwo, real_host); host_resolver()->AddRule(kOriginThree, real_host); - host_resolver()->AddRule(SlowDownloadHttpResponse::kSlowDownloadHostName, + host_resolver()->AddRule(SlowDownloadHttpResponse::kSlowResponseHostName, real_host); host_resolver()->AddRule(TestDownloadHttpResponse::kTestDownloadHostName, real_host); @@ -1344,7 +1344,7 @@ // we're in the expected state. download::DownloadItem* download = StartDownloadAndReturnItem( shell(), embedded_test_server()->GetURL( - SlowDownloadHttpResponse::kSlowDownloadHostName, + SlowDownloadHttpResponse::kSlowResponseHostName, SlowDownloadHttpResponse::kUnknownSizeUrl)); ASSERT_EQ(download::DownloadItem::IN_PROGRESS, download->GetState()); @@ -1366,7 +1366,7 @@ // we're in the expected state. download::DownloadItem* download1 = StartDownloadAndReturnItem( shell(), embedded_test_server()->GetURL( - SlowDownloadHttpResponse::kSlowDownloadHostName, + SlowDownloadHttpResponse::kSlowResponseHostName, SlowDownloadHttpResponse::kUnknownSizeUrl)); ASSERT_EQ(download::DownloadItem::IN_PROGRESS, download1->GetState()); @@ -1380,10 +1380,10 @@ // Allow the first request to finish. std::unique_ptr<DownloadTestObserver> observer2(CreateWaiter(shell(), 1)); - EXPECT_TRUE(NavigateToURL(shell(), - embedded_test_server()->GetURL( - SlowDownloadHttpResponse::kSlowDownloadHostName, - SlowDownloadHttpResponse::kFinishDownloadUrl))); + EXPECT_TRUE(NavigateToURL( + shell(), embedded_test_server()->GetURL( + SlowDownloadHttpResponse::kSlowResponseHostName, + SlowDownloadHttpResponse::kFinishSlowResponseUrl))); observer2->WaitForFinished(); // Wait for the third request. @@ -1398,8 +1398,8 @@ // |file1| should be full of '*'s, and |file2| should be the same as the // source file. base::FilePath file1(download1->GetTargetFilePath()); - size_t file_size1 = SlowDownloadHttpResponse::kFirstDownloadSize + - SlowDownloadHttpResponse::kSecondDownloadSize; + size_t file_size1 = SlowDownloadHttpResponse::kFirstResponsePartSize + + SlowDownloadHttpResponse::kSecondResponsePartSize; std::string expected_contents(file_size1, '*'); ASSERT_TRUE(VerifyFile(file1, expected_contents, file_size1)); @@ -1619,7 +1619,7 @@ // Create a download that won't complete. download::DownloadItem* download = StartDownloadAndReturnItem( shell(), embedded_test_server()->GetURL( - SlowDownloadHttpResponse::kSlowDownloadHostName, + SlowDownloadHttpResponse::kSlowResponseHostName, SlowDownloadHttpResponse::kUnknownSizeUrl)); EXPECT_EQ(download::DownloadItem::IN_PROGRESS, download->GetState());
diff --git a/content/child/runtime_features.cc b/content/child/runtime_features.cc index 582ae65..82de7a3 100644 --- a/content/child/runtime_features.cc +++ b/content/child/runtime_features.cc
@@ -182,12 +182,9 @@ {wf::EnablePeriodicBackgroundSync, features::kPeriodicBackgroundSync, kEnableOnly}, {wf::EnableWebXR, features::kWebXr, kUseFeatureState}, - {wf::EnableWebXRARDOMOverlay, features::kWebXrArDOMOverlay, - kEnableOnly}, {wf::EnableWebXRARModule, features::kWebXrArModule, kEnableOnly}, {wf::EnableWebXRHitTest, features::kWebXrHitTest, kEnableOnly}, - {wf::EnableWebXRAnchors, features::kWebXrAnchors, kEnableOnly}, - {wf::EnableWebXRPlaneDetection, features::kWebXrPlaneDetection, + {wf::EnableWebXRIncubations, features::kWebXrIncubations, kEnableOnly}, {wf::EnableFetchMetadata, network::features::kFetchMetadata, kUseFeatureState},
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc index fe9fd904..c59d115 100644 --- a/content/public/common/content_features.cc +++ b/content/public/common/content_features.cc
@@ -715,21 +715,13 @@ const base::Feature kWebXrArModule{"WebXRARModule", base::FEATURE_DISABLED_BY_DEFAULT}; -// Enables access to anchors via WebXR API. -const base::Feature kWebXrAnchors{"WebXRAnchors", - base::FEATURE_DISABLED_BY_DEFAULT}; - // Enables access to raycasting against estimated XR scene geometry. const base::Feature kWebXrHitTest{"WebXRHitTest", base::FEATURE_DISABLED_BY_DEFAULT}; -// Enables access to planes detected in the user's environment. -const base::Feature kWebXrPlaneDetection{"WebXRPlaneDetection", - base::FEATURE_DISABLED_BY_DEFAULT}; - -// Enables access to planes detected in the user's environment. -const base::Feature kWebXrArDOMOverlay{"WebXRARDOMOverlay", - base::FEATURE_DISABLED_BY_DEFAULT}; +// Enables access to experimental WebXR features. +const base::Feature kWebXrIncubations{"WebXRIncubations", + base::FEATURE_DISABLED_BY_DEFAULT}; // Start streaming scripts on script preload. const base::Feature kScriptStreamingOnPreload{"ScriptStreamingOnPreload",
diff --git a/content/public/common/content_features.h b/content/public/common/content_features.h index 23a29843..6928c60 100644 --- a/content/public/common/content_features.h +++ b/content/public/common/content_features.h
@@ -148,10 +148,8 @@ CONTENT_EXPORT extern const base::Feature kWebUsb; CONTENT_EXPORT extern const base::Feature kWebXr; CONTENT_EXPORT extern const base::Feature kWebXrArModule; -CONTENT_EXPORT extern const base::Feature kWebXrAnchors; -CONTENT_EXPORT extern const base::Feature kWebXrArDOMOverlay; CONTENT_EXPORT extern const base::Feature kWebXrHitTest; -CONTENT_EXPORT extern const base::Feature kWebXrPlaneDetection; +CONTENT_EXPORT extern const base::Feature kWebXrIncubations; CONTENT_EXPORT extern const base::Feature kScriptStreamingOnPreload; CONTENT_EXPORT extern const base::Feature kTrustedDOMTypes; CONTENT_EXPORT extern const base::Feature kBrowserUseDisplayThreadPriority;
diff --git a/content/public/test/slow_download_http_response.cc b/content/public/test/slow_download_http_response.cc index 31c297c..b28d395e 100644 --- a/content/public/test/slow_download_http_response.cc +++ b/content/public/test/slow_download_http_response.cc
@@ -4,107 +4,46 @@ #include "content/public/test/slow_download_http_response.h" -#include <utility> - -#include "base/bind.h" #include "base/strings/stringprintf.h" -#include "base/threading/thread_task_runner_handle.h" namespace content { -namespace { - -static bool g_should_finish_download = false; - -void SendResponseBodyDone(const net::test_server::SendBytesCallback& send, - net::test_server::SendCompleteCallback done); - -// Sends the response body with the given size. -void SendResponseBody(const net::test_server::SendBytesCallback& send, - net::test_server::SendCompleteCallback done, - bool finish_download) { - int data_size = finish_download - ? SlowDownloadHttpResponse::kSecondDownloadSize - : SlowDownloadHttpResponse::kFirstDownloadSize; - std::string response(data_size, '*'); - - if (finish_download) { - send.Run(response, std::move(done)); - } else { - send.Run(response, - base::BindOnce(&SendResponseBodyDone, send, std::move(done))); - } -} - -// Called when the response body was sucessfully sent. -void SendResponseBodyDone(const net::test_server::SendBytesCallback& send, - net::test_server::SendCompleteCallback done) { - if (g_should_finish_download) { - base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( - FROM_HERE, - base::BindOnce(&SendResponseBody, send, std::move(done), true), - base::TimeDelta::FromMilliseconds(100)); - } else { - base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( - FROM_HERE, base::BindOnce(&SendResponseBodyDone, send, std::move(done)), - base::TimeDelta::FromMilliseconds(100)); - } -} - -} // namespace - // static -const char SlowDownloadHttpResponse::kSlowDownloadHostName[] = - "url.handled.by.slow.download"; const char SlowDownloadHttpResponse::kUnknownSizeUrl[] = "/download-unknown-size"; const char SlowDownloadHttpResponse::kKnownSizeUrl[] = "/download-known-size"; -const char SlowDownloadHttpResponse::kFinishDownloadUrl[] = "/download-finish"; - -const int SlowDownloadHttpResponse::kFirstDownloadSize = 1024 * 35; -const int SlowDownloadHttpResponse::kSecondDownloadSize = 1024 * 10; // static std::unique_ptr<net::test_server::HttpResponse> SlowDownloadHttpResponse::HandleSlowDownloadRequest( const net::test_server::HttpRequest& request) { - if (request.relative_url != kUnknownSizeUrl && - request.relative_url != kKnownSizeUrl && - request.relative_url != kFinishDownloadUrl) { - return nullptr; - } auto response = std::make_unique<SlowDownloadHttpResponse>(request.relative_url); + if (!response->IsHandledUrl()) { + return nullptr; + } return std::move(response); } SlowDownloadHttpResponse::SlowDownloadHttpResponse(const std::string& url) - : url_(url) {} + : SlowHttpResponse(url) {} SlowDownloadHttpResponse::~SlowDownloadHttpResponse() = default; -void SlowDownloadHttpResponse::SendResponse( - const net::test_server::SendBytesCallback& send, - net::test_server::SendCompleteCallback done) { - std::string response; - response.append("HTTP/1.1 200 OK\r\n"); - if (base::LowerCaseEqualsASCII(kFinishDownloadUrl, url_)) { - response.append("Content-type: text/plain\r\n"); - response.append("\r\n"); +bool SlowDownloadHttpResponse::IsHandledUrl() { + return (url() == SlowDownloadHttpResponse::kUnknownSizeUrl || + url() == SlowDownloadHttpResponse::kKnownSizeUrl || + SlowHttpResponse::IsHandledUrl()); +} - g_should_finish_download = true; - send.Run(response, std::move(done)); - } else { - response.append("Content-type: application/octet-stream\r\n"); - response.append("Cache-Control: max-age=0\r\n"); +void SlowDownloadHttpResponse::AddResponseHeaders(std::string* response) { + response->append("Content-type: application/octet-stream\r\n"); + response->append("Cache-Control: max-age=0\r\n"); - if (base::LowerCaseEqualsASCII(kKnownSizeUrl, url_)) { - response.append(base::StringPrintf( - "Content-Length: %d\r\n", kFirstDownloadSize + kSecondDownloadSize)); - } - response.append("\r\n"); - send.Run(response, - base::BindOnce(&SendResponseBody, send, std::move(done), false)); + if (base::LowerCaseEqualsASCII(kKnownSizeUrl, url())) { + response->append( + base::StringPrintf("Content-Length: %d\r\n", + kFirstResponsePartSize + kSecondResponsePartSize)); } }
diff --git a/content/public/test/slow_download_http_response.h b/content/public/test/slow_download_http_response.h index 8aaad8c..34e95c4 100644 --- a/content/public/test/slow_download_http_response.h +++ b/content/public/test/slow_download_http_response.h
@@ -5,27 +5,16 @@ #ifndef CONTENT_PUBLIC_TEST_SLOW_DOWNLOAD_HTTP_RESPONSE_H_ #define CONTENT_PUBLIC_TEST_SLOW_DOWNLOAD_HTTP_RESPONSE_H_ -#include <set> -#include <string> - -#include "net/test/embedded_test_server/http_request.h" -#include "net/test/embedded_test_server/http_response.h" +#include "content/public/test/slow_http_response.h" namespace content { -/* - * Download response that won't complete until |kFinishDownloadUrl| request is - * received. - */ -class SlowDownloadHttpResponse : public net::test_server::HttpResponse { +// A subclass of SlowHttpResponse that serves a download. +class SlowDownloadHttpResponse : public SlowHttpResponse { public: // Test URLs. - static const char kSlowDownloadHostName[]; static const char kUnknownSizeUrl[]; static const char kKnownSizeUrl[]; - static const char kFinishDownloadUrl[]; - static const int kFirstDownloadSize; - static const int kSecondDownloadSize; static std::unique_ptr<net::test_server::HttpResponse> HandleSlowDownloadRequest(const net::test_server::HttpRequest& request); @@ -33,14 +22,12 @@ SlowDownloadHttpResponse(const std::string& url); ~SlowDownloadHttpResponse() override; - // net::test_server::HttpResponse implementations. - void SendResponse(const net::test_server::SendBytesCallback& send, - net::test_server::SendCompleteCallback done) override; + SlowDownloadHttpResponse(const SlowDownloadHttpResponse&) = delete; + SlowDownloadHttpResponse& operator=(const SlowDownloadHttpResponse&) = delete; - private: - std::string url_; - - DISALLOW_COPY_AND_ASSIGN(SlowDownloadHttpResponse); + // SlowHttpResponse: + bool IsHandledUrl() override; + void AddResponseHeaders(std::string* response) override; }; } // namespace content
diff --git a/content/public/test/slow_http_response.cc b/content/public/test/slow_http_response.cc new file mode 100644 index 0000000..af548af --- /dev/null +++ b/content/public/test/slow_http_response.cc
@@ -0,0 +1,100 @@ +// 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/public/test/slow_http_response.h" + +#include <utility> + +#include "base/bind.h" +#include "base/threading/thread_task_runner_handle.h" + +namespace content { + +namespace { + +static bool g_should_finish_response = false; + +void SendResponseBodyDone(const net::test_server::SendBytesCallback& send, + net::test_server::SendCompleteCallback done); + +// The response body is sent in two parts, of size |kFirstResponsePartSize| and +// |kSecondResponsePartSize| respectively. +void SendResponseBody(const net::test_server::SendBytesCallback& send, + net::test_server::SendCompleteCallback done, + bool finish_response) { + int data_size = finish_response ? SlowHttpResponse::kSecondResponsePartSize + : SlowHttpResponse::kFirstResponsePartSize; + std::string response(data_size, '*'); + + if (finish_response) { + send.Run(response, std::move(done)); + } else { + send.Run(response, + base::BindOnce(&SendResponseBodyDone, send, std::move(done))); + } +} + +// Called when the response body was successfully sent. +void SendResponseBodyDone(const net::test_server::SendBytesCallback& send, + net::test_server::SendCompleteCallback done) { + if (g_should_finish_response) { + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, + base::BindOnce(&SendResponseBody, send, std::move(done), true), + base::TimeDelta::FromMilliseconds(100)); + } else { + base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, base::BindOnce(&SendResponseBodyDone, send, std::move(done)), + base::TimeDelta::FromMilliseconds(100)); + } +} + +} // namespace + +// static +const char SlowHttpResponse::kSlowResponseHostName[] = + "url.handled.by.slow.response"; +const char SlowHttpResponse::kSlowResponseUrl[] = "/slow-response"; +const char SlowHttpResponse::kFinishSlowResponseUrl[] = "/slow-response-finish"; + +const int SlowHttpResponse::kFirstResponsePartSize = 1024 * 35; +const int SlowHttpResponse::kSecondResponsePartSize = 1024 * 10; + +SlowHttpResponse::SlowHttpResponse(const std::string& url) : url_(url) {} + +SlowHttpResponse::~SlowHttpResponse() = default; + +bool SlowHttpResponse::IsHandledUrl() { + return url_ == kSlowResponseUrl || url_ == kFinishSlowResponseUrl; +} + +void SlowHttpResponse::AddResponseHeaders(std::string* response) { + response->append("Content-type: text/html\r\n"); +} + +void SlowHttpResponse::SetStatusLine(std::string* response) { + response->append("HTTP/1.1 200 OK\r\n"); +} + +void SlowHttpResponse::SendResponse( + const net::test_server::SendBytesCallback& send, + net::test_server::SendCompleteCallback done) { + std::string response; + SetStatusLine(&response); + if (base::LowerCaseEqualsASCII(kFinishSlowResponseUrl, url_)) { + response.append("Content-type: text/plain\r\n"); + response.append("\r\n"); + + g_should_finish_response = true; + send.Run(response, std::move(done)); + } else { + AddResponseHeaders(&response); + response.append("Cache-Control: max-age=0\r\n"); + response.append("\r\n"); + send.Run(response, + base::BindOnce(&SendResponseBody, send, std::move(done), false)); + } +} + +} // namespace content
diff --git a/content/public/test/slow_http_response.h b/content/public/test/slow_http_response.h new file mode 100644 index 0000000..e2f2b867 --- /dev/null +++ b/content/public/test/slow_http_response.h
@@ -0,0 +1,58 @@ +// 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_PUBLIC_TEST_SLOW_HTTP_RESPONSE_H_ +#define CONTENT_PUBLIC_TEST_SLOW_HTTP_RESPONSE_H_ + +#include <string> + +#include "net/test/embedded_test_server/http_request.h" +#include "net/test/embedded_test_server/http_response.h" + +namespace content { + +// An HTTP response that won't complete until a |kFinishSlowResponseUrl| request +// is received, used to simulate a slow response. +class SlowHttpResponse : public net::test_server::HttpResponse { + public: + // Test URLs. + static const char kSlowResponseHostName[]; + static const char kSlowResponseUrl[]; + static const char kFinishSlowResponseUrl[]; + static const int kFirstResponsePartSize; + static const int kSecondResponsePartSize; + + explicit SlowHttpResponse(const std::string& url); + ~SlowHttpResponse() override; + + SlowHttpResponse(const SlowHttpResponse&) = delete; + SlowHttpResponse& operator=(const SlowHttpResponse&) = delete; + + virtual bool IsHandledUrl(); + + // Subclasses can override this method to add custom HTTP response headers. + // These headers are only applied to the slow response itself, not the + // response to |kFinishSlowResponseUrl|. + virtual void AddResponseHeaders(std::string* response); + + // Subclasses can override this method to write a custom status line; the + // default implementation sets a 200 OK response. This status code is applied + // only to the slow response itself, not the response to + // |kFinishSlowResponseUrl|. + virtual void SetStatusLine(std::string* response); + + // net::test_server::HttpResponse implementations. + void SendResponse(const net::test_server::SendBytesCallback& send, + net::test_server::SendCompleteCallback done) override; + + protected: + const std::string& url() { return url_; } + + private: + std::string url_; +}; + +} // namespace content + +#endif // CONTENT_PUBLIC_TEST_SLOW_HTTP_RESPONSE_H_
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn index 14547768..6cb8f312 100644 --- a/content/test/BUILD.gn +++ b/content/test/BUILD.gn
@@ -173,6 +173,8 @@ "../public/test/simple_url_loader_test_helper.h", "../public/test/slow_download_http_response.cc", "../public/test/slow_download_http_response.h", + "../public/test/slow_http_response.cc", + "../public/test/slow_http_response.h", "../public/test/test_browser_context.cc", "../public/test/test_browser_context.h", "../public/test/test_content_client_initializer.cc",
diff --git a/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt index f3abb38..1291d3d 100644 --- a/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt
@@ -244,3 +244,5 @@ crbug.com/1037949 [ use-vulkan android android-chromium skia-renderer ] Pixel_Video_MP4_FourColors_Rot_270 [ Failure ] crbug.com/1037949 [ use-vulkan android android-chromium skia-renderer ] Pixel_Video_MP4_FourColors_Rot_90 [ Failure ] crbug.com/1037949 [ use-vulkan android android-chromium skia-renderer ] Pixel_Video_VP9 [ Failure ] + +crbug.com/1037654 [ use-vulkan android android-chromium skia-renderer ] Pixel_WebGLCopyImage [ Failure ]
diff --git a/device/fido/BUILD.gn b/device/fido/BUILD.gn index a70f417..7803b5e 100644 --- a/device/fido/BUILD.gn +++ b/device/fido/BUILD.gn
@@ -202,7 +202,6 @@ "mac/make_credential_operation.h", "mac/make_credential_operation.mm", "mac/operation.h", - "mac/operation_base.h", "mac/touch_id_context.h", "mac/touch_id_context.mm", "mac/util.h",
diff --git a/device/fido/mac/get_assertion_operation.h b/device/fido/mac/get_assertion_operation.h index 6a0ff4b..c05260e 100644 --- a/device/fido/mac/get_assertion_operation.h +++ b/device/fido/mac/get_assertion_operation.h
@@ -5,13 +5,15 @@ #ifndef DEVICE_FIDO_MAC_GET_ASSERTION_OPERATION_H_ #define DEVICE_FIDO_MAC_GET_ASSERTION_OPERATION_H_ +#include "base/callback.h" #include "base/component_export.h" #include "base/mac/availability.h" #include "base/macros.h" #include "device/fido/authenticator_get_assertion_response.h" #include "device/fido/ctap_get_assertion_request.h" #include "device/fido/mac/keychain.h" -#include "device/fido/mac/operation_base.h" +#include "device/fido/mac/operation.h" +#include "device/fido/mac/touch_id_context.h" namespace device { namespace fido { @@ -27,17 +29,19 @@ // For documentation on the keychain item metadata, see // |MakeCredentialOperation|. class API_AVAILABLE(macosx(10.12.2)) - COMPONENT_EXPORT(DEVICE_FIDO) GetAssertionOperation - : public OperationBase<CtapGetAssertionRequest, - AuthenticatorGetAssertionResponse> { + COMPONENT_EXPORT(DEVICE_FIDO) GetAssertionOperation : public Operation { public: + using Callback = base::OnceCallback<void( + CtapDeviceResponseCode, + base::Optional<AuthenticatorGetAssertionResponse>)>; + GetAssertionOperation(CtapGetAssertionRequest request, std::string metadata_secret, std::string keychain_access_group, Callback callback); ~GetAssertionOperation() override; - // OperationBase: + // Operation: void Run() override; // GetNextAssertion() may be called for a request with an empty allowList @@ -45,11 +49,20 @@ void GetNextAssertion(Callback callback); private: - const std::string& RpId() const override; - void PromptTouchIdDone(bool success) override; + void PromptTouchIdDone(bool success); base::Optional<AuthenticatorGetAssertionResponse> ResponseForCredential( const Credential& credential); + // The secret parameter passed to |CredentialMetadata| operations to encrypt + // or encode credential metadata for storage in the macOS keychain. + const std::string metadata_secret_; + const std::string keychain_access_group_; + + const std::unique_ptr<TouchIdContext> touch_id_context_ = + TouchIdContext::Create(); + + const CtapGetAssertionRequest request_; + Callback callback_; std::list<Credential> matching_credentials_; DISALLOW_COPY_AND_ASSIGN(GetAssertionOperation);
diff --git a/device/fido/mac/get_assertion_operation.mm b/device/fido/mac/get_assertion_operation.mm index 2867098..4cd7758 100644 --- a/device/fido/mac/get_assertion_operation.mm +++ b/device/fido/mac/get_assertion_operation.mm
@@ -9,6 +9,7 @@ #import <Foundation/Foundation.h> +#include "base/bind.h" #include "base/mac/foundation_util.h" #include "base/mac/mac_logging.h" #include "base/mac/scoped_cftyperef.h" @@ -17,6 +18,7 @@ #include "base/strings/utf_string_conversions.h" #include "components/device_event_log/device_event_log.h" #include "device/fido/fido_constants.h" +#include "device/fido/mac/credential_metadata.h" #include "device/fido/mac/keychain.h" #include "device/fido/mac/util.h" #include "device/fido/public_key_credential_descriptor.h" @@ -34,65 +36,64 @@ std::string metadata_secret, std::string keychain_access_group, Callback callback) - : OperationBase<CtapGetAssertionRequest, AuthenticatorGetAssertionResponse>( - std::move(request), - std::move(metadata_secret), - std::move(keychain_access_group), - std::move(callback)) {} + : metadata_secret_(std::move(metadata_secret)), + keychain_access_group_(std::move(keychain_access_group)), + request_(std::move(request)), + callback_(std::move(callback)) {} GetAssertionOperation::~GetAssertionOperation() = default; -const std::string& GetAssertionOperation::RpId() const { - return request().rp_id; -} - void GetAssertionOperation::Run() { - Init(); // Display the macOS Touch ID prompt. - PromptTouchId(l10n_util::GetStringFUTF16(IDS_WEBAUTHN_TOUCH_ID_PROMPT_REASON, - base::UTF8ToUTF16(RpId()))); + touch_id_context_->PromptTouchId( + l10n_util::GetStringFUTF16(IDS_WEBAUTHN_TOUCH_ID_PROMPT_REASON, + base::UTF8ToUTF16(request_.rp_id)), + base::BindOnce(&GetAssertionOperation::PromptTouchIdDone, + base::Unretained(this))); } void GetAssertionOperation::PromptTouchIdDone(bool success) { if (!success) { - std::move(callback()) - .Run(CtapDeviceResponseCode::kCtap2ErrOperationDenied, base::nullopt); + std::move(callback_).Run(CtapDeviceResponseCode::kCtap2ErrOperationDenied, + base::nullopt); return; } std::set<std::vector<uint8_t>> allowed_credential_ids = - FilterInapplicableEntriesFromAllowList(request()); - if (allowed_credential_ids.empty() && !request().allow_list.empty()) { + FilterInapplicableEntriesFromAllowList(request_); + if (allowed_credential_ids.empty() && !request_.allow_list.empty()) { // The caller checking // TouchIdAuthenticator::HasCredentialForGetAssertionRequest() should have // caught this. NOTREACHED(); - std::move(callback()) - .Run(CtapDeviceResponseCode::kCtap2ErrNoCredentials, base::nullopt); + std::move(callback_).Run(CtapDeviceResponseCode::kCtap2ErrNoCredentials, + base::nullopt); return; } - const bool empty_allow_list = request().allow_list.empty(); + const bool empty_allow_list = request_.allow_list.empty(); std::list<Credential> credentials = - empty_allow_list ? FindResidentCredentialsInKeychain( - keychain_access_group(), metadata_secret(), RpId(), - authentication_context()) - : FindCredentialsInKeychain( - keychain_access_group(), metadata_secret(), RpId(), - allowed_credential_ids, authentication_context()); + empty_allow_list + ? FindResidentCredentialsInKeychain( + keychain_access_group_, metadata_secret_, request_.rp_id, + touch_id_context_->authentication_context()) + : FindCredentialsInKeychain( + keychain_access_group_, metadata_secret_, request_.rp_id, + allowed_credential_ids, + touch_id_context_->authentication_context()); if (credentials.empty()) { - // TouchIdAuthenticator::HasCredentialForGetAssertionRequest() is invoked - // first to ensure this doesn't occur. + // TouchIdAuthenticator::HasCredentialForGetAssertionRequest() is + // invoked first to ensure this doesn't occur. NOTREACHED(); - std::move(callback()) - .Run(CtapDeviceResponseCode::kCtap2ErrNoCredentials, base::nullopt); + std::move(callback_).Run(CtapDeviceResponseCode::kCtap2ErrNoCredentials, + base::nullopt); return; } base::Optional<AuthenticatorGetAssertionResponse> response = ResponseForCredential(credentials.front()); if (!response) { - std::move(callback()) - .Run(CtapDeviceResponseCode::kCtap2ErrNoCredentials, base::nullopt); + std::move(callback_).Run(CtapDeviceResponseCode::kCtap2ErrNoCredentials, + base::nullopt); return; } @@ -102,8 +103,8 @@ matching_credentials_ = std::move(credentials); } - std::move(callback()) - .Run(CtapDeviceResponseCode::kSuccess, std::move(*response)); + std::move(callback_).Run(CtapDeviceResponseCode::kSuccess, + std::move(*response)); } void GetAssertionOperation::GetNextAssertion(Callback callback) { @@ -123,8 +124,8 @@ base::Optional<AuthenticatorGetAssertionResponse> GetAssertionOperation::ResponseForCredential(const Credential& credential) { - base::Optional<CredentialMetadata> metadata = - UnsealCredentialId(metadata_secret(), RpId(), credential.credential_id); + base::Optional<CredentialMetadata> metadata = UnsealCredentialId( + metadata_secret_, request_.rp_id, credential.credential_id); if (!metadata) { // The keychain query already filtered for the RP ID encoded under this // operation's metadata secret, so the credential id really should have @@ -133,10 +134,10 @@ return base::nullopt; } - AuthenticatorData authenticator_data = - MakeAuthenticatorData(RpId(), /*attested_credential_data=*/base::nullopt); + AuthenticatorData authenticator_data = MakeAuthenticatorData( + request_.rp_id, /*attested_credential_data=*/base::nullopt); base::Optional<std::vector<uint8_t>> signature = GenerateSignature( - authenticator_data, request().client_data_hash, credential.private_key); + authenticator_data, request_.client_data_hash, credential.private_key); if (!signature) { FIDO_LOG(ERROR) << "GenerateSignature failed"; return base::nullopt;
diff --git a/device/fido/mac/make_credential_operation.h b/device/fido/mac/make_credential_operation.h index 85fd88c..5495b6371 100644 --- a/device/fido/mac/make_credential_operation.h +++ b/device/fido/mac/make_credential_operation.h
@@ -5,12 +5,14 @@ #ifndef DEVICE_FIDO_MAC_MAKE_CREDENTIAL_OPERATION_H_ #define DEVICE_FIDO_MAC_MAKE_CREDENTIAL_OPERATION_H_ +#include "base/callback.h" #include "base/component_export.h" #include "base/mac/availability.h" #include "base/macros.h" #include "device/fido/authenticator_make_credential_response.h" #include "device/fido/ctap_make_credential_request.h" -#include "device/fido/mac/operation_base.h" +#include "device/fido/mac/operation.h" +#include "device/fido/mac/touch_id_context.h" namespace device { namespace fido { @@ -43,22 +45,42 @@ // separate from any other data that Chrome may store in the keychain in // the future. class API_AVAILABLE(macosx(10.12.2)) - COMPONENT_EXPORT(DEVICE_FIDO) MakeCredentialOperation - : public OperationBase<CtapMakeCredentialRequest, - AuthenticatorMakeCredentialResponse> { + COMPONENT_EXPORT(DEVICE_FIDO) MakeCredentialOperation : public Operation { public: + using Callback = base::OnceCallback<void( + CtapDeviceResponseCode, + base::Optional<AuthenticatorMakeCredentialResponse>)>; + MakeCredentialOperation(CtapMakeCredentialRequest request, std::string profile_id, std::string keychain_access_group, Callback callback); ~MakeCredentialOperation() override; + // Operation: void Run() override; private: - // OperationBase: - const std::string& RpId() const override; - void PromptTouchIdDone(bool success) override; + void PromptTouchIdDone(bool success); + + // DefaultKeychainQuery returns a default keychain query dictionary that has + // the keychain item class, keychain access group and RP ID filled out (but + // not the credential ID). More fields can be set on the return value to + // refine the query. + base::ScopedCFTypeRef<CFMutableDictionaryRef> DefaultKeychainQuery() const; + + // The secret parameter passed to |CredentialMetadata| operations to encrypt + // or encode credential metadata for storage in the macOS keychain. + const std::string metadata_secret_; + const std::string keychain_access_group_; + + const std::unique_ptr<TouchIdContext> touch_id_context_ = + TouchIdContext::Create(); + + const CtapMakeCredentialRequest request_; + Callback callback_; + + DISALLOW_COPY_AND_ASSIGN(MakeCredentialOperation); }; } // namespace mac
diff --git a/device/fido/mac/make_credential_operation.mm b/device/fido/mac/make_credential_operation.mm index e0e8788..0e2ead1 100644 --- a/device/fido/mac/make_credential_operation.mm +++ b/device/fido/mac/make_credential_operation.mm
@@ -8,9 +8,11 @@ #import <Foundation/Foundation.h> +#include "base/bind.h" #include "base/mac/foundation_util.h" #include "base/mac/mac_logging.h" #include "base/mac/scoped_cftyperef.h" +#include "base/strings/sys_string_conversions.h" #include "base/strings/utf_string_conversions.h" #include "components/device_event_log/device_event_log.h" #include "device/fido/attestation_statement_formats.h" @@ -36,20 +38,13 @@ std::string metadata_secret, std::string keychain_access_group, Callback callback) - : OperationBase<CtapMakeCredentialRequest, - AuthenticatorMakeCredentialResponse>( - std::move(request), - std::move(metadata_secret), - std::move(keychain_access_group), - std::move(callback)) {} + : metadata_secret_(std::move(metadata_secret)), + keychain_access_group_(std::move(keychain_access_group)), + request_(std::move(request)), + callback_(std::move(callback)) {} MakeCredentialOperation::~MakeCredentialOperation() = default; -const std::string& MakeCredentialOperation::RpId() const { - return request().rp.id; -} - void MakeCredentialOperation::Run() { - Init(); // Verify pubKeyCredParams contains ES-256, which is the only algorithm we // support. auto is_es256 = @@ -58,30 +53,32 @@ static_cast<int>(CoseAlgorithmIdentifier::kCoseEs256); }; const auto& key_params = - request().public_key_credential_params.public_key_credential_params(); + request_.public_key_credential_params.public_key_credential_params(); if (!std::any_of(key_params.begin(), key_params.end(), is_es256)) { DVLOG(1) << "No supported algorithm found."; - std::move(callback()) - .Run(CtapDeviceResponseCode::kCtap2ErrUnsupportedAlgorithm, - base::nullopt); + std::move(callback_).Run( + CtapDeviceResponseCode::kCtap2ErrUnsupportedAlgorithm, base::nullopt); return; } // Display the macOS Touch ID prompt. - PromptTouchId(l10n_util::GetStringFUTF16(IDS_WEBAUTHN_TOUCH_ID_PROMPT_REASON, - base::UTF8ToUTF16(RpId()))); + touch_id_context_->PromptTouchId( + l10n_util::GetStringFUTF16(IDS_WEBAUTHN_TOUCH_ID_PROMPT_REASON, + base::UTF8ToUTF16(request_.rp.id)), + base::BindOnce(&MakeCredentialOperation::PromptTouchIdDone, + base::Unretained(this))); } void MakeCredentialOperation::PromptTouchIdDone(bool success) { if (!success) { - std::move(callback()) - .Run(CtapDeviceResponseCode::kCtap2ErrOperationDenied, base::nullopt); + std::move(callback_).Run(CtapDeviceResponseCode::kCtap2ErrOperationDenied, + base::nullopt); return; } // Evaluate that excludeList does not contain any credentials stored by this // authenticator. - for (auto& credential : request().exclude_list) { + for (auto& credential : request_.exclude_list) { ScopedCFTypeRef<CFMutableDictionaryRef> query = DefaultKeychainQuery(); CFDictionarySetValue(query, kSecAttrApplicationLabel, [NSData dataWithBytes:credential.id().data() @@ -90,16 +87,15 @@ if (status == errSecSuccess) { // Excluded item found. DVLOG(1) << "credential from excludeList found"; - std::move(callback()) - .Run(CtapDeviceResponseCode::kCtap2ErrCredentialExcluded, - base::nullopt); + std::move(callback_).Run( + CtapDeviceResponseCode::kCtap2ErrCredentialExcluded, base::nullopt); return; } if (status != errSecItemNotFound) { // Unexpected keychain error. OSSTATUS_DLOG(ERROR, status) << "failed to check for excluded credential"; - std::move(callback()) - .Run(CtapDeviceResponseCode::kCtap2ErrOther, base::nullopt); + std::move(callback_).Run(CtapDeviceResponseCode::kCtap2ErrOther, + base::nullopt); return; } } @@ -109,7 +105,7 @@ // Note that because the rk bit is not encoded here, a resident credential // may overwrite a non-resident credential and vice versa. const std::string encoded_rp_id_user_id = - EncodeRpIdAndUserId(metadata_secret(), RpId(), request().user.id); + EncodeRpIdAndUserId(metadata_secret_, request_.rp.id, request_.user.id); { ScopedCFTypeRef<CFMutableDictionaryRef> query = DefaultKeychainQuery(); CFDictionarySetValue(query, kSecAttrApplicationTag, @@ -117,17 +113,17 @@ OSStatus status = Keychain::GetInstance().ItemDelete(query); if (status != errSecSuccess && status != errSecItemNotFound) { OSSTATUS_DLOG(ERROR, status) << "SecItemDelete failed"; - std::move(callback()) - .Run(CtapDeviceResponseCode::kCtap2ErrOther, base::nullopt); + std::move(callback_).Run(CtapDeviceResponseCode::kCtap2ErrOther, + base::nullopt); return; } } // Generate the new key pair. const std::vector<uint8_t> credential_id = - SealCredentialId(metadata_secret(), RpId(), + SealCredentialId(metadata_secret_, request_.rp.id, CredentialMetadata::FromPublicKeyCredentialUserEntity( - request().user, request().resident_key_required)); + request_.user, request_.resident_key_required)); ScopedCFTypeRef<CFMutableDictionaryRef> params( CFDictionaryCreateMutable(kCFAllocatorDefault, 0, nullptr, nullptr)); @@ -142,9 +138,9 @@ CFDictionarySetValue(params, kSecPrivateKeyAttrs, private_key_params); CFDictionarySetValue(private_key_params, kSecAttrIsPermanent, @YES); CFDictionarySetValue(private_key_params, kSecAttrAccessControl, - access_control()); + touch_id_context_->access_control()); CFDictionarySetValue(private_key_params, kSecUseAuthenticationContext, - authentication_context()); + touch_id_context_->authentication_context()); CFDictionarySetValue(private_key_params, kSecAttrApplicationTag, base::SysUTF8ToNSString(encoded_rp_id_user_id)); CFDictionarySetValue(private_key_params, kSecAttrApplicationLabel, @@ -157,16 +153,16 @@ cferr.InitializeInto())); if (!private_key) { FIDO_LOG(ERROR) << "SecKeyCreateRandomKey failed: " << cferr; - std::move(callback()) - .Run(CtapDeviceResponseCode::kCtap2ErrOther, base::nullopt); + std::move(callback_).Run(CtapDeviceResponseCode::kCtap2ErrOther, + base::nullopt); return; } ScopedCFTypeRef<SecKeyRef> public_key( Keychain::GetInstance().KeyCopyPublicKey(private_key)); if (!public_key) { FIDO_LOG(ERROR) << "SecKeyCopyPublicKey failed"; - std::move(callback()) - .Run(CtapDeviceResponseCode::kCtap2ErrOther, base::nullopt); + std::move(callback_).Run(CtapDeviceResponseCode::kCtap2ErrOther, + base::nullopt); return; } @@ -177,18 +173,18 @@ SecKeyRefToECPublicKey(public_key)); if (!attested_credential_data) { FIDO_LOG(ERROR) << "MakeAttestedCredentialData failed"; - std::move(callback()) - .Run(CtapDeviceResponseCode::kCtap2ErrOther, base::nullopt); + std::move(callback_).Run(CtapDeviceResponseCode::kCtap2ErrOther, + base::nullopt); return; } - AuthenticatorData authenticator_data = - MakeAuthenticatorData(RpId(), std::move(*attested_credential_data)); + AuthenticatorData authenticator_data = MakeAuthenticatorData( + request_.rp.id, std::move(*attested_credential_data)); base::Optional<std::vector<uint8_t>> signature = GenerateSignature( - authenticator_data, request().client_data_hash, private_key); + authenticator_data, request_.client_data_hash, private_key); if (!signature) { FIDO_LOG(ERROR) << "MakeSignature failed"; - std::move(callback()) - .Run(CtapDeviceResponseCode::kCtap2ErrOther, base::nullopt); + std::move(callback_).Run(CtapDeviceResponseCode::kCtap2ErrOther, + base::nullopt); return; } AuthenticatorMakeCredentialResponse response( @@ -198,10 +194,22 @@ std::make_unique<PackedAttestationStatement>( CoseAlgorithmIdentifier::kCoseEs256, std::move(*signature), /*x509_certificates=*/std::vector<std::vector<uint8_t>>()))); - std::move(callback()) - .Run(CtapDeviceResponseCode::kSuccess, std::move(response)); + std::move(callback_).Run(CtapDeviceResponseCode::kSuccess, + std::move(response)); } +base::ScopedCFTypeRef<CFMutableDictionaryRef> +MakeCredentialOperation::DefaultKeychainQuery() const { + base::ScopedCFTypeRef<CFMutableDictionaryRef> query( + CFDictionaryCreateMutable(kCFAllocatorDefault, 0, nullptr, nullptr)); + CFDictionarySetValue(query, kSecClass, kSecClassKey); + CFDictionarySetValue(query, kSecAttrAccessGroup, + base::SysUTF8ToNSString(keychain_access_group_)); + CFDictionarySetValue( + query, kSecAttrLabel, + base::SysUTF8ToNSString(EncodeRpId(metadata_secret_, request_.rp.id))); + return query; +} } // namespace mac } // namespace fido } // namespace device
diff --git a/device/fido/mac/operation.h b/device/fido/mac/operation.h index 191a2dbe..c62a2c9 100644 --- a/device/fido/mac/operation.h +++ b/device/fido/mac/operation.h
@@ -11,15 +11,12 @@ namespace fido { namespace mac { -// Operation is the interface to OperationBase. class Operation { public: + Operation() = default; virtual ~Operation() = default; virtual void Run() = 0; - protected: - Operation() = default; - private: DISALLOW_COPY_AND_ASSIGN(Operation); };
diff --git a/device/fido/mac/operation_base.h b/device/fido/mac/operation_base.h deleted file mode 100644 index be25331..0000000 --- a/device/fido/mac/operation_base.h +++ /dev/null
@@ -1,113 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef DEVICE_FIDO_MAC_OPERATION_BASE_H_ -#define DEVICE_FIDO_MAC_OPERATION_BASE_H_ - -#import <Foundation/Foundation.h> -#import <Security/Security.h> - -#include "base/bind.h" -#include "base/callback.h" -#include "base/mac/scoped_cftyperef.h" -#include "base/macros.h" -#include "base/strings/sys_string_conversions.h" -#include "device/fido/mac/credential_metadata.h" -#include "device/fido/mac/operation.h" -#include "device/fido/mac/touch_id_context.h" - -namespace device { -namespace fido { -namespace mac { - -// OperationBase abstracts behavior common to both concrete Operations, -// |MakeCredentialOperation| and |GetAssertionOperation|. -template <class Request, class Response> -class API_AVAILABLE(macosx(10.12.2)) OperationBase : public Operation { - public: - using Callback = base::OnceCallback<void(CtapDeviceResponseCode, - base::Optional<Response>)>; - - OperationBase(Request request, - std::string metadata_secret, - std::string keychain_access_group, - Callback callback) - : request_(std::move(request)), - metadata_secret_(std::move(metadata_secret)), - keychain_access_group_(std::move(keychain_access_group)), - callback_(std::move(callback)), - touch_id_context_(TouchIdContext::Create()) {} - - ~OperationBase() override = default; - - protected: - // Subclasses must call Init() at the beginning of Run(). - void Init() { encoded_rp_id_ = EncodeRpId(metadata_secret(), RpId()); } - - // PromptTouchId triggers a Touch ID consent dialog with the given reason - // string. Subclasses implement the PromptTouchIdDone callback to receive the - // result. - void PromptTouchId(const base::string16& reason) { - // The callback passed to TouchIdContext::Prompt will not fire if the - // TouchIdContext itself has been deleted. Since that it is owned by this - // class, there is no need to bind the callback to a weak ref here. - touch_id_context_->PromptTouchId( - reason, base::BindOnce(&OperationBase::PromptTouchIdDone, - base::Unretained(this))); - } - - // Callback for |PromptTouchId|. - virtual void PromptTouchIdDone(bool success) = 0; - - // Subclasses override RpId to return the RP ID from the type-specific - // request. - virtual const std::string& RpId() const = 0; - - LAContext* authentication_context() const { - return touch_id_context_->authentication_context(); - } - SecAccessControlRef access_control() const { - return touch_id_context_->access_control(); - } - - // DefaultKeychainQuery returns a default keychain query dictionary that has - // the keychain item class, keychain access group and RP ID filled out (but - // not the credential ID). More fields can be set on the return value to - // refine the query. - base::ScopedCFTypeRef<CFMutableDictionaryRef> DefaultKeychainQuery() const { - base::ScopedCFTypeRef<CFMutableDictionaryRef> query( - CFDictionaryCreateMutable(kCFAllocatorDefault, 0, nullptr, nullptr)); - CFDictionarySetValue(query, kSecClass, kSecClassKey); - CFDictionarySetValue(query, kSecAttrAccessGroup, - base::SysUTF8ToNSString(keychain_access_group_)); - DCHECK(!encoded_rp_id_.empty()); - CFDictionarySetValue(query, kSecAttrLabel, - base::SysUTF8ToNSString(encoded_rp_id_)); - return query; - } - - const std::string& metadata_secret() const { return metadata_secret_; } - const std::string& keychain_access_group() const { - return keychain_access_group_; - } - const Request& request() const { return request_; } - Callback& callback() { return callback_; } - - private: - Request request_; - // The secret parameter passed to |CredentialMetadata| operations to encrypt - // or encode credential metadata for storage in the macOS keychain. - std::string metadata_secret_; - std::string keychain_access_group_; - std::string encoded_rp_id_ = ""; - Callback callback_; - - std::unique_ptr<TouchIdContext> touch_id_context_; -}; - -} // namespace mac -} // namespace fido -} // namespace device - -#endif // DEVICE_FIDO_MAC_OPERATION_BASE_H_
diff --git a/extensions/common/api/_behavior_features.json b/extensions/common/api/_behavior_features.json index 1a34c0ad..6c6e5b7 100644 --- a/extensions/common/api/_behavior_features.json +++ b/extensions/common/api/_behavior_features.json
@@ -69,7 +69,6 @@ "2F47B526FA71F44816618C41EC55E5EE9543FDCC", // Braille Keyboard "86672C8D7A04E24EFB244BF96FE518C4C4809F73", // Speech synthesis "1CF709D51B2B96CF79D00447300BD3BFBE401D21", // Mobile activation - "D519188F86D9ACCEE0412007B227D9936EB9676B", // Gaia auth extension "40FF1103292F40C34066E023B8BE8CAE18306EAE", // Chromeos help "3C654B3B6682CA194E75AD044CEDE927675DDEE8", // Easy unlock "2FCBCE08B34CCA1728A85F1EFBD9A34DD2558B2E", // ChromeVox
diff --git a/extensions/test/test_extension_dir.cc b/extensions/test/test_extension_dir.cc index 8e1e94f0..0941ae2e 100644 --- a/extensions/test/test_extension_dir.cc +++ b/extensions/test/test_extension_dir.cc
@@ -28,13 +28,6 @@ WriteFile(FILE_PATH_LITERAL("manifest.json"), manifest); } -void TestExtensionDir::WriteManifestWithSingleQuotes( - base::StringPiece manifest) { - std::string double_quotes; - base::ReplaceChars(manifest.data(), "'", "\"", &double_quotes); - WriteManifest(double_quotes); -} - void TestExtensionDir::WriteFile(const base::FilePath::StringType& filename, base::StringPiece contents) { base::ScopedAllowBlockingForTesting allow_blocking;
diff --git a/extensions/test/test_extension_dir.h b/extensions/test/test_extension_dir.h index d9d30d2..1b0fa73 100644 --- a/extensions/test/test_extension_dir.h +++ b/extensions/test/test_extension_dir.h
@@ -23,12 +23,6 @@ // is performed. If desired this should be done on extension installation. void WriteManifest(base::StringPiece manifest); - // Like WriteManifest, but where the |manifest| is given in single-quotes - // rather than double-quotes. This is for convenience to avoid escaping. - // - // E.g. |manifest| can be {'name': 'me'} rather than {\"name\": \"me\"}. - void WriteManifestWithSingleQuotes(base::StringPiece manifest); - // Writes |contents| to |filename| within the unpacked dir, overwriting // anything that was already there. void WriteFile(const base::FilePath::StringType& filename,
diff --git a/google_apis/gaia/fake_gaia.cc b/google_apis/gaia/fake_gaia.cc index 1300753..fe66742 100644 --- a/google_apis/gaia/fake_gaia.cc +++ b/google_apis/gaia/fake_gaia.cc
@@ -61,9 +61,6 @@ const char kDefaultGaiaId[] = "12345"; -const base::FilePath::CharType kServiceLogin[] = - FILE_PATH_LITERAL("google_apis/test/service_login.html"); - const base::FilePath::CharType kEmbeddedSetupChromeos[] = FILE_PATH_LITERAL("google_apis/test/embedded_setup_chromeos.html"); @@ -143,9 +140,6 @@ base::FilePath source_root_dir; base::PathService::Get(base::DIR_SOURCE_ROOT, &source_root_dir); CHECK(base::ReadFileToString( - source_root_dir.Append(base::FilePath(kServiceLogin)), - &service_login_response_)); - CHECK(base::ReadFileToString( source_root_dir.Append(base::FilePath(kEmbeddedSetupChromeos)), &embedded_setup_chromeos_response_)); } @@ -212,10 +206,6 @@ REGISTER_RESPONSE_HANDLER( gaia_urls->merge_session_url(), HandleMergeSession); - // Handles /ServiceLogin GAIA call. - REGISTER_RESPONSE_HANDLER( - gaia_urls->service_login_url(), HandleServiceLogin); - // Handles /embedded/setup/v2/chromeos GAIA call. REGISTER_RESPONSE_HANDLER(gaia_urls->embedded_setup_chromeos_url(2), HandleEmbeddedSetupChromeos); @@ -445,13 +435,6 @@ return nullptr; } -void FakeGaia::HandleServiceLogin(const HttpRequest& request, - BasicHttpResponse* http_response) { - http_response->set_code(net::HTTP_OK); - http_response->set_content(service_login_response_); - http_response->set_content_type("text/html"); -} - void FakeGaia::HandleEmbeddedSetupChromeos(const HttpRequest& request, BasicHttpResponse* http_response) { GURL request_url = GURL("http://localhost").Resolve(request.relative_url);
diff --git a/google_apis/gaia/fake_gaia.h b/google_apis/gaia/fake_gaia.h index ee6e367..3b2a025f9 100644 --- a/google_apis/gaia/fake_gaia.h +++ b/google_apis/gaia/fake_gaia.h
@@ -270,7 +270,6 @@ EmailToGaiaIdMap email_to_gaia_id_map_; AccessTokenInfoMap access_token_info_map_; RequestHandlerMap request_handlers_; - std::string service_login_response_; std::string embedded_setup_chromeos_response_; SamlAccountIdpMap saml_account_idp_map_; SamlDomainRedirectUrlMap saml_domain_url_map_;
diff --git a/google_apis/test/service_login.html b/google_apis/test/service_login.html deleted file mode 100644 index 332be01..0000000 --- a/google_apis/test/service_login.html +++ /dev/null
@@ -1,64 +0,0 @@ -<HTML> -<HEAD> -<SCRIPT> -var gaia = gaia || {}; -gaia.chromeOSLogin = {}; - -gaia.chromeOSLogin.parent_page_url_ = -'chrome-extension://mfffpogegjflfpflabcdkioaeobkgjik/main.html'; - -gaia.chromeOSLogin.attemptLogin = function(email, password, attemptToken) { - var msg = { - 'method': 'attemptLogin', - 'email': email, - 'password': password, - 'attemptToken': attemptToken - }; - window.parent.postMessage(msg, gaia.chromeOSLogin.parent_page_url_); -}; - -gaia.chromeOSLogin.onAttemptedLogin = function(emailFormElement, - passwordFormElement, - continueUrlElement) { - var email = emailFormElement.value; - var passwd = passwordFormElement.value; - var attemptToken = new Date().getTime(); - - gaia.chromeOSLogin.attemptLogin(email, passwd, attemptToken); - - if (continueUrlElement) { - var prevAttemptIndex = continueUrlElement.value.indexOf('?attemptToken'); - if (prevAttemptIndex != -1) { - continueUrlElement.value = - continueUrlElement.value.substr(0, prevAttemptIndex); - } - continueUrlElement.value += '?attemptToken=' + attemptToken; - } -}; - -function submitAndGo() { - gaia.chromeOSLogin.onAttemptedLogin(document.getElementById("Email"), - document.getElementById("Passwd"), - document.getElementById("continue")); - return true; -} - -function onAuthError() { - if (window.domAutomationController) { - window.domAutomationController.send('loginfail'); - } -} - -</SCRIPT> -</HEAD> -<BODY> - Local Auth Server:<BR> - <FORM action='/ServiceLoginAuth' method=POST onsubmit='submitAndGo()'> - <INPUT TYPE=text id="Email" name="Email"> - <INPUT TYPE=text id="Passwd" name="Passwd"> - <INPUT TYPE=hidden id="continue" name="continue" - value="chrome-extension://mfffpogegjflfpflabcdkioaeobkgjik/success.html"> - <INPUT TYPE=Submit id="signIn"> - </FORM> -</BODY> -</HTML>
diff --git a/gpu/command_buffer/service/shared_context_state.cc b/gpu/command_buffer/service/shared_context_state.cc index 38d551b..5ac1d3e4 100644 --- a/gpu/command_buffer/service/shared_context_state.cc +++ b/gpu/command_buffer/service/shared_context_state.cc
@@ -424,7 +424,8 @@ break; } - transfer_cache_->PurgeMemory(memory_pressure_level); + if (transfer_cache_) + transfer_cache_->PurgeMemory(memory_pressure_level); } uint64_t SharedContextState::GetMemoryUsage() {
diff --git a/headless/lib/browser/headless_web_contents_impl.cc b/headless/lib/browser/headless_web_contents_impl.cc index 2de537a..84a8833 100644 --- a/headless/lib/browser/headless_web_contents_impl.cc +++ b/headless/lib/browser/headless_web_contents_impl.cc
@@ -13,6 +13,7 @@ #include "base/memory/weak_ptr.h" #include "base/stl_util.h" #include "base/strings/utf_string_conversions.h" +#include "base/task/post_task.h" #include "base/trace_event/trace_event.h" #include "base/values.h" #include "components/security_state/content/content_utils.h" @@ -304,6 +305,10 @@ agent_host_->RemoveObserver(this); if (render_process_host_) render_process_host_->RemoveObserver(this); + // Defer destruction of WindowTreeHost, as it does sync mojo calls + // in the destructor of ui::Compositor. + base::SequencedTaskRunnerHandle::Get()->DeleteSoon( + FROM_HERE, std::move(window_tree_host_)); } void HeadlessWebContentsImpl::RenderFrameCreated(
diff --git a/headless/test/headless_browser_test.cc b/headless/test/headless_browser_test.cc index f0d0459..b0d1eec 100644 --- a/headless/test/headless_browser_test.cc +++ b/headless/test/headless_browser_test.cc
@@ -295,6 +295,9 @@ browser()->GetDevToolsTarget()->DetachClient(browser_devtools_client_.get()); browser_context_->Close(); browser_context_ = nullptr; + // Let the tasks that might have beein scheduled during web contents + // being closed run (see https://crbug.com/1036627 for details). + base::RunLoop().RunUntilIdle(); } bool HeadlessAsyncDevTooledBrowserTest::GetEnableBeginFrameControl() {
diff --git a/ios/chrome/app/application_delegate/BUILD.gn b/ios/chrome/app/application_delegate/BUILD.gn index 5c118e1..b51eb860 100644 --- a/ios/chrome/app/application_delegate/BUILD.gn +++ b/ios/chrome/app/application_delegate/BUILD.gn
@@ -152,6 +152,7 @@ "CoreSpotlight.framework", "UIKit.framework", ] + allow_circular_includes_from = [ "//ios/chrome/browser/url_loading" ] } source_set("test_support") {
diff --git a/ios/chrome/browser/overlays/aggregate_overlay_request_support_unittest.cc b/ios/chrome/browser/overlays/aggregate_overlay_request_support_unittest.cc index c22476ea..a3ca9129 100644 --- a/ios/chrome/browser/overlays/aggregate_overlay_request_support_unittest.cc +++ b/ios/chrome/browser/overlays/aggregate_overlay_request_support_unittest.cc
@@ -6,27 +6,14 @@ #include "ios/chrome/browser/overlays/public/overlay_request.h" #include "ios/chrome/browser/overlays/public/overlay_request_config.h" +#include "ios/chrome/browser/overlays/test/overlay_test_macros.h" #include "testing/platform_test.h" namespace { // Fake request config types. -class FirstConfig : public OverlayRequestConfig<FirstConfig> { - private: - OVERLAY_USER_DATA_SETUP(FirstConfig); -}; -OVERLAY_USER_DATA_SETUP_IMPL(FirstConfig); - -class SecondConfig : public OverlayRequestConfig<SecondConfig> { - private: - OVERLAY_USER_DATA_SETUP(SecondConfig); -}; -OVERLAY_USER_DATA_SETUP_IMPL(SecondConfig); - -class ThirdConfig : public OverlayRequestConfig<ThirdConfig> { - private: - OVERLAY_USER_DATA_SETUP(ThirdConfig); -}; -OVERLAY_USER_DATA_SETUP_IMPL(ThirdConfig); +DEFINE_TEST_OVERLAY_REQUEST_CONFIG(FirstConfig); +DEFINE_TEST_OVERLAY_REQUEST_CONFIG(SecondConfig); +DEFINE_TEST_OVERLAY_REQUEST_CONFIG(ThirdConfig); } // namespace using AggregateOverlayRequestSupportTest = PlatformTest;
diff --git a/ios/chrome/browser/overlays/default_overlay_request_cancel_handler_unittest.mm b/ios/chrome/browser/overlays/default_overlay_request_cancel_handler_unittest.mm index a8c42d5..63d7ecb 100644 --- a/ios/chrome/browser/overlays/default_overlay_request_cancel_handler_unittest.mm +++ b/ios/chrome/browser/overlays/default_overlay_request_cancel_handler_unittest.mm
@@ -21,7 +21,7 @@ public: DefaultOverlayRequestCancelHandlerTest() : PlatformTest() { std::unique_ptr<OverlayRequest> request = - OverlayRequest::CreateWithConfig<FakeOverlayUserData>(nullptr); + OverlayRequest::CreateWithConfig<FakeOverlayUserData>(); queue()->AddRequest(std::move(request)); }
diff --git a/ios/chrome/browser/overlays/overlay_callback_manager_impl_unittest.cc b/ios/chrome/browser/overlays/overlay_callback_manager_impl_unittest.cc index 433b009e..d3548742 100644 --- a/ios/chrome/browser/overlays/overlay_callback_manager_impl_unittest.cc +++ b/ios/chrome/browser/overlays/overlay_callback_manager_impl_unittest.cc
@@ -7,20 +7,13 @@ #include "base/bind.h" #include "ios/chrome/browser/overlays/public/overlay_response.h" #include "ios/chrome/browser/overlays/test/fake_overlay_user_data.h" +#include "ios/chrome/browser/overlays/test/overlay_test_macros.h" #include "testing/platform_test.h" namespace { // Fake dispatch response info types. -class FirstResponseInfo : public OverlayUserData<FirstResponseInfo> { - private: - OVERLAY_USER_DATA_SETUP(FirstResponseInfo); -}; -OVERLAY_USER_DATA_SETUP_IMPL(FirstResponseInfo); -class SecondResponseInfo : public OverlayUserData<SecondResponseInfo> { - private: - OVERLAY_USER_DATA_SETUP(SecondResponseInfo); -}; -OVERLAY_USER_DATA_SETUP_IMPL(SecondResponseInfo); +DEFINE_TEST_OVERLAY_RESPONSE_INFO(FirstResponseInfo); +DEFINE_TEST_OVERLAY_RESPONSE_INFO(SecondResponseInfo); } // namespace using OverlayCallbackManagerImplTest = PlatformTest;
diff --git a/ios/chrome/browser/overlays/overlay_presenter_impl_unittest.mm b/ios/chrome/browser/overlays/overlay_presenter_impl_unittest.mm index 2a2b901..c17e62f 100644 --- a/ios/chrome/browser/overlays/overlay_presenter_impl_unittest.mm +++ b/ios/chrome/browser/overlays/overlay_presenter_impl_unittest.mm
@@ -92,7 +92,7 @@ if (!queue) return nullptr; std::unique_ptr<OverlayRequest> inserted_request = - OverlayRequest::CreateWithConfig<FakeOverlayUserData>(nullptr); + OverlayRequest::CreateWithConfig<FakeOverlayUserData>(); OverlayRequest* request = inserted_request.get(); if (expect_presentation) EXPECT_CALL(observer(), WillShowOverlay(&presenter(), request));
diff --git a/ios/chrome/browser/overlays/overlay_request_impl_unittest.cc b/ios/chrome/browser/overlays/overlay_request_impl_unittest.cc index 5a8fe1fd..e7c626d 100644 --- a/ios/chrome/browser/overlays/overlay_request_impl_unittest.cc +++ b/ios/chrome/browser/overlays/overlay_request_impl_unittest.cc
@@ -16,7 +16,7 @@ TEST_F(OverlayRequestImplTest, ExecuteCallback) { void* kResponseData = &kResponseData; std::unique_ptr<OverlayRequest> request = - OverlayRequest::CreateWithConfig<FakeOverlayUserData>(nullptr); + OverlayRequest::CreateWithConfig<FakeOverlayUserData>(); __block bool callback_executed = false; request->GetCallbackManager()->AddCompletionCallback( base::BindOnce(base::RetainBlock(^(OverlayResponse* response) {
diff --git a/ios/chrome/browser/overlays/overlay_request_queue_impl_unittest.mm b/ios/chrome/browser/overlays/overlay_request_queue_impl_unittest.mm index ea165b8..05c4215 100644 --- a/ios/chrome/browser/overlays/overlay_request_queue_impl_unittest.mm +++ b/ios/chrome/browser/overlays/overlay_request_queue_impl_unittest.mm
@@ -60,7 +60,7 @@ OverlayRequest* AddRequest() { std::unique_ptr<OverlayRequest> passed_request = - OverlayRequest::CreateWithConfig<FakeOverlayUserData>(nullptr); + OverlayRequest::CreateWithConfig<FakeOverlayUserData>(); OverlayRequest* request = passed_request.get(); EXPECT_CALL(observer(), RequestAddedToQueue(queue(), request, queue()->size())); @@ -165,7 +165,7 @@ // when cancelling a request with a custom cancel handler. TEST_F(OverlayRequestQueueImplTest, CustomCancelHandler) { std::unique_ptr<OverlayRequest> passed_request = - OverlayRequest::CreateWithConfig<FakeOverlayUserData>(nullptr); + OverlayRequest::CreateWithConfig<FakeOverlayUserData>(); OverlayRequest* request = passed_request.get(); std::unique_ptr<FakeCancelHandler> passed_cancel_handler = std::make_unique<FakeCancelHandler>(request, queue());
diff --git a/ios/chrome/browser/overlays/overlay_request_support_unittest.cc b/ios/chrome/browser/overlays/overlay_request_support_unittest.cc index b8cf8cd..2908ad04 100644 --- a/ios/chrome/browser/overlays/overlay_request_support_unittest.cc +++ b/ios/chrome/browser/overlays/overlay_request_support_unittest.cc
@@ -5,15 +5,12 @@ #include "ios/chrome/browser/overlays/public/overlay_request_support.h" #include "ios/chrome/browser/overlays/test/fake_overlay_user_data.h" +#include "ios/chrome/browser/overlays/test/overlay_test_macros.h" #include "testing/platform_test.h" namespace { // Fake request config type for use in tests. -class FakeConfig : public OverlayUserData<FakeConfig> { - private: - OVERLAY_USER_DATA_SETUP(FakeConfig); -}; -OVERLAY_USER_DATA_SETUP_IMPL(FakeConfig); +DEFINE_TEST_OVERLAY_REQUEST_CONFIG(FakeConfig); } // namespace using SupportsOverlayRequestTest = PlatformTest; @@ -21,7 +18,7 @@ // Tests that OverlayRequestSupport::All() supports arbitrary config types. TEST_F(SupportsOverlayRequestTest, SupportAll) { std::unique_ptr<OverlayRequest> first_request = - OverlayRequest::CreateWithConfig<FakeOverlayUserData>(nullptr); + OverlayRequest::CreateWithConfig<FakeOverlayUserData>(); std::unique_ptr<OverlayRequest> second_request = OverlayRequest::CreateWithConfig<FakeConfig>(); @@ -33,7 +30,7 @@ // Tests that OverlayRequestSupport::None() does not support config types. TEST_F(SupportsOverlayRequestTest, SupportNone) { std::unique_ptr<OverlayRequest> first_request = - OverlayRequest::CreateWithConfig<FakeOverlayUserData>(nullptr); + OverlayRequest::CreateWithConfig<FakeOverlayUserData>(); std::unique_ptr<OverlayRequest> second_request = OverlayRequest::CreateWithConfig<FakeConfig>(); @@ -51,7 +48,7 @@ // Verify that FakeOverlayUserData requests aren't supported. std::unique_ptr<OverlayRequest> unsupported_request = - OverlayRequest::CreateWithConfig<FakeOverlayUserData>(nullptr); + OverlayRequest::CreateWithConfig<FakeOverlayUserData>(); EXPECT_FALSE(support->IsRequestSupported(unsupported_request.get())); // Verify that FakeConfig requests are supported.
diff --git a/ios/chrome/browser/overlays/test/BUILD.gn b/ios/chrome/browser/overlays/test/BUILD.gn index ab2ca63..00d4182 100644 --- a/ios/chrome/browser/overlays/test/BUILD.gn +++ b/ios/chrome/browser/overlays/test/BUILD.gn
@@ -9,6 +9,7 @@ "fake_overlay_presentation_context.h", "fake_overlay_user_data.cc", "fake_overlay_user_data.h", + "overlay_test_macros.h", ] configs += [ "//build/config/compiler:enable_arc" ]
diff --git a/ios/chrome/browser/overlays/test/fake_overlay_user_data.h b/ios/chrome/browser/overlays/test/fake_overlay_user_data.h index 7e0b256c..fe9b507 100644 --- a/ios/chrome/browser/overlays/test/fake_overlay_user_data.h +++ b/ios/chrome/browser/overlays/test/fake_overlay_user_data.h
@@ -16,7 +16,7 @@ private: OVERLAY_USER_DATA_SETUP(FakeOverlayUserData); - FakeOverlayUserData(void* value); + FakeOverlayUserData(void* value = nullptr); void* value_ = nullptr; };
diff --git a/ios/chrome/browser/overlays/test/overlay_test_macros.h b/ios/chrome/browser/overlays/test/overlay_test_macros.h new file mode 100644 index 0000000..121c757 --- /dev/null +++ b/ios/chrome/browser/overlays/test/overlay_test_macros.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 IOS_CHROME_BROWSER_OVERLAYS_TEST_OVERLAY_TEST_MACROS_H_ +#define IOS_CHROME_BROWSER_OVERLAYS_TEST_OVERLAY_TEST_MACROS_H_ + +#include "ios/chrome/browser/overlays/public/overlay_request_config.h" + +// Macro used to define an OverlayRequestConfig that holds no data. Can be used +// in tests for functionality specific to config types. +#define DEFINE_TEST_OVERLAY_REQUEST_CONFIG(ConfigType) \ + class ConfigType : public OverlayRequestConfig<ConfigType> { \ + private: \ + OVERLAY_USER_DATA_SETUP(ConfigType); \ + }; \ + OVERLAY_USER_DATA_SETUP_IMPL(ConfigType) + +// Macro used to define a response info that holds no data. Can be used +// in tests for functionality specific to info types. +#define DEFINE_TEST_OVERLAY_RESPONSE_INFO(InfoType) \ + class InfoType : public OverlayUserData<InfoType> { \ + private: \ + OVERLAY_USER_DATA_SETUP(InfoType); \ + }; \ + OVERLAY_USER_DATA_SETUP_IMPL(InfoType) + +#endif // IOS_CHROME_BROWSER_OVERLAYS_TEST_OVERLAY_TEST_MACROS_H_
diff --git a/ios/chrome/browser/ui/overlays/common/alerts/alert_overlay_mediator_unittest.mm b/ios/chrome/browser/ui/overlays/common/alerts/alert_overlay_mediator_unittest.mm index 594b965f..c8d5128 100644 --- a/ios/chrome/browser/ui/overlays/common/alerts/alert_overlay_mediator_unittest.mm +++ b/ios/chrome/browser/ui/overlays/common/alerts/alert_overlay_mediator_unittest.mm
@@ -36,7 +36,7 @@ // applied to the consumer. TEST_F(AlertOverlayMediatorTest, SetUpConsumer) { std::unique_ptr<OverlayRequest> request = - OverlayRequest::CreateWithConfig<FakeOverlayUserData>(nullptr); + OverlayRequest::CreateWithConfig<FakeOverlayUserData>(); FakeAlertOverlayMediator* mediator = [[FakeAlertOverlayMediator alloc] initWithRequest:request.get()]; mediator.alertTitle = @"Title";
diff --git a/ios/chrome/browser/ui/overlays/overlay_request_mediator_unittest.mm b/ios/chrome/browser/ui/overlays/overlay_request_mediator_unittest.mm index 8229cb4..24835f1 100644 --- a/ios/chrome/browser/ui/overlays/overlay_request_mediator_unittest.mm +++ b/ios/chrome/browser/ui/overlays/overlay_request_mediator_unittest.mm
@@ -18,7 +18,7 @@ // Tests that the mediator's request is reset after destruction. TEST_F(OverlayRequestMediatorTest, ResetRequestAfterDestruction) { std::unique_ptr<OverlayRequest> request = - OverlayRequest::CreateWithConfig<FakeOverlayUserData>(nullptr); + OverlayRequest::CreateWithConfig<FakeOverlayUserData>(); OverlayRequestMediator* mediator = [[OverlayRequestMediator alloc] initWithRequest:request.get()]; EXPECT_EQ(request.get(), mediator.request);
diff --git a/ios/chrome/browser/ui/overlays/overlay_request_ui_state_unittest.mm b/ios/chrome/browser/ui/overlays/overlay_request_ui_state_unittest.mm index dad5aa0..4ccedf31 100644 --- a/ios/chrome/browser/ui/overlays/overlay_request_ui_state_unittest.mm +++ b/ios/chrome/browser/ui/overlays/overlay_request_ui_state_unittest.mm
@@ -22,8 +22,7 @@ public: OverlayRequestUIStateTest() : PlatformTest(), - request_( - OverlayRequest::CreateWithConfig<FakeOverlayUserData>(nullptr)), + request_(OverlayRequest::CreateWithConfig<FakeOverlayUserData>()), state_(request_.get()) {} OverlayRequest* request() { return request_.get(); }
diff --git a/ios/chrome/browser/url_loading/app_url_loading_service.h b/ios/chrome/browser/url_loading/app_url_loading_service.h index 7ed27d8..3b67cb1 100644 --- a/ios/chrome/browser/url_loading/app_url_loading_service.h +++ b/ios/chrome/browser/url_loading/app_url_loading_service.h
@@ -9,6 +9,7 @@ #import <UIKit/UIKit.h> #include "base/ios/block_types.h" +#import "ios/chrome/app/application_delegate/tab_opening.h" #include "ios/chrome/app/application_mode.h" #include "ui/base/page_transition_types.h" @@ -37,7 +38,7 @@ // If the current tab in |targetMode| is a NTP, it can be reused to open URL. // |completion| is executed after the tab is opened. After Tab is open the // virtual URL is set to the pending navigation item. -- (void)openSelectedTabInMode:(ApplicationMode)targetMode +- (void)openSelectedTabInMode:(ApplicationModeForTabOpening)targetMode withUrlLoadParams:(const UrlLoadParams&)urlLoadParams completion:(ProceduralBlock)completion;
diff --git a/ios/chrome/browser/url_loading/app_url_loading_service.mm b/ios/chrome/browser/url_loading/app_url_loading_service.mm index 6cb7aff..5f7c8026 100644 --- a/ios/chrome/browser/url_loading/app_url_loading_service.mm +++ b/ios/chrome/browser/url_loading/app_url_loading_service.mm
@@ -34,9 +34,10 @@ if (params.from_chrome) { [delegate_ dismissModalDialogsWithCompletion:^{ - [delegate_ openSelectedTabInMode:ApplicationMode::NORMAL - withUrlLoadParams:saved_params - completion:nil]; + [delegate_ + openSelectedTabInMode:ApplicationModeForTabOpening::NORMAL + withUrlLoadParams:saved_params + completion:nil]; } dismissOmnibox:YES]; } else {
diff --git a/net/base/io_buffer.cc b/net/base/io_buffer.cc index 6e2ea7a7..429dbc09 100644 --- a/net/base/io_buffer.cc +++ b/net/base/io_buffer.cc
@@ -9,23 +9,19 @@ namespace net { -namespace { - // TODO(eroman): IOBuffer is being converted to require buffer sizes and offsets // be specified as "size_t" rather than "int" (crbug.com/488553). To facilitate // this move (since LOTS of code needs to be updated), both "size_t" and "int // are being accepted. When using "size_t" this function ensures that it can be // safely converted to an "int" without truncation. -void AssertValidBufferSize(size_t size) { +void IOBuffer::AssertValidBufferSize(size_t size) { base::CheckedNumeric<int>(size).ValueOrDie(); } -void AssertValidBufferSize(int size) { +void IOBuffer::AssertValidBufferSize(int size) { CHECK_GE(size, 0); } -} // namespace - IOBuffer::IOBuffer() : data_(nullptr) {} IOBuffer::IOBuffer(int buffer_size) {
diff --git a/net/base/io_buffer.h b/net/base/io_buffer.h index 4064047..a2944ea5 100644 --- a/net/base/io_buffer.h +++ b/net/base/io_buffer.h
@@ -86,6 +86,9 @@ protected: friend class base::RefCountedThreadSafe<IOBuffer>; + static void AssertValidBufferSize(size_t size); + static void AssertValidBufferSize(int size); + // Only allow derived classes to specify data_. // In all other cases, we own data_, and must delete it at destruction time. explicit IOBuffer(char* data);
diff --git a/net/quic/platform/impl/quic_mem_slice_impl.cc b/net/quic/platform/impl/quic_mem_slice_impl.cc index 0abf31a..99b42078 100644 --- a/net/quic/platform/impl/quic_mem_slice_impl.cc +++ b/net/quic/platform/impl/quic_mem_slice_impl.cc
@@ -8,11 +8,28 @@ namespace quic { +namespace { + +class QuicIOBuffer : public net::IOBuffer { + public: + QuicIOBuffer(QuicUniqueBufferPtr buffer, size_t size) + : buffer_(std::move(buffer)) { + AssertValidBufferSize(size); + data_ = buffer_.get(); + } + + private: + ~QuicIOBuffer() override { data_ = nullptr; } + + QuicUniqueBufferPtr buffer_; +}; + +} // namespace + QuicMemSliceImpl::QuicMemSliceImpl() = default; -QuicMemSliceImpl::QuicMemSliceImpl(QuicBufferAllocator* /*allocator*/, - size_t length) { - io_buffer_ = base::MakeRefCounted<net::IOBuffer>(length); +QuicMemSliceImpl::QuicMemSliceImpl(QuicUniqueBufferPtr buffer, size_t length) { + io_buffer_ = base::MakeRefCounted<QuicIOBuffer>(std::move(buffer), length); length_ = length; }
diff --git a/net/quic/platform/impl/quic_mem_slice_impl.h b/net/quic/platform/impl/quic_mem_slice_impl.h index 95cddf3a..bf550d4 100644 --- a/net/quic/platform/impl/quic_mem_slice_impl.h +++ b/net/quic/platform/impl/quic_mem_slice_impl.h
@@ -7,12 +7,11 @@ #include "base/memory/ref_counted.h" #include "net/base/io_buffer.h" +#include "net/third_party/quiche/src/quic/core/quic_buffer_allocator.h" #include "net/third_party/quiche/src/quic/platform/api/quic_export.h" namespace quic { -class QuicBufferAllocator; - // QuicMemSliceImpl TODO(fayang) class QUIC_EXPORT_PRIVATE QuicMemSliceImpl { public: @@ -20,7 +19,7 @@ QuicMemSliceImpl(); // Constructs a QuicMemSliceImp by let |allocator| allocate a data buffer of // |length|. - QuicMemSliceImpl(QuicBufferAllocator* allocator, size_t length); + QuicMemSliceImpl(QuicUniqueBufferPtr buffer, size_t length); QuicMemSliceImpl(scoped_refptr<net::IOBuffer> io_buffer, size_t length);
diff --git a/net/quic/quic_chromium_connection_helper.cc b/net/quic/quic_chromium_connection_helper.cc index 70f8fd2..b5d1208 100644 --- a/net/quic/quic_chromium_connection_helper.cc +++ b/net/quic/quic_chromium_connection_helper.cc
@@ -3,9 +3,17 @@ // found in the LICENSE file. #include "net/quic/quic_chromium_connection_helper.h" +#include "base/no_destructor.h" namespace net { +namespace { +quic::QuicBufferAllocator* GetBufferAllocator() { + static base::NoDestructor<quic::SimpleBufferAllocator> allocator; + return &*allocator; +} +} // namespace + QuicChromiumConnectionHelper::QuicChromiumConnectionHelper( const quic::QuicClock* clock, quic::QuicRandom* random_generator) @@ -23,7 +31,7 @@ quic::QuicBufferAllocator* QuicChromiumConnectionHelper::GetStreamSendBufferAllocator() { - return &buffer_allocator_; + return GetBufferAllocator(); } } // namespace net
diff --git a/net/quic/quic_chromium_connection_helper.h b/net/quic/quic_chromium_connection_helper.h index 2417ee0e..e3b4460 100644 --- a/net/quic/quic_chromium_connection_helper.h +++ b/net/quic/quic_chromium_connection_helper.h
@@ -39,7 +39,6 @@ private: const quic::QuicClock* clock_; quic::QuicRandom* random_generator_; - quic::SimpleBufferAllocator buffer_allocator_; DISALLOW_COPY_AND_ASSIGN(QuicChromiumConnectionHelper); };
diff --git a/net/quic/quic_flags_list.h b/net/quic/quic_flags_list.h index d050be8b..696fef0 100644 --- a/net/quic/quic_flags_list.h +++ b/net/quic/quic_flags_list.h
@@ -433,3 +433,9 @@ bool, FLAGS_quic_reloadable_flag_quic_create_server_handshaker_in_constructor, false) + +// If true, the frequency of stream frame coalescing will be logged as +// QuicSession.CoalesceStreamFrameStatus. +QUIC_FLAG(bool, + FLAGS_quic_reloadable_flag_quic_log_coalesce_stream_frame_frequency, + false)
diff --git a/services/device/hid/hid_service_linux.cc b/services/device/hid/hid_service_linux.cc index 61157bfe..74aca99 100644 --- a/services/device/hid/hid_service_linux.cc +++ b/services/device/hid/hid_service_linux.cc
@@ -222,19 +222,20 @@ } scoped_refptr<HidDeviceInfo> device_info = map_entry->second; - auto params = - std::make_unique<ConnectParams>(device_info, std::move(callback)); - #if defined(OS_CHROMEOS) - chromeos::PermissionBrokerClient::ErrorCallback error_callback = - base::BindOnce(&HidServiceLinux::OnPathOpenError, - params->device_info->device_node(), - std::move(params->callback)); + // Adapt |callback| to a repeating callback because the implementation below + // requires separate callbacks for success and error. Only one will be called. + auto copyable_callback = base::AdaptCallbackForRepeating(std::move(callback)); chromeos::PermissionBrokerClient::Get()->OpenPath( device_info->device_node(), - base::BindOnce(&HidServiceLinux::OnPathOpenComplete, std::move(params)), - std::move(error_callback)); + base::BindOnce( + &HidServiceLinux::OnPathOpenComplete, + std::make_unique<ConnectParams>(device_info, copyable_callback)), + base::BindOnce(&HidServiceLinux::OnPathOpenError, + device_info->device_node(), copyable_callback)); #else + auto params = + std::make_unique<ConnectParams>(device_info, std::move(callback)); scoped_refptr<base::SequencedTaskRunner> blocking_task_runner = params->blocking_task_runner; blocking_task_runner->PostTask(
diff --git a/testing/scripts/run_performance_tests.py b/testing/scripts/run_performance_tests.py index 77525216..bff4403c 100755 --- a/testing/scripts/run_performance_tests.py +++ b/testing/scripts/run_performance_tests.py
@@ -123,6 +123,7 @@ """ def __init__(self, isolated_out_dir, perf_test_name): + self.name = perf_test_name self.benchmark_path = os.path.join(isolated_out_dir, perf_test_name) def SetUp(self): @@ -161,8 +162,10 @@ class GtestCommandGenerator(object): - def __init__(self, options): + def __init__(self, options, override_executable=None, additional_flags=None): self._options = options + self._override_executable = override_executable + self._additional_flags = additional_flags or [] def generate(self, output_dir): """Generate the command to run to start the gtest perf test. @@ -178,20 +181,20 @@ self._get_passthrough_args() ) + @property + def executable_name(self): + """Gets the platform-independent name of the executable.""" + return self._override_executable or self._options.executable + def _get_executable(self): - executable = self._options.executable + executable = self.executable_name if IsWindows(): return r'.\%s.exe' % executable else: return './%s' % executable - @property - def executable_name(self): - """Gets the platform-independent name of the executable.""" - return self._options.executable - def _get_passthrough_args(self): - return self._options.passthrough_args + return self._options.passthrough_args + self._additional_flags def _generate_filter_args(self): if self._options.isolated_script_test_filter: @@ -214,22 +217,33 @@ if self._options.use_gtest_benchmark_script: output_args.append('--output-dir=' + output_dir) # These flags are to make sure that test output perf metrics in the log. - if not '--verbose' in self._options.passthrough_args: + if not '--verbose' in self._get_passthrough_args(): output_args.append('--verbose') if (not '--test-launcher-print-test-stdio=always' - in self._options.passthrough_args): + in self._get_passthrough_args()): output_args.append('--test-launcher-print-test-stdio=always') return output_args -def write_legacy_test_results(return_code, output_filepath): +def write_simple_test_results(return_code, output_filepath, benchmark_name): # TODO(crbug.com/920002): Fix to output # https://chromium.googlesource.com/chromium/src/+/master/docs/testing/json_test_results_format.md - valid = (return_code == 0) - failures = [] if valid else ['(entire test suite)'] + # for each test rather than this summary. output_json = { - 'valid': valid, - 'failures': failures, + 'tests': { + benchmark_name: { + 'expected': 'PASS', + 'actual': 'FAIL' if return_code else 'PASS', + }, + }, + 'interrupted': False, + 'path_delimiter': '/', + 'version': 3, + 'seconds_since_epoch': time.time(), + 'num_failures_by_type': { + 'FAIL': 1 if return_code else 0, + 'PASS': 0 if return_code else 1, + }, } with open(output_filepath, 'w') as fh: json.dump(output_json, fh) @@ -268,13 +282,14 @@ except Exception: traceback.print_exc() return_code = 1 - write_legacy_test_results(return_code, output_paths.test_results) if command_generator.executable_name in GTEST_CONVERSION_WHITELIST: with path_util.SysPath(path_util.GetTracingDir()): # pylint: disable=no-name-in-module from tracing.value import gtest_json_converter # pylint: enable=no-name-in-module gtest_json_converter.ConvertGtestJsonFile(output_paths.perf_results) + write_simple_test_results(return_code, output_paths.test_results, + output_paths.name) return return_code @@ -559,33 +574,53 @@ raise Exception( 'Sharded Telemetry perf tests must either specify --benchmarks ' 'list or have GTEST_SHARD_INDEX environment variable present.') - benchmarks_and_configs = shard_map[shard_index]['benchmarks'] - - for (benchmark, story_selection_config - ) in benchmarks_and_configs.iteritems(): - # Need to run the benchmark on both latest browser and reference build. - output_paths = OutputFilePaths(isolated_out_dir, benchmark).SetUp() - command_generator = TelemetryCommandGenerator( - benchmark, options, story_selection_config=story_selection_config) - print('\n### {folder} ###'.format(folder=benchmark)) - return_code = execute_telemetry_benchmark( - command_generator, output_paths, options.xvfb) - overall_return_code = return_code or overall_return_code - test_results_files.append(output_paths.test_results) - if options.run_ref_build: - reference_benchmark_foldername = benchmark + '.reference' - reference_output_paths = OutputFilePaths( - isolated_out_dir, reference_benchmark_foldername).SetUp() - reference_command_generator = TelemetryCommandGenerator( + shard_configuration = shard_map[shard_index] + assert ('benchmarks' in shard_configuration or + 'executables' in shard_configuration), ( + 'Every shard must have benchmarks or executables associated ' + 'with it.') + if 'benchmarks' in shard_configuration: + benchmarks_and_configs = shard_configuration['benchmarks'] + for (benchmark, story_selection_config + ) in benchmarks_and_configs.iteritems(): + # Need to run the benchmark on both latest browser and reference + # build. + output_paths = OutputFilePaths(isolated_out_dir, benchmark).SetUp() + command_generator = TelemetryCommandGenerator( benchmark, options, - story_selection_config=story_selection_config, is_reference=True) - print('\n### {folder} ###'.format( - folder=reference_benchmark_foldername)) - # We intentionally ignore the return code and test results of the - # reference build. - execute_telemetry_benchmark( - reference_command_generator, reference_output_paths, - options.xvfb) + story_selection_config=story_selection_config) + print('\n### {folder} ###'.format(folder=benchmark)) + return_code = execute_telemetry_benchmark( + command_generator, output_paths, options.xvfb) + overall_return_code = return_code or overall_return_code + test_results_files.append(output_paths.test_results) + if options.run_ref_build: + reference_benchmark_foldername = benchmark + '.reference' + reference_output_paths = OutputFilePaths( + isolated_out_dir, reference_benchmark_foldername).SetUp() + reference_command_generator = TelemetryCommandGenerator( + benchmark, options, + story_selection_config=story_selection_config, + is_reference=True) + print('\n### {folder} ###'.format( + folder=reference_benchmark_foldername)) + # We intentionally ignore the return code and test results of the + # reference build. + execute_telemetry_benchmark( + reference_command_generator, reference_output_paths, + options.xvfb) + if 'executables' in shard_configuration: + names_and_configs = shard_configuration['executables'] + for (name, configuration + ) in names_and_configs.iteritems(): + command_generator = GtestCommandGenerator( + options, override_executable=configuration['path'], + additional_flags=configuration['arguments']) + output_paths = OutputFilePaths(isolated_out_dir, name).SetUp() + print('\n### {folder} ###'.format(folder=name)) + overall_return_code = execute_gtest_perf_test( + command_generator, output_paths, options.xvfb) + test_results_files.append(output_paths.test_results) else: raise Exception('Telemetry tests must provide either a shard map or a ' '--benchmarks list so that we know which stories to run.')
diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc index 1e5d370..51fcd3f3 100644 --- a/third_party/blink/common/features.cc +++ b/third_party/blink/common/features.cc
@@ -396,10 +396,6 @@ const base::Feature kHtmlImportsRequestInitiatorLock{ "HtmlImportsRequestInitiatorLock", base::FEATURE_ENABLED_BY_DEFAULT}; -// When 'enabled', directly compositing images is turned off. -const base::Feature kDisableDirectlyCompositedImages{ - "DisableDirectlyCompositedImages", base::FEATURE_DISABLED_BY_DEFAULT}; - // Enables redirecting subresources in the page to better compressed and // optimized versions to provide data savings. const base::Feature kSubresourceRedirect{"SubresourceRedirect",
diff --git a/third_party/blink/public/common/features.h b/third_party/blink/public/common/features.h index c6a0a73..a8159c1 100644 --- a/third_party/blink/public/common/features.h +++ b/third_party/blink/public/common/features.h
@@ -127,7 +127,6 @@ BLINK_COMMON_EXPORT extern const base::Feature kARIAAnnotations; -BLINK_COMMON_EXPORT extern const base::Feature kDisableDirectlyCompositedImages; BLINK_COMMON_EXPORT extern const base::Feature kCompositeCrossOriginIframes; BLINK_COMMON_EXPORT extern const base::Feature kVizHitTestOcclusionCheck;
diff --git a/third_party/blink/public/platform/web_runtime_features.h b/third_party/blink/public/platform/web_runtime_features.h index f82bb2a5..c6141238d 100644 --- a/third_party/blink/public/platform/web_runtime_features.h +++ b/third_party/blink/public/platform/web_runtime_features.h
@@ -193,10 +193,8 @@ BLINK_PLATFORM_EXPORT static void EnableWebUsb(bool); BLINK_PLATFORM_EXPORT static void EnableWebXR(bool); BLINK_PLATFORM_EXPORT static void EnableWebXRARModule(bool); - BLINK_PLATFORM_EXPORT static void EnableWebXRARDOMOverlay(bool); - BLINK_PLATFORM_EXPORT static void EnableWebXRAnchors(bool); BLINK_PLATFORM_EXPORT static void EnableWebXRHitTest(bool); - BLINK_PLATFORM_EXPORT static void EnableWebXRPlaneDetection(bool); + BLINK_PLATFORM_EXPORT static void EnableWebXRIncubations(bool); BLINK_PLATFORM_EXPORT static void EnableXSLT(bool); BLINK_PLATFORM_EXPORT static void ForceOverlayFullscreenVideo(bool); BLINK_PLATFORM_EXPORT static void EnableTimerThrottlingForBackgroundTabs(
diff --git a/third_party/blink/renderer/bindings/scripts/bind_gen/code_node.py b/third_party/blink/renderer/bindings/scripts/bind_gen/code_node.py index 5dd315c..8b2b7a48 100644 --- a/third_party/blink/renderer/bindings/scripts/bind_gen/code_node.py +++ b/third_party/blink/renderer/bindings/scripts/bind_gen/code_node.py
@@ -432,25 +432,40 @@ except that addition and removal of None have no effect. """ - def __init__(self, code_nodes=None, separator="\n", separator_last=""): + def __init__(self, code_nodes=None, separator="\n", head="", tail=""): + """ + Args: + code_nodes: A list of CodeNode to be rendered. + separator: A str inserted between code nodes. + head: + tail: The head and tail sections that will be rendered iff the + content list is not empty. + """ assert isinstance(separator, str) - assert isinstance(separator_last, str) + assert isinstance(head, str) + assert isinstance(tail, str) element_nodes_gensym = CodeNode.gensym() element_nodes = [] template_text = format_template( """\ +% if {element_nodes}: +{head}\\ +% endif % for node in {element_nodes}: ${node}\\ % if not loop.last: {separator}\\ % endif % endfor -{separator_last}\ +% if {element_nodes}: +{tail}\\ +% endif\ """, element_nodes=element_nodes_gensym, separator=separator, - separator_last=separator_last) + head=head, + tail=tail) template_vars = {element_nodes_gensym: element_nodes} CodeNode.__init__( @@ -530,12 +545,13 @@ and provides the points where SymbolDefinitionNodes can be inserted. """ - def __init__(self, code_nodes=None, separator="\n", separator_last=""): + def __init__(self, code_nodes=None, separator="\n", head="", tail=""): ListNode.__init__( self, code_nodes=code_nodes, separator=separator, - separator_last=separator_last) + head=head, + tail=tail) def _render(self, renderer, last_render_state): duplicates = [] @@ -558,12 +574,13 @@ insert corresponding SymbolDefinitionNodes appropriately. """ - def __init__(self, code_nodes=None, separator="\n", separator_last=""): + def __init__(self, code_nodes=None, separator="\n", head="", tail=""): SequenceNode.__init__( self, code_nodes=code_nodes, separator=separator, - separator_last=separator_last) + head=head, + tail=tail) self._likeliness = Likeliness.ALWAYS self._registered_code_symbols = set()
diff --git a/third_party/blink/renderer/bindings/scripts/bind_gen/code_node_cxx.py b/third_party/blink/renderer/bindings/scripts/bind_gen/code_node_cxx.py index 08f30a1..e911960 100644 --- a/third_party/blink/renderer/bindings/scripts/bind_gen/code_node_cxx.py +++ b/third_party/blink/renderer/bindings/scripts/bind_gen/code_node_cxx.py
@@ -152,7 +152,7 @@ delete=False): """ Args: - name: Function name node, which may include nested-name-specifier + name: Function name, which may include nested-name-specifier (i.e. 'namespace_name::' and/or 'class_name::'). arg_decls: List of argument declarations. return_type: Return type. @@ -185,10 +185,10 @@ CompositeNode.__init__( self, template_format, - name=name, + name=_to_maybe_text_node(name), arg_decls=ListNode( - _to_node_list(arg_decls, TextNode), separator=", "), - return_type=return_type, + map(_to_maybe_text_node, arg_decls), separator=", "), + return_type=_to_maybe_text_node(return_type), const=const, override=override, default_or_delete=default_or_delete) @@ -204,7 +204,7 @@ member_initializer_list=None): """ Args: - name: Function name node, which may include nested-name-specifier + name: Function name, which may include nested-name-specifier (i.e. 'namespace_name::' and/or 'class_name::'). arg_decls: List of argument declarations. return_type: Return type. @@ -228,21 +228,20 @@ if member_initializer_list is None: member_initializer_list = "" else: - initializers = ListNode( - _to_node_list(member_initializer_list, TextNode), - separator=", ") - member_initializer_list = ListNode([TextNode(" : "), initializers], - separator="") + member_initializer_list = ListNode( + map(_to_maybe_text_node, member_initializer_list), + separator=", ", + head=" : ") self._body_node = SymbolScopeNode() CompositeNode.__init__( self, template_format, - name=name, + name=_to_maybe_text_node(name), arg_decls=ListNode( - _to_node_list(arg_decls, TextNode), separator=", "), - return_type=return_type, + map(_to_maybe_text_node, arg_decls), separator=", "), + return_type=_to_maybe_text_node(return_type), const=const, override=override, member_initializer_list=member_initializer_list, @@ -253,20 +252,117 @@ return self._body_node +class CxxClassDefNode(CompositeNode): + def __init__(self, name, base_class_names=None, final=False): + """ + Args: + name: The class name to be defined. + base_class_names: The list of base class names. + final: True makes this a final class. + """ + assert isinstance(final, bool) + + template_format = ("class {name}{final}{base_clause} {{\n" + " {top_section}\n" + " {public_section}\n" + " {protected_section}\n" + " {private_section}\n" + "}};") + + final = " final" if final else "" + + if base_class_names is None: + base_clause = "" + else: + base_specifier_list = [ + CompositeNode( + "public {base_class_name}", + base_class_name=_to_maybe_text_node(base_class_name)) + for base_class_name in base_class_names + ] + base_clause = ListNode( + base_specifier_list, separator=", ", head=" : ") + + self._top_section = ListNode(tail="\n") + self._public_section = ListNode(head="public:\n", tail="\n") + self._protected_section = ListNode(head="protected:\n", tail="\n") + self._private_section = ListNode(head="private:\n", tail="\n") + + CompositeNode.__init__( + self, + template_format, + name=_to_maybe_text_node(name), + final=final, + base_clause=base_clause, + top_section=self._top_section, + public_section=self._public_section, + protected_section=self._protected_section, + private_section=self._private_section) + + @property + def top_section(self): + return self._top_section + + @property + def public_section(self): + return self._public_section + + @property + def protected_section(self): + return self._protected_section + + @property + def private_section(self): + return self._private_section + + +class CxxNamespaceNode(CompositeNode): + def __init__(self, name="", body=None): + template_format = ("namespace {name} {{\n" + "\n" + "{body}\n" + "\n" + "}} // namespace {name}") + + if body is None: + self._body = ListNode() + else: + self._body = _to_list_node(body) + + CompositeNode.__init__( + self, template_format, name=name, body=self._body) + + @property + def body(self): + return self._body + + def _to_conditional_node(cond): if isinstance(cond, CodeNode): return cond - elif isinstance(cond, CodeGenExpr): + if isinstance(cond, CodeGenExpr): return TextNode(cond.to_text()) - elif isinstance(cond, str): + if isinstance(cond, str): return TextNode(cond) - else: - assert False + assert False -def _to_node_list(iterable, constructor): - return map(lambda x: x if isinstance(x, CodeNode) else constructor(x), - iterable) +def _to_list_node(node): + if isinstance(node, ListNode): + return node + if isinstance(node, CodeNode): + return ListNode([node]) + if isinstance(node, (list, tuple)): + return ListNode(node) + assert False + + +def _to_maybe_text_node(node): + if isinstance(node, CodeNode): + return node + if isinstance(node, str): + return TextNode(node) + assert False def _to_symbol_scope_node(node, likeliness):
diff --git a/third_party/blink/renderer/bindings/scripts/bind_gen/code_node_cxx_test.py b/third_party/blink/renderer/bindings/scripts/bind_gen/code_node_cxx_test.py index e7dd51a..1210b58 100644 --- a/third_party/blink/renderer/bindings/scripts/bind_gen/code_node_cxx_test.py +++ b/third_party/blink/renderer/bindings/scripts/bind_gen/code_node_cxx_test.py
@@ -7,6 +7,7 @@ from .code_node import SymbolNode from .code_node import SymbolScopeNode from .code_node import TextNode +from .code_node_cxx import CxxClassDefNode from .code_node_cxx import CxxFuncDefNode from .code_node_cxx import CxxLikelyIfNode from .code_node_cxx import CxxUnlikelyIfNode @@ -33,7 +34,7 @@ self.assertEqual(actual, expected) def test_symbol_definition_with_branches(self): - root = SymbolScopeNode(separator_last="\n") + root = SymbolScopeNode() root.register_code_symbols([ SymbolNode("var1", "int ${var1} = 1;"), @@ -75,11 +76,11 @@ int var6 = 6; return var6; } -var3; +var3;\ """) def test_symbol_definition_with_nested_branches(self): - root = SymbolScopeNode(separator_last="\n") + root = SymbolScopeNode() root.register_code_symbols([ SymbolNode("var1", "int ${var1} = 1;"), @@ -128,26 +129,21 @@ return var2; } return; -} +}\ """) def test_function_definition_minimum(self): - root = SymbolScopeNode(separator_last="\n") - root.append( - CxxFuncDefNode( - name="blink::bindings::func", arg_decls=[], - return_type="void")) + root = CxxFuncDefNode( + name="blink::bindings::func", arg_decls=[], return_type="void") self.assertRenderResult(root, """\ void blink::bindings::func() { -} +}\ """) def test_function_definition_full(self): - root = SymbolScopeNode(separator_last="\n") - - func_def = CxxFuncDefNode( + root = CxxFuncDefNode( name="blink::bindings::func", arg_decls=["int arg1", "int arg2"], return_type="void", @@ -158,19 +154,17 @@ "member2(\"str\")", ]) - func_def.body.register_code_symbols([ + root.body.register_code_symbols([ SymbolNode("var1", "int ${var1} = 1;"), SymbolNode("var2", "int ${var2} = 2;"), ]) - func_def.body.extend([ + root.body.extend([ CxxUnlikelyIfNode( cond=TextNode("${var1}"), body=[TextNode("return ${var1};")]), TextNode("return ${var2};"), ]) - root.append(func_def) - self.assertRenderResult( root, """\ void blink::bindings::func(int arg1, int arg2) const override\ @@ -181,5 +175,33 @@ } int var2 = 2; return var2; -} +}\ +""") + + def test_class_definition(self): + root = CxxClassDefNode("X", ["A", "B"], final=True) + + root.public_section.extend([ + TextNode("void m1();"), + TextNode("void m2();"), + ]) + root.private_section.extend([ + TextNode("int m1_;"), + TextNode("int m2_;"), + ]) + + self.assertRenderResult( + root, """\ +class X final : public A, public B { + + public: + void m1(); + void m2(); + + + private: + int m1_; + int m2_; + +};\ """)
diff --git a/third_party/blink/renderer/bindings/scripts/bind_gen/code_node_test.py b/third_party/blink/renderer/bindings/scripts/bind_gen/code_node_test.py index bee9252..a5ea6bb 100644 --- a/third_party/blink/renderer/bindings/scripts/bind_gen/code_node_test.py +++ b/third_party/blink/renderer/bindings/scripts/bind_gen/code_node_test.py
@@ -72,6 +72,14 @@ root.remove(root[-1]) self.assertRenderResult(root, "2,3,5") + def test_list_node_head_and_tail(self): + self.assertRenderResult(ListNode(), "") + self.assertRenderResult(ListNode(head="head"), "") + self.assertRenderResult(ListNode(tail="tail"), "") + self.assertRenderResult( + ListNode([TextNode("-content-")], head="head", tail="tail"), + "head-content-tail") + def test_nested_sequence(self): """Tests nested ListNodes.""" root = ListNode(separator=",") @@ -93,7 +101,7 @@ Tests that use of SymbolNode inserts necessary SymbolDefinitionNode appropriately. """ - root = SymbolScopeNode(separator_last="\n") + root = SymbolScopeNode(tail="\n") root.register_code_symbols([ SymbolNode("var1", "int ${var1} = ${var2} + ${var3};"),
diff --git a/third_party/blink/renderer/bindings/scripts/bind_gen/dictionary.py b/third_party/blink/renderer/bindings/scripts/bind_gen/dictionary.py index c52af687..fc13087b 100644 --- a/third_party/blink/renderer/bindings/scripts/bind_gen/dictionary.py +++ b/third_party/blink/renderer/bindings/scripts/bind_gen/dictionary.py
@@ -637,7 +637,7 @@ make_dict_member_set_def(cg_context.make_copy(dict_member=member)), ]) - root_node = SymbolScopeNode(separator_last="\n") + root_node = ListNode(tail="\n") root_node.set_accumulator(CodeGenAccumulator()) root_node.set_renderer(MakoRenderer()) @@ -681,7 +681,7 @@ make_dict_class_def(cg_context), ]) - root_node = SymbolScopeNode(separator_last="\n") + root_node = ListNode(tail="\n") root_node.set_accumulator(CodeGenAccumulator()) root_node.set_renderer(MakoRenderer())
diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink/renderer/core/dom/document.cc index bee6053..91b3120 100644 --- a/third_party/blink/renderer/core/dom/document.cc +++ b/third_party/blink/renderer/core/dom/document.cc
@@ -3260,7 +3260,7 @@ return; if (val != is_immersive_ar_overlay_) { - DCHECK(RuntimeEnabledFeatures::WebXRARDOMOverlayEnabled(this)); + DCHECK(RuntimeEnabledFeatures::WebXRIncubationsEnabled(this)); is_immersive_ar_overlay_ = val; // If the property has changed, apply the pseudo-style change to the root
diff --git a/third_party/blink/renderer/core/layout/layout_object.cc b/third_party/blink/renderer/core/layout/layout_object.cc index f7679fc7..3b6cac6 100644 --- a/third_party/blink/renderer/core/layout/layout_object.cc +++ b/third_party/blink/renderer/core/layout/layout_object.cc
@@ -2060,14 +2060,9 @@ container->SetNeedsOverflowRecalc(); } - if (diff.NeedsRecomputeOverflow() && !NeedsLayout()) { - // TODO(rhogan): Make inlines capable of recomputing overflow too. - if (IsLayoutBlock()) { - SetNeedsOverflowRecalc(); - } else { - SetNeedsLayoutAndPrefWidthsRecalc( - layout_invalidation_reason::kStyleChange); - } + if (diff.NeedsRecomputeVisualOverflow()) { + PaintingLayer()->SetNeedsVisualOverflowRecalc(); + SetShouldCheckForPaintInvalidation(); } if (diff.NeedsPaintInvalidationSubtree() ||
diff --git a/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.cc b/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.cc index b99cf22..7a3652c 100644 --- a/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.cc +++ b/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.cc
@@ -28,7 +28,6 @@ #include <memory> #include "cc/layers/picture_layer.h" -#include "third_party/blink/public/common/features.h" #include "third_party/blink/renderer/core/accessibility/apply_dark_mode.h" #include "third_party/blink/renderer/core/display_lock/display_lock_utilities.h" #include "third_party/blink/renderer/core/dom/dom_node_ids.h" @@ -1576,9 +1575,6 @@ bool CompositedLayerMapping::IsDirectlyCompositedImage() const { DCHECK(GetLayoutObject().IsImage()); - if (base::FeatureList::IsEnabled(features::kDisableDirectlyCompositedImages)) - return false; - LayoutImage& image_layout_object = ToLayoutImage(GetLayoutObject()); if (owning_layer_.HasBoxDecorationsOrBackground() ||
diff --git a/third_party/blink/renderer/core/style/computed_style.cc b/third_party/blink/renderer/core/style/computed_style.cc index b20a297..9b7525f 100644 --- a/third_party/blink/renderer/core/style/computed_style.cc +++ b/third_party/blink/renderer/core/style/computed_style.cc
@@ -903,8 +903,9 @@ diff.SetFilterChanged(); if (ComputedStyleBase:: - UpdatePropertySpecificDifferencesNeedsRecomputeOverflow(*this, other)) - diff.SetNeedsRecomputeOverflow(); + UpdatePropertySpecificDifferencesNeedsRecomputeVisualOverflow(*this, + other)) + diff.SetNeedsRecomputeVisualOverflow(); if (ComputedStyleBase::UpdatePropertySpecificDifferencesBackdropFilter(*this, other))
diff --git a/third_party/blink/renderer/core/style/computed_style_diff_functions.json5 b/third_party/blink/renderer/core/style/computed_style_diff_functions.json5 index eb09609..21c836e 100644 --- a/third_party/blink/renderer/core/style/computed_style_diff_functions.json5 +++ b/third_party/blink/renderer/core/style/computed_style_diff_functions.json5
@@ -388,7 +388,7 @@ fields_to_diff: ["Mask", "MaskBoxImage"], }, { - name: "UpdatePropertySpecificDifferencesNeedsRecomputeOverflow", + name: "UpdatePropertySpecificDifferencesNeedsRecomputeVisualOverflow", predicates_to_test: [ { predicate: "a.BoxShadowDataEquivalent(b)",
diff --git a/third_party/blink/renderer/core/style/style_difference.cc b/third_party/blink/renderer/core/style/style_difference.cc index 49ef5c4..92a12377 100644 --- a/third_party/blink/renderer/core/style/style_difference.cc +++ b/third_party/blink/renderer/core/style/style_difference.cc
@@ -43,7 +43,7 @@ break; } - out << ", recomputeOverflow=" << diff.recompute_overflow_; + out << ", recomputeVisualOverflow=" << diff.recompute_visual_overflow_; out << ", visualRectUpdate=" << diff.visual_rect_update_; out << ", propertySpecificDifferences=";
diff --git a/third_party/blink/renderer/core/style/style_difference.h b/third_party/blink/renderer/core/style/style_difference.h index 517fbb8..437fad93 100644 --- a/third_party/blink/renderer/core/style/style_difference.h +++ b/third_party/blink/renderer/core/style/style_difference.h
@@ -40,7 +40,7 @@ layout_type_(kNoLayout), needs_collect_inlines_(false), needs_reshape_(false), - recompute_overflow_(false), + recompute_visual_overflow_(false), visual_rect_update_(false), property_specific_differences_(0), scroll_anchor_disabling_property_changed_(false), @@ -52,7 +52,7 @@ layout_type_ = std::max(layout_type_, other.layout_type_); needs_collect_inlines_ |= other.needs_collect_inlines_; needs_reshape_ |= other.needs_reshape_; - recompute_overflow_ |= other.recompute_overflow_; + recompute_visual_overflow_ |= other.recompute_visual_overflow_; visual_rect_update_ |= other.visual_rect_update_; property_specific_differences_ |= other.property_specific_differences_; scroll_anchor_disabling_property_changed_ |= @@ -63,7 +63,7 @@ bool HasDifference() const { return paint_invalidation_type_ || layout_type_ || needs_collect_inlines_ || needs_reshape_ || property_specific_differences_ || - recompute_overflow_ || visual_rect_update_ || + recompute_visual_overflow_ || visual_rect_update_ || scroll_anchor_disabling_property_changed_ || compositing_reasons_changed_; } @@ -116,8 +116,10 @@ bool NeedsReshape() const { return needs_reshape_; } void SetNeedsReshape() { needs_reshape_ = true; } - bool NeedsRecomputeOverflow() const { return recompute_overflow_; } - void SetNeedsRecomputeOverflow() { recompute_overflow_ = true; } + bool NeedsRecomputeVisualOverflow() const { + return recompute_visual_overflow_; + } + void SetNeedsRecomputeVisualOverflow() { recompute_visual_overflow_ = true; } bool NeedsVisualRectUpdate() const { return visual_rect_update_; } void SetNeedsVisualRectUpdate() { visual_rect_update_ = true; } @@ -214,7 +216,7 @@ unsigned layout_type_ : 2; unsigned needs_collect_inlines_ : 1; unsigned needs_reshape_ : 1; - unsigned recompute_overflow_ : 1; + unsigned recompute_visual_overflow_ : 1; unsigned visual_rect_update_ : 1; unsigned property_specific_differences_ : kPropertyDifferenceCount; unsigned scroll_anchor_disabling_property_changed_ : 1;
diff --git a/third_party/blink/renderer/core/style/style_difference_test.cc b/third_party/blink/renderer/core/style/style_difference_test.cc index f45ae9b..9cffd2f 100644 --- a/third_party/blink/renderer/core/style/style_difference_test.cc +++ b/third_party/blink/renderer/core/style/style_difference_test.cc
@@ -16,7 +16,7 @@ EXPECT_EQ( "StyleDifference{layoutType=NoLayout, " "collectInlines=0, reshape=0, " - "paintInvalidationType=NoPaintInvalidation, recomputeOverflow=0, " + "paintInvalidationType=NoPaintInvalidation, recomputeVisualOverflow=0, " "visualRectUpdate=0, propertySpecificDifferences=, " "scrollAnchorDisablingPropertyChanged=0}", string_stream.str()); @@ -29,7 +29,7 @@ diff.SetNeedsPositionedMovementLayout(); diff.SetNeedsReshape(); diff.SetNeedsCollectInlines(); - diff.SetNeedsRecomputeOverflow(); + diff.SetNeedsRecomputeVisualOverflow(); diff.SetNeedsVisualRectUpdate(); diff.SetTransformChanged(); diff.SetScrollAnchorDisablingPropertyChanged(); @@ -37,8 +37,9 @@ EXPECT_EQ( "StyleDifference{layoutType=PositionedMovement, " "collectInlines=1, reshape=1, " - "paintInvalidationType=PaintInvalidationObject, recomputeOverflow=1, " - "visualRectUpdate=1, propertySpecificDifferences=TransformChanged, " + "paintInvalidationType=PaintInvalidationObject, " + "recomputeVisualOverflow=1, visualRectUpdate=1, " + "propertySpecificDifferences=TransformChanged, " "scrollAnchorDisablingPropertyChanged=1}", string_stream.str()); } @@ -58,7 +59,7 @@ EXPECT_EQ( "StyleDifference{layoutType=NoLayout, " "collectInlines=0, reshape=0, " - "paintInvalidationType=NoPaintInvalidation, recomputeOverflow=0, " + "paintInvalidationType=NoPaintInvalidation, recomputeVisualOverflow=0, " "visualRectUpdate=0, " "propertySpecificDifferences=TransformChanged|OpacityChanged|" "ZIndexChanged|FilterChanged|BackdropFilterChanged|CSSClipChanged|"
diff --git a/third_party/blink/renderer/modules/remote_objects/remote_object.cc b/third_party/blink/renderer/modules/remote_objects/remote_object.cc index 95674b2..2cffcbd 100644 --- a/third_party/blink/renderer/modules/remote_objects/remote_object.cc +++ b/third_party/blink/renderer/modules/remote_objects/remote_object.cc
@@ -31,8 +31,16 @@ std::vector<std::string> RemoteObject::EnumerateNamedProperties( v8::Isolate* isolate) { - // TODO(crbug.com/794320): implement this. - return std::vector<std::string>(); + if (!object_.is_bound()) { + gateway_->BindRemoteObjectReceiver(object_id_, + object_.BindNewPipeAndPassReceiver()); + } + WTF::Vector<WTF::String> methods; + object_->GetMethods(&methods); + std::vector<std::string> result; + for (const auto& method : methods) + result.push_back(method.Utf8()); + return result; } } // namespace blink
diff --git a/third_party/blink/renderer/modules/remote_objects/remote_object.h b/third_party/blink/renderer/modules/remote_objects/remote_object.h index e48b712f..c9636d4b 100644 --- a/third_party/blink/renderer/modules/remote_objects/remote_object.h +++ b/third_party/blink/renderer/modules/remote_objects/remote_object.h
@@ -39,6 +39,7 @@ private: WeakPersistent<RemoteObjectGatewayImpl> gateway_{nullptr}; + mojo::Remote<mojom::blink::RemoteObject> object_; int32_t object_id_; };
diff --git a/third_party/blink/renderer/modules/remote_objects/remote_object_gateway_impl.cc b/third_party/blink/renderer/modules/remote_objects/remote_object_gateway_impl.cc index bc9acdc0..6d308bec 100644 --- a/third_party/blink/renderer/modules/remote_objects/remote_object_gateway_impl.cc +++ b/third_party/blink/renderer/modules/remote_objects/remote_object_gateway_impl.cc
@@ -9,6 +9,8 @@ #include "third_party/blink/renderer/platform/bindings/v8_binding.h" #include "third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h" +#undef GetObject + namespace blink { // static @@ -94,6 +96,12 @@ named_objects_.erase(iter); } +void RemoteObjectGatewayImpl::BindRemoteObjectReceiver( + int32_t object_id, + mojo::PendingReceiver<mojom::blink::RemoteObject> receiver) { + object_host_->GetObject(object_id, std::move(receiver)); +} + // static void RemoteObjectGatewayFactoryImpl::Create( LocalFrame* frame,
diff --git a/third_party/blink/renderer/modules/remote_objects/remote_object_gateway_impl.h b/third_party/blink/renderer/modules/remote_objects/remote_object_gateway_impl.h index 6797675..32097c5 100644 --- a/third_party/blink/renderer/modules/remote_objects/remote_object_gateway_impl.h +++ b/third_party/blink/renderer/modules/remote_objects/remote_object_gateway_impl.h
@@ -54,6 +54,10 @@ Supplement<LocalFrame>::Trace(visitor); } + void BindRemoteObjectReceiver( + int32_t object_id, + mojo::PendingReceiver<mojom::blink::RemoteObject>); + private: // mojom::blink::RemoteObjectGateway void AddNamedObject(const WTF::String& name, int32_t id) override;
diff --git a/third_party/blink/renderer/modules/xr/xr.cc b/third_party/blink/renderer/modules/xr/xr.cc index 8cef770..478d187 100644 --- a/third_party/blink/renderer/modules/xr/xr.cc +++ b/third_party/blink/renderer/modules/xr/xr.cc
@@ -117,7 +117,7 @@ return device::mojom::XRSessionFeature::REF_SPACE_BOUNDED_FLOOR; } else if (feature_string == "unbounded") { return device::mojom::XRSessionFeature::REF_SPACE_UNBOUNDED; - } else if (RuntimeEnabledFeatures::WebXRARDOMOverlayEnabled(doc) && + } else if (RuntimeEnabledFeatures::WebXRIncubationsEnabled(doc) && feature_string == "dom-overlay-for-handheld-ar") { return device::mojom::XRSessionFeature::DOM_OVERLAY_FOR_HANDHELD_AR; }
diff --git a/third_party/blink/renderer/modules/xr/xr_anchor.idl b/third_party/blink/renderer/modules/xr/xr_anchor.idl index 337c56e..2728ce5 100644 --- a/third_party/blink/renderer/modules/xr/xr_anchor.idl +++ b/third_party/blink/renderer/modules/xr/xr_anchor.idl
@@ -5,7 +5,7 @@ [ SecureContext, Exposed=Window, - RuntimeEnabled=WebXRAnchors + RuntimeEnabled=WebXRIncubations ] interface XRAnchor { readonly attribute XRSpace? anchorSpace;
diff --git a/third_party/blink/renderer/modules/xr/xr_anchor_set.idl b/third_party/blink/renderer/modules/xr/xr_anchor_set.idl index aee2cb2..ddb69dd 100644 --- a/third_party/blink/renderer/modules/xr/xr_anchor_set.idl +++ b/third_party/blink/renderer/modules/xr/xr_anchor_set.idl
@@ -5,7 +5,7 @@ [ SecureContext, Exposed=Window, - RuntimeEnabled=WebXRAnchors + RuntimeEnabled=WebXRIncubations ] interface XRAnchorSet { readonly setlike<XRAnchor>;
diff --git a/third_party/blink/renderer/modules/xr/xr_frame.idl b/third_party/blink/renderer/modules/xr/xr_frame.idl index 4c0cdfa6..e76a5b4f 100644 --- a/third_party/blink/renderer/modules/xr/xr_frame.idl +++ b/third_party/blink/renderer/modules/xr/xr_frame.idl
@@ -12,9 +12,9 @@ // More details about the real-world understanding APIs can be found here: // https://github.com/immersive-web/real-world-geometry/blob/master/plane-detection-explainer.md - [RuntimeEnabled=WebXRPlaneDetection] readonly attribute XRWorldInformation worldInformation; + [RuntimeEnabled=WebXRIncubations] readonly attribute XRWorldInformation worldInformation; - [RuntimeEnabled=WebXRAnchors] readonly attribute XRAnchorSet trackedAnchors; + [RuntimeEnabled=WebXRIncubations] readonly attribute XRAnchorSet trackedAnchors; [RaisesException] XRViewerPose? getViewerPose(XRReferenceSpace referenceSpace); [RaisesException] XRPose? getPose(XRSpace space, XRSpace relativeTo);
diff --git a/third_party/blink/renderer/modules/xr/xr_plane.idl b/third_party/blink/renderer/modules/xr/xr_plane.idl index 2c2f6820..e448c0793b 100644 --- a/third_party/blink/renderer/modules/xr/xr_plane.idl +++ b/third_party/blink/renderer/modules/xr/xr_plane.idl
@@ -12,7 +12,7 @@ [ SecureContext, Exposed=Window, - RuntimeEnabled=WebXRPlaneDetection + RuntimeEnabled=WebXRIncubations ] interface XRPlane { readonly attribute XRSpace planeSpace; @@ -20,5 +20,5 @@ readonly attribute XRPlaneOrientation? orientation; readonly attribute DOMHighResTimeStamp lastChangedTime; - [RuntimeEnabled=WebXRAnchors, CallWith=ScriptState, RaisesException] Promise<XRAnchor> createAnchor(XRRigidTransform initial_pose, XRSpace space); + [CallWith=ScriptState, RaisesException] Promise<XRAnchor> createAnchor(XRRigidTransform initial_pose, XRSpace space); };
diff --git a/third_party/blink/renderer/modules/xr/xr_plane_detection_state.idl b/third_party/blink/renderer/modules/xr/xr_plane_detection_state.idl index 94573244..8b41426a 100644 --- a/third_party/blink/renderer/modules/xr/xr_plane_detection_state.idl +++ b/third_party/blink/renderer/modules/xr/xr_plane_detection_state.idl
@@ -7,7 +7,7 @@ [ SecureContext, Exposed=Window, - RuntimeEnabled=WebXRPlaneDetection + RuntimeEnabled=WebXRIncubations ] interface XRPlaneDetectionState { readonly attribute boolean enabled;
diff --git a/third_party/blink/renderer/modules/xr/xr_plane_set.idl b/third_party/blink/renderer/modules/xr/xr_plane_set.idl index 8e04e6bd..f0d3a0d4 100644 --- a/third_party/blink/renderer/modules/xr/xr_plane_set.idl +++ b/third_party/blink/renderer/modules/xr/xr_plane_set.idl
@@ -7,7 +7,7 @@ [ SecureContext, Exposed=Window, - RuntimeEnabled=WebXRPlaneDetection + RuntimeEnabled=WebXRIncubations ] interface XRPlaneSet { readonly setlike<XRPlane>;
diff --git a/third_party/blink/renderer/modules/xr/xr_session.idl b/third_party/blink/renderer/modules/xr/xr_session.idl index cb85a643d..4638ba0 100644 --- a/third_party/blink/renderer/modules/xr/xr_session.idl +++ b/third_party/blink/renderer/modules/xr/xr_session.idl
@@ -50,11 +50,11 @@ [RuntimeEnabled=WebXRHitTest, CallWith=ScriptState, RaisesException] Promise<FrozenArray<XRHitResult>> requestHitTest(XRRay ray, XRSpace space); // https://github.com/immersive-web/real-world-geometry/blob/master/plane-detection-explainer.md - [RuntimeEnabled=WebXRPlaneDetection] readonly attribute XRWorldTrackingState worldTrackingState; - [RuntimeEnabled=WebXRPlaneDetection, RaisesException] void updateWorldTrackingState(optional XRWorldTrackingStateInit state); + [RuntimeEnabled=WebXRIncubations] readonly attribute XRWorldTrackingState worldTrackingState; + [RuntimeEnabled=WebXRIncubations, RaisesException] void updateWorldTrackingState(optional XRWorldTrackingStateInit state); - [RuntimeEnabled=WebXRAnchors] readonly attribute XRAnchorSet trackedAnchors; - [RuntimeEnabled=WebXRAnchors, CallWith=ScriptState, RaisesException] Promise<XRAnchor> createAnchor(XRRigidTransform initial_pose, XRSpace space); + [RuntimeEnabled=WebXRIncubations] readonly attribute XRAnchorSet trackedAnchors; + [RuntimeEnabled=WebXRIncubations, CallWith=ScriptState, RaisesException] Promise<XRAnchor> createAnchor(XRRigidTransform initial_pose, XRSpace space); [CallWith=ScriptState, Measure, RaisesException] Promise<void> end();
diff --git a/third_party/blink/renderer/modules/xr/xr_world_information.idl b/third_party/blink/renderer/modules/xr/xr_world_information.idl index 7aa6950..b60addc 100644 --- a/third_party/blink/renderer/modules/xr/xr_world_information.idl +++ b/third_party/blink/renderer/modules/xr/xr_world_information.idl
@@ -7,7 +7,7 @@ [ SecureContext, Exposed=Window, - RuntimeEnabled=WebXRPlaneDetection + RuntimeEnabled=WebXRIncubations ] interface XRWorldInformation { readonly attribute XRPlaneSet? detectedPlanes;
diff --git a/third_party/blink/renderer/modules/xr/xr_world_tracking_state.idl b/third_party/blink/renderer/modules/xr/xr_world_tracking_state.idl index 070ee06..ee714c3 100644 --- a/third_party/blink/renderer/modules/xr/xr_world_tracking_state.idl +++ b/third_party/blink/renderer/modules/xr/xr_world_tracking_state.idl
@@ -7,7 +7,7 @@ [ SecureContext, Exposed=Window, - RuntimeEnabled=WebXRPlaneDetection + RuntimeEnabled=WebXRIncubations ] interface XRWorldTrackingState { readonly attribute XRPlaneDetectionState planeDetectionState;
diff --git a/third_party/blink/renderer/platform/exported/web_runtime_features.cc b/third_party/blink/renderer/platform/exported/web_runtime_features.cc index 5821aa7..57a9102 100644 --- a/third_party/blink/renderer/platform/exported/web_runtime_features.cc +++ b/third_party/blink/renderer/platform/exported/web_runtime_features.cc
@@ -476,20 +476,12 @@ RuntimeEnabledFeatures::SetWebXRARModuleEnabled(enable); } -void WebRuntimeFeatures::EnableWebXRARDOMOverlay(bool enable) { - RuntimeEnabledFeatures::SetWebXRARDOMOverlayEnabled(enable); -} - -void WebRuntimeFeatures::EnableWebXRAnchors(bool enable) { - RuntimeEnabledFeatures::SetWebXRAnchorsEnabled(enable); -} - void WebRuntimeFeatures::EnableWebXRHitTest(bool enable) { RuntimeEnabledFeatures::SetWebXRHitTestEnabled(enable); } -void WebRuntimeFeatures::EnableWebXRPlaneDetection(bool enable) { - RuntimeEnabledFeatures::SetWebXRPlaneDetectionEnabled(enable); +void WebRuntimeFeatures::EnableWebXRIncubations(bool enable) { + RuntimeEnabledFeatures::SetWebXRIncubationsEnabled(enable); } void WebRuntimeFeatures::EnablePresentationAPI(bool enable) {
diff --git a/third_party/blink/renderer/platform/heap/heap_stats_collector.cc b/third_party/blink/renderer/platform/heap/heap_stats_collector.cc index 6b8dc5c..da31a21d 100644 --- a/third_party/blink/renderer/platform/heap/heap_stats_collector.cc +++ b/third_party/blink/renderer/platform/heap/heap_stats_collector.cc
@@ -170,6 +170,10 @@ return base::TimeDelta::FromSecondsD(estimated_marking_time_in_seconds()); } +base::TimeDelta ThreadHeapStatsCollector::Event::roots_marking_time() const { + return scope_data[kVisitRoots]; +} + base::TimeDelta ThreadHeapStatsCollector::Event::incremental_marking_time() const { return scope_data[kIncrementalMarkingStartMarking] +
diff --git a/third_party/blink/renderer/platform/heap/heap_stats_collector.h b/third_party/blink/renderer/platform/heap/heap_stats_collector.h index e5e7207f..4e8a2bd 100644 --- a/third_party/blink/renderer/platform/heap/heap_stats_collector.h +++ b/third_party/blink/renderer/platform/heap/heap_stats_collector.h
@@ -63,6 +63,7 @@ V(VisitDOMWrappers) \ V(VisitPersistentRoots) \ V(VisitPersistents) \ + V(VisitRoots) \ V(VisitStackRoots) #define FOR_ALL_CONCURRENT_SCOPES(V) \ @@ -250,6 +251,9 @@ // Time spent in the final atomic pause in sweeping and compacting the heap. base::TimeDelta atomic_sweep_and_compact_time() const; + // Time spent marking the roots. + base::TimeDelta roots_marking_time() const; + // Time spent incrementally marking the heap. base::TimeDelta incremental_marking_time() const;
diff --git a/third_party/blink/renderer/platform/heap/thread_state.cc b/third_party/blink/renderer/platform/heap/thread_state.cc index 9afaaa7..4d1078c9 100644 --- a/third_party/blink/renderer/platform/heap/thread_state.cc +++ b/third_party/blink/renderer/platform/heap/thread_state.cc
@@ -888,6 +888,8 @@ UMA_HISTOGRAM_TIMES("BlinkGC.TimeForAtomicPhaseMarking", event.atomic_marking_time()); UMA_HISTOGRAM_TIMES("BlinkGC.TimeForGCCycle", event.gc_cycle_time()); + UMA_HISTOGRAM_TIMES("BlinkGC.TimeForMarkingRoots", + event.roots_marking_time()); UMA_HISTOGRAM_TIMES("BlinkGC.TimeForIncrementalMarking", event.incremental_marking_time()); UMA_HISTOGRAM_TIMES("BlinkGC.TimeForMarking.Foreground", @@ -1618,6 +1620,9 @@ } void ThreadState::MarkPhaseVisitRoots() { + ThreadHeapStatsCollector::Scope stats_scope( + Heap().stats_collector(), ThreadHeapStatsCollector::kVisitRoots); + Visitor* visitor = current_gc_data_.visitor.get(); VisitPersistents(visitor); @@ -1639,7 +1644,7 @@ } if (current_gc_data_.stack_state == BlinkGC::kHeapPointersOnStack) { - ThreadHeapStatsCollector::Scope stats_scope( + ThreadHeapStatsCollector::Scope stack_stats_scope( Heap().stats_collector(), ThreadHeapStatsCollector::kVisitStackRoots); PushRegistersAndVisitStack(); }
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_request.cc b/third_party/blink/renderer/platform/loader/fetch/resource_request.cc index 4a07d2eb..0a75aaf2 100644 --- a/third_party/blink/renderer/platform/loader/fetch/resource_request.cc +++ b/third_party/blink/renderer/platform/loader/fetch/resource_request.cc
@@ -97,6 +97,7 @@ std::unique_ptr<ResourceRequest> request = std::make_unique<ResourceRequest>(new_url); request->SetRequestorOrigin(RequestorOrigin()); + request->SetIsolatedWorldOrigin(IsolatedWorldOrigin()); request->SetHttpMethod(new_method); request->SetSiteForCookies(new_site_for_cookies); String referrer =
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 index 9420a1b..870fc43 100644 --- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 +++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -1871,15 +1871,6 @@ status: "stable", }, { - name: "WebXRAnchors", - // depends_on: ["WebXRARModule"], // TODO(https://crbug.com/954679): uncomment once bug is fixed - }, - { - name: "WebXRARDOMOverlay", - // depends_on: ["WebXRARModule"], // TODO(https://crbug.com/954679): uncomment once bug is fixed - status: "experimental", - }, - { name: "WebXRARModule", depends_on: ["WebXR"], status: "experimental", @@ -1890,8 +1881,9 @@ status: "experimental" }, { - name: "WebXRPlaneDetection", + name: "WebXRIncubations", // depends_on: ["WebXRARModule"], // TODO(https://crbug.com/954679): uncomment once bug is fixed + status: "experimental", }, // Extends window placement functionality for multi-screen devices. {
diff --git a/third_party/blink/web_tests/MSANExpectations b/third_party/blink/web_tests/MSANExpectations index bab9f08b..4540782 100644 --- a/third_party/blink/web_tests/MSANExpectations +++ b/third_party/blink/web_tests/MSANExpectations
@@ -362,3 +362,7 @@ # Note to sheriffs: Timeouts about "idlharness" or "interfaces" are usually crbug.com/856601. crbug.com/856601 [ Linux ] external/wpt/secure-contexts/idlharness.any.html [ Pass Timeout ] crbug.com/856601 [ Linux ] external/wpt/compression/compression-stream.tentative.any.serviceworker.html [ Pass Timeout ] + +# Sheriff 2019-12-27 +crbug.com/856601 [ Linux ] external/wpt/battery-status/idlharness.https.window.html [ Pass Timeout ] +crbug.com/856601 [ Linux ] external/wpt/permissions/idlharness.any.html [ Pass Timeout ]
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index dfe34d6..9b47a6b3 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -1470,7 +1470,7 @@ crbug.com/6606 external/wpt/mathml/relations/css-styling/displaystyle-015.html [ Failure ] crbug.com/6606 external/wpt/mathml/relations/css-styling/displaystyle-1.html [ Failure ] crbug.com/6606 external/wpt/mathml/relations/css-styling/displaystyle-2.html [ Failure ] -crbug.com/6606 external/wpt/mathml/relations/css-styling/ignored-properties-001.html [ Failure ] +crbug.com/6606 external/wpt/mathml/relations/css-styling/ignored-properties-001.html [ Failure Timeout ] crbug.com/6606 external/wpt/mathml/relations/css-styling/lengths-1.html [ Failure ] crbug.com/6606 external/wpt/mathml/relations/css-styling/lengths-2.html [ Failure ] crbug.com/6606 external/wpt/mathml/relations/css-styling/mathvariant-auto.html [ Failure ] @@ -6145,4 +6145,10 @@ crbug.com/1036626 virtual/threaded/http/tests/devtools/tracing/tracing-record-input-events.js [ Pass Failure ] crbug.com/1036054 [ Mac10.13 ] virtual/threaded/fast/scroll-snap/snap-to-area-with-fractional-offset.html [ Pass Failure ] crbug.com/960944 animations/web-animations/animation-state-changes-positive-playback-rate.html [ Pass Failure ] -crbug.com/1033381 synthetic_gestures/smooth-scroll-tiny-delta.html [ Pass Crash ] \ No newline at end of file +crbug.com/1033381 synthetic_gestures/smooth-scroll-tiny-delta.html [ Pass Crash ] + +# Sheriff 2019-12-27 +crbug.com/1038037 [ Win ] virtual/gpu-rasterization/images/exif-orientation-css.html [ Pass Failure ] +crbug.com/1038037 [ Win ] virtual/gpu-rasterization/images/exif-orientation-none-css.html [ Pass Failure ] +crbug.com/1037798 [ Win ] virtual/gpu-rasterization/images/exif-orientation-image-document.html [ Pass Failure ] +crbug.com/1038091 [ Win ] virtual/gpu-rasterization/images/jpeg-yuv-image-decoding.html [ Pass Failure ]
diff --git a/third_party/blink/web_tests/animations/composition/column-gap-composition.html b/third_party/blink/web_tests/animations/composition/column-gap-composition.html deleted file mode 100644 index 6c8512d..0000000 --- a/third_party/blink/web_tests/animations/composition/column-gap-composition.html +++ /dev/null
@@ -1,58 +0,0 @@ -<!DOCTYPE html> -<meta charset="UTF-8"> -<body> -<script src="../interpolation/resources/interpolation-test.js"></script> -<script> -assertComposition({ - property: 'column-gap', - underlying: '50px', - addFrom: '100px', - addTo: '200px', -}, [ - {at: -0.3, is: '120px'}, - {at: 0, is: '150px'}, - {at: 0.5, is: '200px'}, - {at: 1, is: '250px'}, - {at: 1.5, is: '300px'}, -]); - -assertComposition({ - property: 'column-gap', - underlying: '100px', - addFrom: '10px', - addTo: '2px', -}, [ - {at: -0.5, is: '114px'}, - {at: 0, is: '110px'}, - {at: 0.5, is: '106px'}, - {at: 1, is: '102px'}, - {at: 1.5, is: '98px'}, // Value clamping should happen after composition. -]); - -assertComposition({ - property: 'column-gap', - underlying: '50px', - addFrom: '100px', - replaceTo: '200px', -}, [ - {at: -0.3, is: '135px'}, - {at: 0, is: '150px'}, - {at: 0.5, is: '175px'}, - {at: 1, is: '200px'}, - {at: 1.5, is: '225px'}, -]); - -assertComposition({ - property: 'column-gap', - underlying: '100px', - addFrom: '100px', - addTo: 'normal', -}, [ - {at: -0.3, is: '200px'}, - {at: 0, is: '200px'}, - {at: 0.5, is: 'normal'}, - {at: 1, is: 'normal'}, - {at: 1.5, is: 'normal'}, -]); -</script> -</body>
diff --git a/third_party/blink/web_tests/animations/composition/height-composition.html b/third_party/blink/web_tests/animations/composition/height-composition.html deleted file mode 100644 index d1224586..0000000 --- a/third_party/blink/web_tests/animations/composition/height-composition.html +++ /dev/null
@@ -1,71 +0,0 @@ -<!DOCTYPE html> -<meta charset="UTF-8"> -<body> -<script src="../interpolation/resources/interpolation-test.js"></script> -<script> -assertComposition({ - property: 'height', - underlying: '50px', - addFrom: '100px', - addTo: '200px', -}, [ - {at: -0.3, is: '120px'}, - {at: 0, is: '150px'}, - {at: 0.5, is: '200px'}, - {at: 1, is: '250px'}, - {at: 1.5, is: '300px'}, -]); - -assertComposition({ - property: 'height', - underlying: '100px', - addFrom: '10px', - addTo: '2px', -}, [ - {at: -0.5, is: '114px'}, - {at: 0, is: '110px'}, - {at: 0.5, is: '106px'}, - {at: 1, is: '102px'}, - {at: 1.5, is: '98px'}, // Value clamping should happen after composition. -]); - -assertComposition({ - property: 'height', - underlying: '10%', - addFrom: '100px', - addTo: '20%', -}, [ - {at: -0.3, is: 'calc(130px + 4%)'}, - {at: 0, is: 'calc(100px + 10%)'}, - {at: 0.5, is: 'calc(50px + 20%)'}, - {at: 1, is: '30%'}, - {at: 1.5, is: 'calc(-50px + 40%)'}, -]); - -assertComposition({ - property: 'height', - underlying: '50px', - addFrom: '100px', - replaceTo: '200px', -}, [ - {at: -0.3, is: '135px'}, - {at: 0, is: '150px'}, - {at: 0.5, is: '175px'}, - {at: 1, is: '200px'}, - {at: 1.5, is: '225px'}, -]); - -assertComposition({ - property: 'height', - underlying: '100px', - addFrom: '100px', - addTo: 'auto', -}, [ - {at: -0.3, is: '200px'}, - {at: 0, is: '200px'}, - {at: 0.5, is: 'auto'}, - {at: 1, is: 'auto'}, - {at: 1.5, is: 'auto'}, -]); -</script> -</body>
diff --git a/third_party/blink/web_tests/animations/composition/margin-bottom-composition.html b/third_party/blink/web_tests/animations/composition/margin-bottom-composition.html deleted file mode 100644 index a2c6e5b..0000000 --- a/third_party/blink/web_tests/animations/composition/margin-bottom-composition.html +++ /dev/null
@@ -1,71 +0,0 @@ -<!DOCTYPE html> -<meta charset="UTF-8"> -<body> -<script src="../interpolation/resources/interpolation-test.js"></script> -<script> -assertComposition({ - property: 'margin-bottom', - underlying: '50px', - addFrom: '100px', - addTo: '200px', -}, [ - {at: -0.3, is: '120px'}, - {at: 0, is: '150px'}, - {at: 0.5, is: '200px'}, - {at: 1, is: '250px'}, - {at: 1.5, is: '300px'}, -]); - -assertComposition({ - property: 'margin-bottom', - underlying: '100px', - addFrom: '10px', - addTo: '2px', -}, [ - {at: -0.5, is: '114px'}, - {at: 0, is: '110px'}, - {at: 0.5, is: '106px'}, - {at: 1, is: '102px'}, - {at: 1.5, is: '98px'}, -]); - -assertComposition({ - property: 'margin-bottom', - underlying: '10%', - addFrom: '100px', - addTo: '20%', -}, [ - {at: -0.3, is: 'calc(130px + 4%)'}, - {at: 0, is: 'calc(100px + 10%)'}, - {at: 0.5, is: 'calc(50px + 20%)'}, - {at: 1, is: '30%'}, - {at: 1.5, is: 'calc(-50px + 40%)'}, -]); - -assertComposition({ - property: 'margin-bottom', - underlying: '50px', - addFrom: '100px', - replaceTo: '200px', -}, [ - {at: -0.3, is: '135px'}, - {at: 0, is: '150px'}, - {at: 0.5, is: '175px'}, - {at: 1, is: '200px'}, - {at: 1.5, is: '225px'}, -]); - -assertComposition({ - property: 'margin-bottom', - underlying: '100px', - addFrom: '100px', - addTo: 'auto', -}, [ - {at: -0.3, is: '200px'}, - {at: 0, is: '200px'}, - {at: 0.5, is: 'auto'}, - {at: 1, is: 'auto'}, - {at: 1.5, is: 'auto'}, -]); -</script> -</body>
diff --git a/third_party/blink/web_tests/animations/composition/margin-left-composition.html b/third_party/blink/web_tests/animations/composition/margin-left-composition.html deleted file mode 100644 index 7db9096f..0000000 --- a/third_party/blink/web_tests/animations/composition/margin-left-composition.html +++ /dev/null
@@ -1,71 +0,0 @@ -<!DOCTYPE html> -<meta charset="UTF-8"> -<body> -<script src="../interpolation/resources/interpolation-test.js"></script> -<script> -assertComposition({ - property: 'margin-left', - underlying: '50px', - addFrom: '100px', - addTo: '200px', -}, [ - {at: -0.3, is: '120px'}, - {at: 0, is: '150px'}, - {at: 0.5, is: '200px'}, - {at: 1, is: '250px'}, - {at: 1.5, is: '300px'}, -]); - -assertComposition({ - property: 'margin-left', - underlying: '100px', - addFrom: '10px', - addTo: '2px', -}, [ - {at: -0.5, is: '114px'}, - {at: 0, is: '110px'}, - {at: 0.5, is: '106px'}, - {at: 1, is: '102px'}, - {at: 1.5, is: '98px'}, -]); - -assertComposition({ - property: 'margin-left', - underlying: '10%', - addFrom: '100px', - addTo: '20%', -}, [ - {at: -0.3, is: 'calc(130px + 4%)'}, - {at: 0, is: 'calc(100px + 10%)'}, - {at: 0.5, is: 'calc(50px + 20%)'}, - {at: 1, is: '30%'}, - {at: 1.5, is: 'calc(-50px + 40%)'}, -]); - -assertComposition({ - property: 'margin-left', - underlying: '50px', - addFrom: '100px', - replaceTo: '200px', -}, [ - {at: -0.3, is: '135px'}, - {at: 0, is: '150px'}, - {at: 0.5, is: '175px'}, - {at: 1, is: '200px'}, - {at: 1.5, is: '225px'}, -]); - -assertComposition({ - property: 'margin-left', - underlying: '100px', - addFrom: '100px', - addTo: 'auto', -}, [ - {at: -0.3, is: '200px'}, - {at: 0, is: '200px'}, - {at: 0.5, is: 'auto'}, - {at: 1, is: 'auto'}, - {at: 1.5, is: 'auto'}, -]); -</script> -</body>
diff --git a/third_party/blink/web_tests/animations/composition/margin-right-composition.html b/third_party/blink/web_tests/animations/composition/margin-right-composition.html deleted file mode 100644 index 00762fa..0000000 --- a/third_party/blink/web_tests/animations/composition/margin-right-composition.html +++ /dev/null
@@ -1,71 +0,0 @@ -<!DOCTYPE html> -<meta charset="UTF-8"> -<body> -<script src="../interpolation/resources/interpolation-test.js"></script> -<script> -assertComposition({ - property: 'margin-right', - underlying: '50px', - addFrom: '100px', - addTo: '200px', -}, [ - {at: -0.3, is: '120px'}, - {at: 0, is: '150px'}, - {at: 0.5, is: '200px'}, - {at: 1, is: '250px'}, - {at: 1.5, is: '300px'}, -]); - -assertComposition({ - property: 'margin-right', - underlying: '100px', - addFrom: '10px', - addTo: '2px', -}, [ - {at: -0.5, is: '114px'}, - {at: 0, is: '110px'}, - {at: 0.5, is: '106px'}, - {at: 1, is: '102px'}, - {at: 1.5, is: '98px'}, -]); - -assertComposition({ - property: 'margin-right', - underlying: '10%', - addFrom: '100px', - addTo: '20%', -}, [ - {at: -0.3, is: 'calc(130px + 4%)'}, - {at: 0, is: 'calc(100px + 10%)'}, - {at: 0.5, is: 'calc(50px + 20%)'}, - {at: 1, is: '30%'}, - {at: 1.5, is: 'calc(-50px + 40%)'}, -]); - -assertComposition({ - property: 'margin-right', - underlying: '50px', - addFrom: '100px', - replaceTo: '200px', -}, [ - {at: -0.3, is: '135px'}, - {at: 0, is: '150px'}, - {at: 0.5, is: '175px'}, - {at: 1, is: '200px'}, - {at: 1.5, is: '225px'}, -]); - -assertComposition({ - property: 'margin-right', - underlying: '100px', - addFrom: '100px', - addTo: 'auto', -}, [ - {at: -0.3, is: '200px'}, - {at: 0, is: '200px'}, - {at: 0.5, is: 'auto'}, - {at: 1, is: 'auto'}, - {at: 1.5, is: 'auto'}, -]); -</script> -</body>
diff --git a/third_party/blink/web_tests/animations/composition/margin-top-composition.html b/third_party/blink/web_tests/animations/composition/margin-top-composition.html deleted file mode 100644 index 21774b61..0000000 --- a/third_party/blink/web_tests/animations/composition/margin-top-composition.html +++ /dev/null
@@ -1,71 +0,0 @@ -<!DOCTYPE html> -<meta charset="UTF-8"> -<body> -<script src="../interpolation/resources/interpolation-test.js"></script> -<script> -assertComposition({ - property: 'margin-top', - underlying: '50px', - addFrom: '100px', - addTo: '200px', -}, [ - {at: -0.3, is: '120px'}, - {at: 0, is: '150px'}, - {at: 0.5, is: '200px'}, - {at: 1, is: '250px'}, - {at: 1.5, is: '300px'}, -]); - -assertComposition({ - property: 'margin-top', - underlying: '100px', - addFrom: '10px', - addTo: '2px', -}, [ - {at: -0.5, is: '114px'}, - {at: 0, is: '110px'}, - {at: 0.5, is: '106px'}, - {at: 1, is: '102px'}, - {at: 1.5, is: '98px'}, -]); - -assertComposition({ - property: 'margin-top', - underlying: '10%', - addFrom: '100px', - addTo: '20%', -}, [ - {at: -0.3, is: 'calc(130px + 4%)'}, - {at: 0, is: 'calc(100px + 10%)'}, - {at: 0.5, is: 'calc(50px + 20%)'}, - {at: 1, is: '30%'}, - {at: 1.5, is: 'calc(-50px + 40%)'}, -]); - -assertComposition({ - property: 'margin-top', - underlying: '50px', - addFrom: '100px', - replaceTo: '200px', -}, [ - {at: -0.3, is: '135px'}, - {at: 0, is: '150px'}, - {at: 0.5, is: '175px'}, - {at: 1, is: '200px'}, - {at: 1.5, is: '225px'}, -]); - -assertComposition({ - property: 'margin-top', - underlying: '100px', - addFrom: '100px', - addTo: 'auto', -}, [ - {at: -0.3, is: '200px'}, - {at: 0, is: '200px'}, - {at: 0.5, is: 'auto'}, - {at: 1, is: 'auto'}, - {at: 1.5, is: 'auto'}, -]); -</script> -</body>
diff --git a/third_party/blink/web_tests/animations/composition/max-height-composition.html b/third_party/blink/web_tests/animations/composition/max-height-composition.html deleted file mode 100644 index 64d7057..0000000 --- a/third_party/blink/web_tests/animations/composition/max-height-composition.html +++ /dev/null
@@ -1,71 +0,0 @@ -<!DOCTYPE html> -<meta charset="UTF-8"> -<body> -<script src="../interpolation/resources/interpolation-test.js"></script> -<script> -assertComposition({ - property: 'max-height', - underlying: '50px', - addFrom: '100px', - addTo: '200px', -}, [ - {at: -0.3, is: '120px'}, - {at: 0, is: '150px'}, - {at: 0.5, is: '200px'}, - {at: 1, is: '250px'}, - {at: 1.5, is: '300px'}, -]); - -assertComposition({ - property: 'max-height', - underlying: '100px', - addFrom: '10px', - addTo: '2px', -}, [ - {at: -0.5, is: '114px'}, - {at: 0, is: '110px'}, - {at: 0.5, is: '106px'}, - {at: 1, is: '102px'}, - {at: 1.5, is: '98px'}, // Value clamping should happen after composition. -]); - -assertComposition({ - property: 'max-height', - underlying: '10%', - addFrom: '100px', - addTo: '20%', -}, [ - {at: -0.3, is: 'calc(130px + 4%)'}, - {at: 0, is: 'calc(100px + 10%)'}, - {at: 0.5, is: 'calc(50px + 20%)'}, - {at: 1, is: '30%'}, - {at: 1.5, is: 'calc(-50px + 40%)'}, -]); - -assertComposition({ - property: 'max-height', - underlying: '50px', - addFrom: '100px', - replaceTo: '200px', -}, [ - {at: -0.3, is: '135px'}, - {at: 0, is: '150px'}, - {at: 0.5, is: '175px'}, - {at: 1, is: '200px'}, - {at: 1.5, is: '225px'}, -]); - -assertComposition({ - property: 'max-height', - underlying: '100px', - addFrom: '100px', - addTo: 'none', -}, [ - {at: -0.3, is: '200px'}, - {at: 0, is: '200px'}, - {at: 0.5, is: 'none'}, - {at: 1, is: 'none'}, - {at: 1.5, is: 'none'}, -]); -</script> -</body>
diff --git a/third_party/blink/web_tests/animations/composition/max-width-composition.html b/third_party/blink/web_tests/animations/composition/max-width-composition.html deleted file mode 100644 index 4d8ddb04..0000000 --- a/third_party/blink/web_tests/animations/composition/max-width-composition.html +++ /dev/null
@@ -1,71 +0,0 @@ -<!DOCTYPE html> -<meta charset="UTF-8"> -<body> -<script src="../interpolation/resources/interpolation-test.js"></script> -<script> -assertComposition({ - property: 'max-width', - underlying: '50px', - addFrom: '100px', - addTo: '200px', -}, [ - {at: -0.3, is: '120px'}, - {at: 0, is: '150px'}, - {at: 0.5, is: '200px'}, - {at: 1, is: '250px'}, - {at: 1.5, is: '300px'}, -]); - -assertComposition({ - property: 'max-width', - underlying: '100px', - addFrom: '10px', - addTo: '2px', -}, [ - {at: -0.5, is: '114px'}, - {at: 0, is: '110px'}, - {at: 0.5, is: '106px'}, - {at: 1, is: '102px'}, - {at: 1.5, is: '98px'}, // Value clamping should happen after composition. -]); - -assertComposition({ - property: 'max-width', - underlying: '10%', - addFrom: '100px', - addTo: '20%', -}, [ - {at: -0.3, is: 'calc(130px + 4%)'}, - {at: 0, is: 'calc(100px + 10%)'}, - {at: 0.5, is: 'calc(50px + 20%)'}, - {at: 1, is: '30%'}, - {at: 1.5, is: 'calc(-50px + 40%)'}, -]); - -assertComposition({ - property: 'max-width', - underlying: '50px', - addFrom: '100px', - replaceTo: '200px', -}, [ - {at: -0.3, is: '135px'}, - {at: 0, is: '150px'}, - {at: 0.5, is: '175px'}, - {at: 1, is: '200px'}, - {at: 1.5, is: '225px'}, -]); - -assertComposition({ - property: 'max-width', - underlying: '100px', - addFrom: '100px', - addTo: 'none', -}, [ - {at: -0.3, is: '200px'}, - {at: 0, is: '200px'}, - {at: 0.5, is: 'none'}, - {at: 1, is: 'none'}, - {at: 1.5, is: 'none'}, -]); -</script> -</body>
diff --git a/third_party/blink/web_tests/animations/composition/min-height-composition.html b/third_party/blink/web_tests/animations/composition/min-height-composition.html deleted file mode 100644 index efe3d874..0000000 --- a/third_party/blink/web_tests/animations/composition/min-height-composition.html +++ /dev/null
@@ -1,71 +0,0 @@ -<!DOCTYPE html> -<meta charset="UTF-8"> -<body> -<script src="../interpolation/resources/interpolation-test.js"></script> -<script> -assertComposition({ - property: 'min-height', - underlying: '50px', - addFrom: '100px', - addTo: '200px', -}, [ - {at: -0.3, is: '120px'}, - {at: 0, is: '150px'}, - {at: 0.5, is: '200px'}, - {at: 1, is: '250px'}, - {at: 1.5, is: '300px'}, -]); - -assertComposition({ - property: 'min-height', - underlying: '100px', - addFrom: '10px', - addTo: '2px', -}, [ - {at: -0.5, is: '114px'}, - {at: 0, is: '110px'}, - {at: 0.5, is: '106px'}, - {at: 1, is: '102px'}, - {at: 1.5, is: '98px'}, // Value clamping should happen after composition. -]); - -assertComposition({ - property: 'min-height', - underlying: '10%', - addFrom: '100px', - addTo: '20%', -}, [ - {at: -0.3, is: 'calc(130px + 4%)'}, - {at: 0, is: 'calc(100px + 10%)'}, - {at: 0.5, is: 'calc(50px + 20%)'}, - {at: 1, is: '30%'}, - {at: 1.5, is: 'calc(-50px + 40%)'}, -]); - -assertComposition({ - property: 'min-height', - underlying: '50px', - addFrom: '100px', - replaceTo: '200px', -}, [ - {at: -0.3, is: '135px'}, - {at: 0, is: '150px'}, - {at: 0.5, is: '175px'}, - {at: 1, is: '200px'}, - {at: 1.5, is: '225px'}, -]); - -assertComposition({ - property: 'min-height', - underlying: '100px', - addFrom: '100px', - addTo: 'auto', -}, [ - {at: -0.3, is: '200px'}, - {at: 0, is: '200px'}, - {at: 0.5, is: 'auto'}, - {at: 1, is: 'auto'}, - {at: 1.5, is: 'auto'}, -]); -</script> -</body>
diff --git a/third_party/blink/web_tests/animations/composition/min-width-composition.html b/third_party/blink/web_tests/animations/composition/min-width-composition.html deleted file mode 100644 index 55e1e75..0000000 --- a/third_party/blink/web_tests/animations/composition/min-width-composition.html +++ /dev/null
@@ -1,71 +0,0 @@ -<!DOCTYPE html> -<meta charset="UTF-8"> -<body> -<script src="../interpolation/resources/interpolation-test.js"></script> -<script> -assertComposition({ - property: 'min-width', - underlying: '50px', - addFrom: '100px', - addTo: '200px', -}, [ - {at: -0.3, is: '120px'}, - {at: 0, is: '150px'}, - {at: 0.5, is: '200px'}, - {at: 1, is: '250px'}, - {at: 1.5, is: '300px'}, -]); - -assertComposition({ - property: 'min-width', - underlying: '100px', - addFrom: '10px', - addTo: '2px', -}, [ - {at: -0.5, is: '114px'}, - {at: 0, is: '110px'}, - {at: 0.5, is: '106px'}, - {at: 1, is: '102px'}, - {at: 1.5, is: '98px'}, // Value clamping should happen after composition. -]); - -assertComposition({ - property: 'min-width', - underlying: '10%', - addFrom: '100px', - addTo: '20%', -}, [ - {at: -0.3, is: 'calc(130px + 4%)'}, - {at: 0, is: 'calc(100px + 10%)'}, - {at: 0.5, is: 'calc(50px + 20%)'}, - {at: 1, is: '30%'}, - {at: 1.5, is: 'calc(-50px + 40%)'}, -]); - -assertComposition({ - property: 'min-width', - underlying: '50px', - addFrom: '100px', - replaceTo: '200px', -}, [ - {at: -0.3, is: '135px'}, - {at: 0, is: '150px'}, - {at: 0.5, is: '175px'}, - {at: 1, is: '200px'}, - {at: 1.5, is: '225px'}, -]); - -assertComposition({ - property: 'min-width', - underlying: '100px', - addFrom: '100px', - addTo: 'auto', -}, [ - {at: -0.3, is: '200px'}, - {at: 0, is: '200px'}, - {at: 0.5, is: 'auto'}, - {at: 1, is: 'auto'}, - {at: 1.5, is: 'auto'}, -]); -</script> -</body>
diff --git a/third_party/blink/web_tests/animations/composition/padding-bottom-composition.html b/third_party/blink/web_tests/animations/composition/padding-bottom-composition.html deleted file mode 100644 index 4a4ff24..0000000 --- a/third_party/blink/web_tests/animations/composition/padding-bottom-composition.html +++ /dev/null
@@ -1,58 +0,0 @@ -<!DOCTYPE html> -<meta charset="UTF-8"> -<body> -<script src="../interpolation/resources/interpolation-test.js"></script> -<script> -assertComposition({ - property: 'padding-bottom', - underlying: '50px', - addFrom: '100px', - addTo: '200px', -}, [ - {at: -0.3, is: '120px'}, - {at: 0, is: '150px'}, - {at: 0.5, is: '200px'}, - {at: 1, is: '250px'}, - {at: 1.5, is: '300px'}, -]); - -assertComposition({ - property: 'padding-bottom', - underlying: '100px', - addFrom: '10px', - addTo: '2px', -}, [ - {at: -0.5, is: '114px'}, - {at: 0, is: '110px'}, - {at: 0.5, is: '106px'}, - {at: 1, is: '102px'}, - {at: 1.5, is: '98px'}, // Value clamping should happen after composition. -]); - -assertComposition({ - property: 'padding-bottom', - underlying: '10%', - addFrom: '100px', - addTo: '20%', -}, [ - {at: -0.3, is: 'calc(130px + 4%)'}, - {at: 0, is: 'calc(100px + 10%)'}, - {at: 0.5, is: 'calc(50px + 20%)'}, - {at: 1, is: '30%'}, - {at: 1.5, is: 'calc(-50px + 40%)'}, -]); - -assertComposition({ - property: 'padding-bottom', - underlying: '50px', - addFrom: '100px', - replaceTo: '200px', -}, [ - {at: -0.3, is: '135px'}, - {at: 0, is: '150px'}, - {at: 0.5, is: '175px'}, - {at: 1, is: '200px'}, - {at: 1.5, is: '225px'}, -]); -</script> -</body>
diff --git a/third_party/blink/web_tests/animations/composition/padding-left-composition.html b/third_party/blink/web_tests/animations/composition/padding-left-composition.html deleted file mode 100644 index 4b265105..0000000 --- a/third_party/blink/web_tests/animations/composition/padding-left-composition.html +++ /dev/null
@@ -1,58 +0,0 @@ -<!DOCTYPE html> -<meta charset="UTF-8"> -<body> -<script src="../interpolation/resources/interpolation-test.js"></script> -<script> -assertComposition({ - property: 'padding-left', - underlying: '50px', - addFrom: '100px', - addTo: '200px', -}, [ - {at: -0.3, is: '120px'}, - {at: 0, is: '150px'}, - {at: 0.5, is: '200px'}, - {at: 1, is: '250px'}, - {at: 1.5, is: '300px'}, -]); - -assertComposition({ - property: 'padding-left', - underlying: '100px', - addFrom: '10px', - addTo: '2px', -}, [ - {at: -0.5, is: '114px'}, - {at: 0, is: '110px'}, - {at: 0.5, is: '106px'}, - {at: 1, is: '102px'}, - {at: 1.5, is: '98px'}, // Value clamping should happen after composition. -]); - -assertComposition({ - property: 'padding-left', - underlying: '10%', - addFrom: '100px', - addTo: '20%', -}, [ - {at: -0.3, is: 'calc(130px + 4%)'}, - {at: 0, is: 'calc(100px + 10%)'}, - {at: 0.5, is: 'calc(50px + 20%)'}, - {at: 1, is: '30%'}, - {at: 1.5, is: 'calc(-50px + 40%)'}, -]); - -assertComposition({ - property: 'padding-left', - underlying: '50px', - addFrom: '100px', - replaceTo: '200px', -}, [ - {at: -0.3, is: '135px'}, - {at: 0, is: '150px'}, - {at: 0.5, is: '175px'}, - {at: 1, is: '200px'}, - {at: 1.5, is: '225px'}, -]); -</script> -</body>
diff --git a/third_party/blink/web_tests/animations/composition/padding-right-composition.html b/third_party/blink/web_tests/animations/composition/padding-right-composition.html deleted file mode 100644 index 4bbef1e..0000000 --- a/third_party/blink/web_tests/animations/composition/padding-right-composition.html +++ /dev/null
@@ -1,58 +0,0 @@ -<!DOCTYPE html> -<meta charset="UTF-8"> -<body> -<script src="../interpolation/resources/interpolation-test.js"></script> -<script> -assertComposition({ - property: 'padding-right', - underlying: '50px', - addFrom: '100px', - addTo: '200px', -}, [ - {at: -0.3, is: '120px'}, - {at: 0, is: '150px'}, - {at: 0.5, is: '200px'}, - {at: 1, is: '250px'}, - {at: 1.5, is: '300px'}, -]); - -assertComposition({ - property: 'padding-right', - underlying: '100px', - addFrom: '10px', - addTo: '2px', -}, [ - {at: -0.5, is: '114px'}, - {at: 0, is: '110px'}, - {at: 0.5, is: '106px'}, - {at: 1, is: '102px'}, - {at: 1.5, is: '98px'}, // Value clamping should happen after composition. -]); - -assertComposition({ - property: 'padding-right', - underlying: '10%', - addFrom: '100px', - addTo: '20%', -}, [ - {at: -0.3, is: 'calc(130px + 4%)'}, - {at: 0, is: 'calc(100px + 10%)'}, - {at: 0.5, is: 'calc(50px + 20%)'}, - {at: 1, is: '30%'}, - {at: 1.5, is: 'calc(-50px + 40%)'}, -]); - -assertComposition({ - property: 'padding-right', - underlying: '50px', - addFrom: '100px', - replaceTo: '200px', -}, [ - {at: -0.3, is: '135px'}, - {at: 0, is: '150px'}, - {at: 0.5, is: '175px'}, - {at: 1, is: '200px'}, - {at: 1.5, is: '225px'}, -]); -</script> -</body>
diff --git a/third_party/blink/web_tests/animations/composition/padding-top-composition.html b/third_party/blink/web_tests/animations/composition/padding-top-composition.html deleted file mode 100644 index 3b88e53..0000000 --- a/third_party/blink/web_tests/animations/composition/padding-top-composition.html +++ /dev/null
@@ -1,58 +0,0 @@ -<!DOCTYPE html> -<meta charset="UTF-8"> -<body> -<script src="../interpolation/resources/interpolation-test.js"></script> -<script> -assertComposition({ - property: 'padding-top', - underlying: '50px', - addFrom: '100px', - addTo: '200px', -}, [ - {at: -0.3, is: '120px'}, - {at: 0, is: '150px'}, - {at: 0.5, is: '200px'}, - {at: 1, is: '250px'}, - {at: 1.5, is: '300px'}, -]); - -assertComposition({ - property: 'padding-top', - underlying: '100px', - addFrom: '10px', - addTo: '2px', -}, [ - {at: -0.5, is: '114px'}, - {at: 0, is: '110px'}, - {at: 0.5, is: '106px'}, - {at: 1, is: '102px'}, - {at: 1.5, is: '98px'}, // Value clamping should happen after composition. -]); - -assertComposition({ - property: 'padding-top', - underlying: '10%', - addFrom: '100px', - addTo: '20%', -}, [ - {at: -0.3, is: 'calc(130px + 4%)'}, - {at: 0, is: 'calc(100px + 10%)'}, - {at: 0.5, is: 'calc(50px + 20%)'}, - {at: 1, is: '30%'}, - {at: 1.5, is: 'calc(-50px + 40%)'}, -]); - -assertComposition({ - property: 'padding-top', - underlying: '50px', - addFrom: '100px', - replaceTo: '200px', -}, [ - {at: -0.3, is: '135px'}, - {at: 0, is: '150px'}, - {at: 0.5, is: '175px'}, - {at: 1, is: '200px'}, - {at: 1.5, is: '225px'}, -]); -</script> -</body>
diff --git a/third_party/blink/web_tests/animations/composition/row-gap-composition.html b/third_party/blink/web_tests/animations/composition/row-gap-composition.html deleted file mode 100644 index 055d5cb..0000000 --- a/third_party/blink/web_tests/animations/composition/row-gap-composition.html +++ /dev/null
@@ -1,58 +0,0 @@ -<!DOCTYPE html> -<meta charset="UTF-8"> -<body> -<script src="../interpolation/resources/interpolation-test.js"></script> -<script> -assertComposition({ - property: 'row-gap', - underlying: '50px', - addFrom: '100px', - addTo: '200px', -}, [ - {at: -0.3, is: '120px'}, - {at: 0, is: '150px'}, - {at: 0.5, is: '200px'}, - {at: 1, is: '250px'}, - {at: 1.5, is: '300px'}, -]); - -assertComposition({ - property: 'row-gap', - underlying: '100px', - addFrom: '10px', - addTo: '2px', -}, [ - {at: -0.5, is: '114px'}, - {at: 0, is: '110px'}, - {at: 0.5, is: '106px'}, - {at: 1, is: '102px'}, - {at: 1.5, is: '98px'}, // Value clamping should happen after composition. -]); - -assertComposition({ - property: 'row-gap', - underlying: '50px', - addFrom: '100px', - replaceTo: '200px', -}, [ - {at: -0.3, is: '135px'}, - {at: 0, is: '150px'}, - {at: 0.5, is: '175px'}, - {at: 1, is: '200px'}, - {at: 1.5, is: '225px'}, -]); - -assertComposition({ - property: 'row-gap', - underlying: '100px', - addFrom: '100px', - addTo: 'normal', -}, [ - {at: -0.3, is: '200px'}, - {at: 0, is: '200px'}, - {at: 0.5, is: 'normal'}, - {at: 1, is: 'normal'}, - {at: 1.5, is: 'normal'}, -]); -</script> -</body>
diff --git a/third_party/blink/web_tests/animations/composition/shape-margin-composition.html b/third_party/blink/web_tests/animations/composition/shape-margin-composition.html deleted file mode 100644 index 62ae2dd..0000000 --- a/third_party/blink/web_tests/animations/composition/shape-margin-composition.html +++ /dev/null
@@ -1,58 +0,0 @@ -<!DOCTYPE html> -<meta charset="UTF-8"> -<body> -<script src="../interpolation/resources/interpolation-test.js"></script> -<script> -assertComposition({ - property: 'shape-margin', - underlying: '50px', - addFrom: '100px', - addTo: '200px', -}, [ - {at: -0.3, is: '120px'}, - {at: 0, is: '150px'}, - {at: 0.5, is: '200px'}, - {at: 1, is: '250px'}, - {at: 1.5, is: '300px'}, -]); - -assertComposition({ - property: 'shape-margin', - underlying: '100px', - addFrom: '10px', - addTo: '2px', -}, [ - {at: -0.5, is: '114px'}, - {at: 0, is: '110px'}, - {at: 0.5, is: '106px'}, - {at: 1, is: '102px'}, - {at: 1.5, is: '98px'}, // Value clamping should happen after composition. -]); - -assertComposition({ - property: 'shape-margin', - underlying: '10%', - addFrom: '100px', - addTo: '20%', -}, [ - {at: -0.3, is: 'calc(130px + 4%)'}, - {at: 0, is: 'calc(100px + 10%)'}, - {at: 0.5, is: 'calc(50px + 20%)'}, - {at: 1, is: '30%'}, - {at: 1.5, is: 'calc(-50px + 40%)'}, -]); - -assertComposition({ - property: 'shape-margin', - underlying: '50px', - addFrom: '100px', - replaceTo: '200px', -}, [ - {at: -0.3, is: '135px'}, - {at: 0, is: '150px'}, - {at: 0.5, is: '175px'}, - {at: 1, is: '200px'}, - {at: 1.5, is: '225px'}, -]); -</script> -</body>
diff --git a/third_party/blink/web_tests/animations/composition/shape-outside-composition.html b/third_party/blink/web_tests/animations/composition/shape-outside-composition.html deleted file mode 100644 index 700ac0d..0000000 --- a/third_party/blink/web_tests/animations/composition/shape-outside-composition.html +++ /dev/null
@@ -1,182 +0,0 @@ -<!DOCTYPE html> -<meta charset="UTF-8"> -<body> -<script src="../interpolation/resources/interpolation-test.js"></script> -<script> -assertComposition({ - property: 'shape-outside', - underlying: 'circle(100px at 25px 25%)', - addFrom: 'circle(10px at 25px 75%)', - addTo: 'circle(50px at 50px center)', -}, [ - {at: -0.3, is: 'circle(98px at 42.5px 107.5%)'}, - {at: 0, is: 'circle(110px at 50px 100%)'}, - {at: 0.3, is: 'circle(122px at 57.5px 92.5%)'}, - {at: 0.6, is: 'circle(134px at 65px 85%)'}, - {at: 1, is: 'circle(150px at 75px 75%)'}, - {at: 1.5, is: 'circle(170px at 87.5px 62.5%)'}, -]); - -assertComposition({ - property: 'shape-outside', - underlying: 'circle(100px at 20px 20%)', - addFrom: 'circle(50px at 50px 50%)', - replaceTo: 'circle(50% at 150px 150%)', -}, [ - {at: -0.3, is: 'circle(calc(195px + -15%) at 46px 46%)'}, - {at: 0, is: 'circle(150px at 70px 70%)'}, - {at: 0.3, is: 'circle(calc(105px + 15%) at 94px 94%)'}, - {at: 0.6, is: 'circle(calc(60px + 30%) at 118px 118%)'}, - {at: 1, is: 'circle(50% at 150px 150%)'}, - {at: 1.5, is: 'circle(calc(-75px + 75%) at 190px 190%)'}, -]); - -assertComposition({ - property: 'shape-outside', - underlying: 'circle(farthest-side at 25px 75%)', - addFrom: 'circle(farthest-side at 25px 75%)', - addTo: 'circle(farthest-side at 50px center)', -}, [ - {at: 0.25, is: 'circle(farthest-side at 25px 75%)'}, - {at: 0.75, is: 'circle(farthest-side at 50px 50%)'}, -]); - -assertComposition({ - property: 'shape-outside', - underlying: 'circle(50px at 10px 20px)', - addFrom: 'circle(50px at 10px 20px)', - addTo: 'circle(farthest-side at 30px 40px)', -}, [ - {at: 0.25, is: 'circle(100px at 20px 40px)'}, - {at: 0.75, is: 'circle(farthest-side at 30px 40px)'}, -]); - -assertComposition({ - property: 'shape-outside', - underlying: 'ellipse(10px 20px at 30px 40px)', - addFrom: 'ellipse(40px 30px at 20px 10px)', - addTo: 'ellipse(140px 130px at 120px 110px)', -}, [ - {at: -0.3, is: 'ellipse(20px 20px at 20px 20px)'}, - {at: 0, is: 'ellipse(50px 50px at 50px 50px)'}, - {at: 0.3, is: 'ellipse(80px 80px at 80px 80px)'}, - {at: 0.6, is: 'ellipse(110px 110px at 110px 110px)'}, - {at: 1, is: 'ellipse(150px 150px at 150px 150px)'}, - {at: 1.5, is: 'ellipse(200px 200px at 200px 200px)'}, -]); - -assertComposition({ - property: 'shape-outside', - underlying: 'ellipse(10px 20px at 30px 40px)', - replaceFrom: 'ellipse(40px 30px at 20px 10px)', - addTo: 'ellipse(40px 30px at 20px 10px)', -}, [ - {at: -0.3, is: 'ellipse(37px 24px at 11px -2px)'}, - {at: 0, is: 'ellipse(40px 30px at 20px 10px)'}, - {at: 0.3, is: 'ellipse(43px 36px at 29px 22px)'}, - {at: 0.6, is: 'ellipse(46px 42px at 38px 34px)'}, - {at: 1, is: 'ellipse(50px 50px at 50px 50px)'}, - {at: 1.5, is: 'ellipse(55px 60px at 65px 70px)'}, -]); - -assertComposition({ - property: 'shape-outside', - underlying: 'ellipse(25px 75%)', - addFrom: 'ellipse()', - addTo: 'ellipse(closest-side farthest-side)', -}, [ - {at: 0.25, is: 'ellipse(at 50% 50%)'}, - {at: 0.75, is: 'ellipse(closest-side farthest-side at 50% 50%)'}, -]); - -assertComposition({ - property: 'shape-outside', - underlying: 'inset(20px)', - addFrom: 'inset(20px)', - addTo: 'inset(40%)', -}, [ - {at: -0.3, is: 'inset(calc(46px + -12%))'}, - {at: 0, is: 'inset(40px)'}, - {at: 0.3, is: 'inset(calc(34px + 12%))'}, - {at: 0.6, is: 'inset(calc(28px + 24%))'}, - {at: 1, is: 'inset(calc(20px + 40%))'}, - {at: 1.5, is: 'inset(calc(10px + 60%))'}, -]); - -assertComposition({ - property: 'shape-outside', - underlying: 'inset(1px 2px 3px 4px round 10px 20px 30px 40px / 50px 60px 70px 80px)', - addFrom: 'inset(1px 2px 3px 4px round 10px 20px 30px 40px / 50px 60px 70px 80px)', - replaceTo: 'inset(102px 104px 106px 108px round 120px 140px 160px 180px / 200px 220px 240px 260px)', -}, [ - {at: -0.3, is: 'inset(-28px -26px -24px -22px round 0px 10px 30px 50px / 70px 90px 110px 130px)'}, - {at: 0, is: 'inset(2px 4px 6px 8px round 20px 40px 60px 80px / 100px 120px 140px 160px)'}, - {at: 0.25, is: 'inset(27px 29px 31px 33px round 45px 65px 85px 105px / 125px 145px 165px 185px)'}, - {at: 0.75, is: 'inset(77px 79px 81px 83px round 95px 115px 135px 155px / 175px 195px 215px 235px)'}, - {at: 1, is: 'inset(102px 104px 106px 108px round 120px 140px 160px 180px / 200px 220px 240px 260px)'}, - {at: 1.5, is: 'inset(152px 154px 156px 158px round 170px 190px 210px 230px / 250px 270px 290px 310px)'}, -]); - -assertComposition({ - property: 'shape-outside', - underlying: 'inset(1px 2px round 100px 200px)', - addFrom: 'inset(1px 2px round 100px 200px)', - addTo: 'inset(101px 102px 101px 102px)', -}, [ - {at: -0.3, is: 'inset(-28px -26px round 230px 460px)'}, - {at: 0, is: 'inset(2px 4px round 200px 400px)'}, - {at: 0.3, is: 'inset(32px 34px round 170px 340px)'}, - {at: 0.6, is: 'inset(62px 64px round 140px 280px)'}, - {at: 1, is: 'inset(102px 104px round 100px 200px)'}, - {at: 1.5, is: 'inset(152px 154px round 50px 100px)'}, -]); - -assertComposition({ - property: 'shape-outside', - underlying: 'polygon(10px 20%, 30px 40%)', - addFrom: 'polygon(10px 20%, 30px 40%)', - addTo: 'polygon(110px 120%, 130px 140%)', -}, [ - {at: -0.3, is: 'polygon(-10px 10%, 30px 50%)'}, - {at: 0, is: 'polygon(20px 40%, 60px 80%)'}, - {at: 0.3, is: 'polygon(50px 70%, 90px 110%)'}, - {at: 0.6, is: 'polygon(80px 100%, 120px 140%)'}, - {at: 1, is: 'polygon(120px 140%, 160px 180%)'}, - {at: 1.5, is: 'polygon(170px 190%, 210px 230%)'}, -]); - -assertComposition({ - property: 'shape-outside', - underlying: 'polygon(evenodd, 10px 20px)', - addFrom: 'polygon(evenodd, 10px 20px)', - addTo: 'polygon(evenodd, 110px 120px)', -}, [ - {at: -0.3, is: 'polygon(evenodd, -10px 10px)'}, - {at: 0, is: 'polygon(evenodd, 20px 40px)'}, - {at: 0.3, is: 'polygon(evenodd, 50px 70px)'}, - {at: 0.6, is: 'polygon(evenodd, 80px 100px)'}, - {at: 1, is: 'polygon(evenodd, 120px 140px)'}, - {at: 1.5, is: 'polygon(evenodd, 170px 190px)'}, -]); - -assertComposition({ - property: 'shape-outside', - underlying: 'polygon(evenodd, 10px 20px)', - addFrom: 'polygon(evenodd, 10px 20px)', - addTo: 'polygon(nonzero, 30px 40px)', -}, [ - {at: 0.25, is: 'polygon(evenodd, 20px 40px)'}, - {at: 0.75, is: 'polygon(30px 40px)'}, -]); - -assertComposition({ - property: 'shape-outside', - underlying: 'polygon(10px 20px, 30px 40px)', - addFrom: 'polygon(10px 20px, 30px 40px)', - addTo: 'polygon(30px 40px)', -}, [ - {at: 0.25, is: 'polygon(20px 40px, 60px 80px)'}, - {at: 0.75, is: 'polygon(30px 40px)'}, -]); -</script> -</body>
diff --git a/third_party/blink/web_tests/animations/composition/width-composition.html b/third_party/blink/web_tests/animations/composition/width-composition.html deleted file mode 100644 index 8508886..0000000 --- a/third_party/blink/web_tests/animations/composition/width-composition.html +++ /dev/null
@@ -1,71 +0,0 @@ -<!DOCTYPE html> -<meta charset="UTF-8"> -<body> -<script src="../interpolation/resources/interpolation-test.js"></script> -<script> -assertComposition({ - property: 'width', - underlying: '50px', - addFrom: '100px', - addTo: '200px', -}, [ - {at: -0.3, is: '120px'}, - {at: 0, is: '150px'}, - {at: 0.5, is: '200px'}, - {at: 1, is: '250px'}, - {at: 1.5, is: '300px'}, -]); - -assertComposition({ - property: 'width', - underlying: '100px', - addFrom: '10px', - addTo: '2px', -}, [ - {at: -0.5, is: '114px'}, - {at: 0, is: '110px'}, - {at: 0.5, is: '106px'}, - {at: 1, is: '102px'}, - {at: 1.5, is: '98px'}, // Value clamping should happen after composition. -]); - -assertComposition({ - property: 'width', - underlying: '10%', - addFrom: '100px', - addTo: '20%', -}, [ - {at: -0.3, is: 'calc(130px + 4%)'}, - {at: 0, is: 'calc(100px + 10%)'}, - {at: 0.5, is: 'calc(50px + 20%)'}, - {at: 1, is: '30%'}, - {at: 1.5, is: 'calc(-50px + 40%)'}, -]); - -assertComposition({ - property: 'width', - underlying: '50px', - addFrom: '100px', - replaceTo: '200px', -}, [ - {at: -0.3, is: '135px'}, - {at: 0, is: '150px'}, - {at: 0.5, is: '175px'}, - {at: 1, is: '200px'}, - {at: 1.5, is: '225px'}, -]); - -assertComposition({ - property: 'width', - underlying: '100px', - addFrom: '100px', - addTo: 'auto', -}, [ - {at: -0.3, is: '200px'}, - {at: 0, is: '200px'}, - {at: 0.5, is: 'auto'}, - {at: 1, is: 'auto'}, - {at: 1.5, is: 'auto'}, -]); -</script> -</body>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-align/animation/column-gap-composition.html b/third_party/blink/web_tests/external/wpt/css/css-align/animation/column-gap-composition.html new file mode 100644 index 0000000..0054206c --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-align/animation/column-gap-composition.html
@@ -0,0 +1,65 @@ +<!DOCTYPE html> +<meta charset="UTF-8"> +<title>column-gap composition</title> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-column-gap"> +<meta name="assert" content="column-gap supports animation by computed value type"> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/css/support/interpolation-testcommon.js"></script> + +<body> +<script> +test_composition({ + property: 'column-gap', + underlying: '50px', + addFrom: '100px', + addTo: '200px', +}, [ + {at: -0.3, expect: '120px'}, + {at: 0, expect: '150px'}, + {at: 0.5, expect: '200px'}, + {at: 1, expect: '250px'}, + {at: 1.5, expect: '300px'}, +]); + +test_composition({ + property: 'column-gap', + underlying: '100px', + addFrom: '10px', + addTo: '2px', +}, [ + {at: -0.5, expect: '114px'}, + {at: 0, expect: '110px'}, + {at: 0.5, expect: '106px'}, + {at: 1, expect: '102px'}, + {at: 1.5, expect: '98px'}, // Value clamping should happen after composition. +]); + +test_composition({ + property: 'column-gap', + underlying: '50px', + addFrom: '100px', + replaceTo: '200px', +}, [ + {at: -0.3, expect: '135px'}, + {at: 0, expect: '150px'}, + {at: 0.5, expect: '175px'}, + {at: 1, expect: '200px'}, + {at: 1.5, expect: '225px'}, +]); + +test_composition({ + property: 'column-gap', + underlying: '100px', + addFrom: '100px', + addTo: 'normal', +}, [ + {at: -0.3, expect: '200px'}, + {at: 0, expect: '200px'}, + {at: 0.5, expect: 'normal'}, + {at: 1, expect: 'normal'}, + {at: 1.5, expect: 'normal'}, +]); +</script> +</body>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-align/animation/row-gap-composition.html b/third_party/blink/web_tests/external/wpt/css/css-align/animation/row-gap-composition.html new file mode 100644 index 0000000..238253a --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-align/animation/row-gap-composition.html
@@ -0,0 +1,65 @@ +<!DOCTYPE html> +<meta charset="UTF-8"> +<title>row-gap composition</title> +<link rel="help" href="https://drafts.csswg.org/css-align-3/#propdef-row-gap"> +<meta name="assert" content="row-gap supports animation by computed value type"> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/css/support/interpolation-testcommon.js"></script> + +<body> +<script> +test_composition({ + property: 'row-gap', + underlying: '50px', + addFrom: '100px', + addTo: '200px', +}, [ + {at: -0.3, expect: '120px'}, + {at: 0, expect: '150px'}, + {at: 0.5, expect: '200px'}, + {at: 1, expect: '250px'}, + {at: 1.5, expect: '300px'}, +]); + +test_composition({ + property: 'row-gap', + underlying: '100px', + addFrom: '10px', + addTo: '2px', +}, [ + {at: -0.5, expect: '114px'}, + {at: 0, expect: '110px'}, + {at: 0.5, expect: '106px'}, + {at: 1, expect: '102px'}, + {at: 1.5, expect: '98px'}, // Value clamping should happen after composition. +]); + +test_composition({ + property: 'row-gap', + underlying: '50px', + addFrom: '100px', + replaceTo: '200px', +}, [ + {at: -0.3, expect: '135px'}, + {at: 0, expect: '150px'}, + {at: 0.5, expect: '175px'}, + {at: 1, expect: '200px'}, + {at: 1.5, expect: '225px'}, +]); + +test_composition({ + property: 'row-gap', + underlying: '100px', + addFrom: '100px', + addTo: 'normal', +}, [ + {at: -0.3, expect: '200px'}, + {at: 0, expect: '200px'}, + {at: 0.5, expect: 'normal'}, + {at: 1, expect: 'normal'}, + {at: 1.5, expect: 'normal'}, +]); +</script> +</body>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-box/animation/margin-bottom-composition.html b/third_party/blink/web_tests/external/wpt/css/css-box/animation/margin-bottom-composition.html new file mode 100644 index 0000000..c95f8de2 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-box/animation/margin-bottom-composition.html
@@ -0,0 +1,78 @@ +<!DOCTYPE html> +<meta charset="UTF-8"> +<title>margin-bottom composition</title> +<link rel="help" href="https://www.w3.org/TR/CSS2/box.html#margin-properties"> +<meta name="assert" content="margin-bottom supports animation"> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/css/support/interpolation-testcommon.js"></script> + +<body> +<script> +test_composition({ + property: 'margin-bottom', + underlying: '50px', + addFrom: '100px', + addTo: '200px', +}, [ + {at: -0.3, expect: '120px'}, + {at: 0, expect: '150px'}, + {at: 0.5, expect: '200px'}, + {at: 1, expect: '250px'}, + {at: 1.5, expect: '300px'}, +]); + +test_composition({ + property: 'margin-bottom', + underlying: '100px', + addFrom: '10px', + addTo: '2px', +}, [ + {at: -0.5, expect: '114px'}, + {at: 0, expect: '110px'}, + {at: 0.5, expect: '106px'}, + {at: 1, expect: '102px'}, + {at: 1.5, expect: '98px'}, +]); + +test_composition({ + property: 'margin-bottom', + underlying: '10%', + addFrom: '100px', + addTo: '20%', +}, [ + {at: -0.3, expect: 'calc(130px + 4%)'}, + {at: 0, expect: 'calc(100px + 10%)'}, + {at: 0.5, expect: 'calc(50px + 20%)'}, + {at: 1, expect: '30%'}, + {at: 1.5, expect: 'calc(-50px + 40%)'}, +]); + +test_composition({ + property: 'margin-bottom', + underlying: '50px', + addFrom: '100px', + replaceTo: '200px', +}, [ + {at: -0.3, expect: '135px'}, + {at: 0, expect: '150px'}, + {at: 0.5, expect: '175px'}, + {at: 1, expect: '200px'}, + {at: 1.5, expect: '225px'}, +]); + +test_composition({ + property: 'margin-bottom', + underlying: '100px', + addFrom: '100px', + addTo: 'auto', +}, [ + {at: -0.3, expect: '200px'}, + {at: 0, expect: '200px'}, + {at: 0.5, expect: 'auto'}, + {at: 1, expect: 'auto'}, + {at: 1.5, expect: 'auto'}, +]); +</script> +</body>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-box/animation/margin-left-composition.html b/third_party/blink/web_tests/external/wpt/css/css-box/animation/margin-left-composition.html new file mode 100644 index 0000000..8f3c646 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-box/animation/margin-left-composition.html
@@ -0,0 +1,78 @@ +<!DOCTYPE html> +<meta charset="UTF-8"> +<title>margin-left composition</title> +<link rel="help" href="https://www.w3.org/TR/CSS2/box.html#margin-properties"> +<meta name="assert" content="margin-left supports animation"> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/css/support/interpolation-testcommon.js"></script> + +<body> +<script> +test_composition({ + property: 'margin-left', + underlying: '50px', + addFrom: '100px', + addTo: '200px', +}, [ + {at: -0.3, expect: '120px'}, + {at: 0, expect: '150px'}, + {at: 0.5, expect: '200px'}, + {at: 1, expect: '250px'}, + {at: 1.5, expect: '300px'}, +]); + +test_composition({ + property: 'margin-left', + underlying: '100px', + addFrom: '10px', + addTo: '2px', +}, [ + {at: -0.5, expect: '114px'}, + {at: 0, expect: '110px'}, + {at: 0.5, expect: '106px'}, + {at: 1, expect: '102px'}, + {at: 1.5, expect: '98px'}, +]); + +test_composition({ + property: 'margin-left', + underlying: '10%', + addFrom: '100px', + addTo: '20%', +}, [ + {at: -0.3, expect: 'calc(130px + 4%)'}, + {at: 0, expect: 'calc(100px + 10%)'}, + {at: 0.5, expect: 'calc(50px + 20%)'}, + {at: 1, expect: '30%'}, + {at: 1.5, expect: 'calc(-50px + 40%)'}, +]); + +test_composition({ + property: 'margin-left', + underlying: '50px', + addFrom: '100px', + replaceTo: '200px', +}, [ + {at: -0.3, expect: '135px'}, + {at: 0, expect: '150px'}, + {at: 0.5, expect: '175px'}, + {at: 1, expect: '200px'}, + {at: 1.5, expect: '225px'}, +]); + +test_composition({ + property: 'margin-left', + underlying: '100px', + addFrom: '100px', + addTo: 'auto', +}, [ + {at: -0.3, expect: '200px'}, + {at: 0, expect: '200px'}, + {at: 0.5, expect: 'auto'}, + {at: 1, expect: 'auto'}, + {at: 1.5, expect: 'auto'}, +]); +</script> +</body>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-box/animation/margin-right-composition.html b/third_party/blink/web_tests/external/wpt/css/css-box/animation/margin-right-composition.html new file mode 100644 index 0000000..c9033033 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-box/animation/margin-right-composition.html
@@ -0,0 +1,78 @@ +<!DOCTYPE html> +<meta charset="UTF-8"> +<title>margin-right composition</title> +<link rel="help" href="https://www.w3.org/TR/CSS2/box.html#margin-properties"> +<meta name="assert" content="margin-right supports animation"> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/css/support/interpolation-testcommon.js"></script> + +<body> +<script> +test_composition({ + property: 'margin-right', + underlying: '50px', + addFrom: '100px', + addTo: '200px', +}, [ + {at: -0.3, expect: '120px'}, + {at: 0, expect: '150px'}, + {at: 0.5, expect: '200px'}, + {at: 1, expect: '250px'}, + {at: 1.5, expect: '300px'}, +]); + +test_composition({ + property: 'margin-right', + underlying: '100px', + addFrom: '10px', + addTo: '2px', +}, [ + {at: -0.5, expect: '114px'}, + {at: 0, expect: '110px'}, + {at: 0.5, expect: '106px'}, + {at: 1, expect: '102px'}, + {at: 1.5, expect: '98px'}, +]); + +test_composition({ + property: 'margin-right', + underlying: '10%', + addFrom: '100px', + addTo: '20%', +}, [ + {at: -0.3, expect: 'calc(130px + 4%)'}, + {at: 0, expect: 'calc(100px + 10%)'}, + {at: 0.5, expect: 'calc(50px + 20%)'}, + {at: 1, expect: '30%'}, + {at: 1.5, expect: 'calc(-50px + 40%)'}, +]); + +test_composition({ + property: 'margin-right', + underlying: '50px', + addFrom: '100px', + replaceTo: '200px', +}, [ + {at: -0.3, expect: '135px'}, + {at: 0, expect: '150px'}, + {at: 0.5, expect: '175px'}, + {at: 1, expect: '200px'}, + {at: 1.5, expect: '225px'}, +]); + +test_composition({ + property: 'margin-right', + underlying: '100px', + addFrom: '100px', + addTo: 'auto', +}, [ + {at: -0.3, expect: '200px'}, + {at: 0, expect: '200px'}, + {at: 0.5, expect: 'auto'}, + {at: 1, expect: 'auto'}, + {at: 1.5, expect: 'auto'}, +]); +</script> +</body>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-box/animation/margin-top-composition.html b/third_party/blink/web_tests/external/wpt/css/css-box/animation/margin-top-composition.html new file mode 100644 index 0000000..5f050bd --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-box/animation/margin-top-composition.html
@@ -0,0 +1,78 @@ +<!DOCTYPE html> +<meta charset="UTF-8"> +<title>margin-top composition</title> +<link rel="help" href="https://www.w3.org/TR/CSS2/box.html#margin-properties"> +<meta name="assert" content="margin-top supports animation"> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/css/support/interpolation-testcommon.js"></script> + +<body> +<script> +test_composition({ + property: 'margin-top', + underlying: '50px', + addFrom: '100px', + addTo: '200px', +}, [ + {at: -0.3, expect: '120px'}, + {at: 0, expect: '150px'}, + {at: 0.5, expect: '200px'}, + {at: 1, expect: '250px'}, + {at: 1.5, expect: '300px'}, +]); + +test_composition({ + property: 'margin-top', + underlying: '100px', + addFrom: '10px', + addTo: '2px', +}, [ + {at: -0.5, expect: '114px'}, + {at: 0, expect: '110px'}, + {at: 0.5, expect: '106px'}, + {at: 1, expect: '102px'}, + {at: 1.5, expect: '98px'}, +]); + +test_composition({ + property: 'margin-top', + underlying: '10%', + addFrom: '100px', + addTo: '20%', +}, [ + {at: -0.3, expect: 'calc(130px + 4%)'}, + {at: 0, expect: 'calc(100px + 10%)'}, + {at: 0.5, expect: 'calc(50px + 20%)'}, + {at: 1, expect: '30%'}, + {at: 1.5, expect: 'calc(-50px + 40%)'}, +]); + +test_composition({ + property: 'margin-top', + underlying: '50px', + addFrom: '100px', + replaceTo: '200px', +}, [ + {at: -0.3, expect: '135px'}, + {at: 0, expect: '150px'}, + {at: 0.5, expect: '175px'}, + {at: 1, expect: '200px'}, + {at: 1.5, expect: '225px'}, +]); + +test_composition({ + property: 'margin-top', + underlying: '100px', + addFrom: '100px', + addTo: 'auto', +}, [ + {at: -0.3, expect: '200px'}, + {at: 0, expect: '200px'}, + {at: 0.5, expect: 'auto'}, + {at: 1, expect: 'auto'}, + {at: 1.5, expect: 'auto'}, +]); +</script> +</body>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-box/animation/padding-bottom-composition.html b/third_party/blink/web_tests/external/wpt/css/css-box/animation/padding-bottom-composition.html new file mode 100644 index 0000000..855b5d3d --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-box/animation/padding-bottom-composition.html
@@ -0,0 +1,65 @@ +<!DOCTYPE html> +<meta charset="UTF-8"> +<title>padding-bottom composition</title> +<link rel="help" href="https://drafts.csswg.org/css-box-3/#padding-shorthand"> +<meta name="assert" content="padding-bottom supports animation as a list of lengths"> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/css/support/interpolation-testcommon.js"></script> + +<body> +<script> +test_composition({ + property: 'padding-bottom', + underlying: '50px', + addFrom: '100px', + addTo: '200px', +}, [ + {at: -0.3, expect: '120px'}, + {at: 0, expect: '150px'}, + {at: 0.5, expect: '200px'}, + {at: 1, expect: '250px'}, + {at: 1.5, expect: '300px'}, +]); + +test_composition({ + property: 'padding-bottom', + underlying: '100px', + addFrom: '10px', + addTo: '2px', +}, [ + {at: -0.5, expect: '114px'}, + {at: 0, expect: '110px'}, + {at: 0.5, expect: '106px'}, + {at: 1, expect: '102px'}, + {at: 1.5, expect: '98px'}, // Value clamping should happen after composition. +]); + +test_composition({ + property: 'padding-bottom', + underlying: '10%', + addFrom: '100px', + addTo: '20%', +}, [ + {at: -0.3, expect: 'calc(130px + 4%)'}, + {at: 0, expect: 'calc(100px + 10%)'}, + {at: 0.5, expect: 'calc(50px + 20%)'}, + {at: 1, expect: '30%'}, + {at: 1.5, expect: 'calc(-50px + 40%)'}, +]); + +test_composition({ + property: 'padding-bottom', + underlying: '50px', + addFrom: '100px', + replaceTo: '200px', +}, [ + {at: -0.3, expect: '135px'}, + {at: 0, expect: '150px'}, + {at: 0.5, expect: '175px'}, + {at: 1, expect: '200px'}, + {at: 1.5, expect: '225px'}, +]); +</script> +</body>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-box/animation/padding-left-composition.html b/third_party/blink/web_tests/external/wpt/css/css-box/animation/padding-left-composition.html new file mode 100644 index 0000000..417777ae --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-box/animation/padding-left-composition.html
@@ -0,0 +1,65 @@ +<!DOCTYPE html> +<meta charset="UTF-8"> +<title>padding-left composition</title> +<link rel="help" href="https://drafts.csswg.org/css-box-3/#padding-shorthand"> +<meta name="assert" content="padding-left supports animation as a list of lengths"> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/css/support/interpolation-testcommon.js"></script> + +<body> +<script> +test_composition({ + property: 'padding-left', + underlying: '50px', + addFrom: '100px', + addTo: '200px', +}, [ + {at: -0.3, expect: '120px'}, + {at: 0, expect: '150px'}, + {at: 0.5, expect: '200px'}, + {at: 1, expect: '250px'}, + {at: 1.5, expect: '300px'}, +]); + +test_composition({ + property: 'padding-left', + underlying: '100px', + addFrom: '10px', + addTo: '2px', +}, [ + {at: -0.5, expect: '114px'}, + {at: 0, expect: '110px'}, + {at: 0.5, expect: '106px'}, + {at: 1, expect: '102px'}, + {at: 1.5, expect: '98px'}, // Value clamping should happen after composition. +]); + +test_composition({ + property: 'padding-left', + underlying: '10%', + addFrom: '100px', + addTo: '20%', +}, [ + {at: -0.3, expect: 'calc(130px + 4%)'}, + {at: 0, expect: 'calc(100px + 10%)'}, + {at: 0.5, expect: 'calc(50px + 20%)'}, + {at: 1, expect: '30%'}, + {at: 1.5, expect: 'calc(-50px + 40%)'}, +]); + +test_composition({ + property: 'padding-left', + underlying: '50px', + addFrom: '100px', + replaceTo: '200px', +}, [ + {at: -0.3, expect: '135px'}, + {at: 0, expect: '150px'}, + {at: 0.5, expect: '175px'}, + {at: 1, expect: '200px'}, + {at: 1.5, expect: '225px'}, +]); +</script> +</body>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-box/animation/padding-right-composition.html b/third_party/blink/web_tests/external/wpt/css/css-box/animation/padding-right-composition.html new file mode 100644 index 0000000..3c80849b --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-box/animation/padding-right-composition.html
@@ -0,0 +1,65 @@ +<!DOCTYPE html> +<meta charset="UTF-8"> +<title>padding-right composition</title> +<link rel="help" href="https://drafts.csswg.org/css-box-3/#padding-shorthand"> +<meta name="assert" content="padding-right supports animation as a list of lengths"> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/css/support/interpolation-testcommon.js"></script> + +<body> +<script> +test_composition({ + property: 'padding-right', + underlying: '50px', + addFrom: '100px', + addTo: '200px', +}, [ + {at: -0.3, expect: '120px'}, + {at: 0, expect: '150px'}, + {at: 0.5, expect: '200px'}, + {at: 1, expect: '250px'}, + {at: 1.5, expect: '300px'}, +]); + +test_composition({ + property: 'padding-right', + underlying: '100px', + addFrom: '10px', + addTo: '2px', +}, [ + {at: -0.5, expect: '114px'}, + {at: 0, expect: '110px'}, + {at: 0.5, expect: '106px'}, + {at: 1, expect: '102px'}, + {at: 1.5, expect: '98px'}, // Value clamping should happen after composition. +]); + +test_composition({ + property: 'padding-right', + underlying: '10%', + addFrom: '100px', + addTo: '20%', +}, [ + {at: -0.3, expect: 'calc(130px + 4%)'}, + {at: 0, expect: 'calc(100px + 10%)'}, + {at: 0.5, expect: 'calc(50px + 20%)'}, + {at: 1, expect: '30%'}, + {at: 1.5, expect: 'calc(-50px + 40%)'}, +]); + +test_composition({ + property: 'padding-right', + underlying: '50px', + addFrom: '100px', + replaceTo: '200px', +}, [ + {at: -0.3, expect: '135px'}, + {at: 0, expect: '150px'}, + {at: 0.5, expect: '175px'}, + {at: 1, expect: '200px'}, + {at: 1.5, expect: '225px'}, +]); +</script> +</body>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-box/animation/padding-top-composition.html b/third_party/blink/web_tests/external/wpt/css/css-box/animation/padding-top-composition.html new file mode 100644 index 0000000..b5083ae --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-box/animation/padding-top-composition.html
@@ -0,0 +1,65 @@ +<!DOCTYPE html> +<meta charset="UTF-8"> +<title>padding-top composition</title> +<link rel="help" href="https://drafts.csswg.org/css-box-3/#padding-shorthand"> +<meta name="assert" content="padding-top supports animation as a list of lengths"> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/css/support/interpolation-testcommon.js"></script> + +<body> +<script> +test_composition({ + property: 'padding-top', + underlying: '50px', + addFrom: '100px', + addTo: '200px', +}, [ + {at: -0.3, expect: '120px'}, + {at: 0, expect: '150px'}, + {at: 0.5, expect: '200px'}, + {at: 1, expect: '250px'}, + {at: 1.5, expect: '300px'}, +]); + +test_composition({ + property: 'padding-top', + underlying: '100px', + addFrom: '10px', + addTo: '2px', +}, [ + {at: -0.5, expect: '114px'}, + {at: 0, expect: '110px'}, + {at: 0.5, expect: '106px'}, + {at: 1, expect: '102px'}, + {at: 1.5, expect: '98px'}, // Value clamping should happen after composition. +]); + +test_composition({ + property: 'padding-top', + underlying: '10%', + addFrom: '100px', + addTo: '20%', +}, [ + {at: -0.3, expect: 'calc(130px + 4%)'}, + {at: 0, expect: 'calc(100px + 10%)'}, + {at: 0.5, expect: 'calc(50px + 20%)'}, + {at: 1, expect: '30%'}, + {at: 1.5, expect: 'calc(-50px + 40%)'}, +]); + +test_composition({ + property: 'padding-top', + underlying: '50px', + addFrom: '100px', + replaceTo: '200px', +}, [ + {at: -0.3, expect: '135px'}, + {at: 0, expect: '150px'}, + {at: 0.5, expect: '175px'}, + {at: 1, expect: '200px'}, + {at: 1.5, expect: '225px'}, +]); +</script> +</body>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-shapes/animation/shape-margin-composition.html b/third_party/blink/web_tests/external/wpt/css/css-shapes/animation/shape-margin-composition.html new file mode 100644 index 0000000..395bad0 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-shapes/animation/shape-margin-composition.html
@@ -0,0 +1,65 @@ +<!DOCTYPE html> +<meta charset="UTF-8"> +<title>shape-margin composition</title> +<link rel="help" href="https://drafts.csswg.org/css-shapes/#shape-margin-property"> +<meta name="assert" content="shape-margin supports animation by computed value"> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/css/support/interpolation-testcommon.js"></script> + +<body> +<script> +test_composition({ + property: 'shape-margin', + underlying: '50px', + addFrom: '100px', + addTo: '200px', +}, [ + {at: -0.3, expect: '120px'}, + {at: 0, expect: '150px'}, + {at: 0.5, expect: '200px'}, + {at: 1, expect: '250px'}, + {at: 1.5, expect: '300px'}, +]); + +test_composition({ + property: 'shape-margin', + underlying: '100px', + addFrom: '10px', + addTo: '2px', +}, [ + {at: -0.5, expect: '114px'}, + {at: 0, expect: '110px'}, + {at: 0.5, expect: '106px'}, + {at: 1, expect: '102px'}, + {at: 1.5, expect: '98px'}, // Value clamping should happen after composition. +]); + +test_composition({ + property: 'shape-margin', + underlying: '10%', + addFrom: '100px', + addTo: '20%', +}, [ + {at: -0.3, expect: 'calc(130px + 4%)'}, + {at: 0, expect: 'calc(100px + 10%)'}, + {at: 0.5, expect: 'calc(50px + 20%)'}, + {at: 1, expect: '30%'}, + {at: 1.5, expect: 'calc(-50px + 40%)'}, +]); + +test_composition({ + property: 'shape-margin', + underlying: '50px', + addFrom: '100px', + replaceTo: '200px', +}, [ + {at: -0.3, expect: '135px'}, + {at: 0, expect: '150px'}, + {at: 0.5, expect: '175px'}, + {at: 1, expect: '200px'}, + {at: 1.5, expect: '225px'}, +]); +</script> +</body>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-shapes/animation/shape-outside-composition.html b/third_party/blink/web_tests/external/wpt/css/css-shapes/animation/shape-outside-composition.html new file mode 100644 index 0000000..0115148e --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-shapes/animation/shape-outside-composition.html
@@ -0,0 +1,189 @@ +<!DOCTYPE html> +<meta charset="UTF-8"> +<title>shape-outside composition</title> +<link rel="help" href="https://drafts.csswg.org/css-shapes/#shape-outside-property"> +<meta name="assert" content="shape-outside supports animation as <basic-shape> or discrete"> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/css/support/interpolation-testcommon.js"></script> + +<body> +<script> +test_composition({ + property: 'shape-outside', + underlying: 'circle(100px at 25px 25%)', + addFrom: 'circle(10px at 25px 75%)', + addTo: 'circle(50px at 50px center)', +}, [ + {at: -0.3, expect: 'circle(98px at 42.5px 107.5%)'}, + {at: 0, expect: 'circle(110px at 50px 100%)'}, + {at: 0.3, expect: 'circle(122px at 57.5px 92.5%)'}, + {at: 0.6, expect: 'circle(134px at 65px 85%)'}, + {at: 1, expect: 'circle(150px at 75px 75%)'}, + {at: 1.5, expect: 'circle(170px at 87.5px 62.5%)'}, +]); + +test_composition({ + property: 'shape-outside', + underlying: 'circle(100px at 20px 20%)', + addFrom: 'circle(50px at 50px 50%)', + replaceTo: 'circle(50% at 150px 150%)', +}, [ + {at: -0.3, expect: 'circle(calc(195px + -15%) at 46px 46%)'}, + {at: 0, expect: 'circle(calc(150px + 0%) at 70px 70%)'}, + {at: 0.3, expect: 'circle(calc(105px + 15%) at 94px 94%)'}, + {at: 0.6, expect: 'circle(calc(60px + 30%) at 118px 118%)'}, + {at: 1, expect: 'circle(50% at 150px 150%)'}, + {at: 1.5, expect: 'circle(calc(-75px + 75%) at 190px 190%)'}, +]); + +test_composition({ + property: 'shape-outside', + underlying: 'circle(farthest-side at 25px 75%)', + addFrom: 'circle(farthest-side at 25px 75%)', + addTo: 'circle(farthest-side at 50px center)', +}, [ + {at: 0.25, expect: 'circle(farthest-side at 25px 75%)'}, + {at: 0.75, expect: 'circle(farthest-side at 50px 50%)'}, +]); + +test_composition({ + property: 'shape-outside', + underlying: 'circle(50px at 10px 20px)', + addFrom: 'circle(50px at 10px 20px)', + addTo: 'circle(farthest-side at 30px 40px)', +}, [ + {at: 0.25, expect: 'circle(100px at 20px 40px)'}, + {at: 0.75, expect: 'circle(farthest-side at 30px 40px)'}, +]); + +test_composition({ + property: 'shape-outside', + underlying: 'ellipse(10px 20px at 30px 40px)', + addFrom: 'ellipse(40px 30px at 20px 10px)', + addTo: 'ellipse(140px 130px at 120px 110px)', +}, [ + {at: -0.3, expect: 'ellipse(20px 20px at 20px 20px)'}, + {at: 0, expect: 'ellipse(50px 50px at 50px 50px)'}, + {at: 0.3, expect: 'ellipse(80px 80px at 80px 80px)'}, + {at: 0.6, expect: 'ellipse(110px 110px at 110px 110px)'}, + {at: 1, expect: 'ellipse(150px 150px at 150px 150px)'}, + {at: 1.5, expect: 'ellipse(200px 200px at 200px 200px)'}, +]); + +test_composition({ + property: 'shape-outside', + underlying: 'ellipse(10px 20px at 30px 40px)', + replaceFrom: 'ellipse(40px 30px at 20px 10px)', + addTo: 'ellipse(40px 30px at 20px 10px)', +}, [ + {at: -0.3, expect: 'ellipse(37px 24px at 11px -2px)'}, + {at: 0, expect: 'ellipse(40px 30px at 20px 10px)'}, + {at: 0.3, expect: 'ellipse(43px 36px at 29px 22px)'}, + {at: 0.6, expect: 'ellipse(46px 42px at 38px 34px)'}, + {at: 1, expect: 'ellipse(50px 50px at 50px 50px)'}, + {at: 1.5, expect: 'ellipse(55px 60px at 65px 70px)'}, +]); + +test_composition({ + property: 'shape-outside', + underlying: 'ellipse(25px 75%)', + addFrom: 'ellipse()', + addTo: 'ellipse(closest-side farthest-side)', +}, [ + {at: 0.25, expect: 'ellipse(at 50% 50%)'}, + {at: 0.75, expect: 'ellipse(closest-side farthest-side at 50% 50%)'}, +]); + +test_composition({ + property: 'shape-outside', + underlying: 'inset(20px)', + addFrom: 'inset(20px)', + addTo: 'inset(40%)', +}, [ + {at: -0.3, expect: 'inset(calc(46px + -12%))'}, + {at: 0, expect: 'inset(calc(40px + 0%))'}, + {at: 0.3, expect: 'inset(calc(34px + 12%))'}, + {at: 0.6, expect: 'inset(calc(28px + 24%))'}, + {at: 1, expect: 'inset(calc(20px + 40%))'}, + {at: 1.5, expect: 'inset(calc(10px + 60%))'}, +]); + +test_composition({ + property: 'shape-outside', + underlying: 'inset(1px 2px 3px 4px round 10px 20px 30px 40px / 50px 60px 70px 80px)', + addFrom: 'inset(1px 2px 3px 4px round 10px 20px 30px 40px / 50px 60px 70px 80px)', + replaceTo: 'inset(102px 104px 106px 108px round 120px 140px 160px 180px / 200px 220px 240px 260px)', +}, [ + {at: -0.3, expect: 'inset(-28px -26px -24px -22px round 0px 10px 30px 50px / 70px 90px 110px 130px)'}, + {at: 0, expect: 'inset(2px 4px 6px 8px round 20px 40px 60px 80px / 100px 120px 140px 160px)'}, + {at: 0.25, expect: 'inset(27px 29px 31px 33px round 45px 65px 85px 105px / 125px 145px 165px 185px)'}, + {at: 0.75, expect: 'inset(77px 79px 81px 83px round 95px 115px 135px 155px / 175px 195px 215px 235px)'}, + {at: 1, expect: 'inset(102px 104px 106px 108px round 120px 140px 160px 180px / 200px 220px 240px 260px)'}, + {at: 1.5, expect: 'inset(152px 154px 156px 158px round 170px 190px 210px 230px / 250px 270px 290px 310px)'}, +]); + +test_composition({ + property: 'shape-outside', + underlying: 'inset(1px 2px round 100px 200px)', + addFrom: 'inset(1px 2px round 100px 200px)', + addTo: 'inset(101px 102px 101px 102px)', +}, [ + {at: -0.3, expect: 'inset(-28px -26px round 230px 460px)'}, + {at: 0, expect: 'inset(2px 4px round 200px 400px)'}, + {at: 0.3, expect: 'inset(32px 34px round 170px 340px)'}, + {at: 0.6, expect: 'inset(62px 64px round 140px 280px)'}, + {at: 1, expect: 'inset(102px 104px round 100px 200px)'}, + {at: 1.5, expect: 'inset(152px 154px round 50px 100px)'}, +]); + +test_composition({ + property: 'shape-outside', + underlying: 'polygon(10px 20%, 30px 40%)', + addFrom: 'polygon(10px 20%, 30px 40%)', + addTo: 'polygon(110px 120%, 130px 140%)', +}, [ + {at: -0.3, expect: 'polygon(-10px 10%, 30px 50%)'}, + {at: 0, expect: 'polygon(20px 40%, 60px 80%)'}, + {at: 0.3, expect: 'polygon(50px 70%, 90px 110%)'}, + {at: 0.6, expect: 'polygon(80px 100%, 120px 140%)'}, + {at: 1, expect: 'polygon(120px 140%, 160px 180%)'}, + {at: 1.5, expect: 'polygon(170px 190%, 210px 230%)'}, +]); + +test_composition({ + property: 'shape-outside', + underlying: 'polygon(evenodd, 10px 20px)', + addFrom: 'polygon(evenodd, 10px 20px)', + addTo: 'polygon(evenodd, 110px 120px)', +}, [ + {at: -0.3, expect: 'polygon(evenodd, -10px 10px)'}, + {at: 0, expect: 'polygon(evenodd, 20px 40px)'}, + {at: 0.3, expect: 'polygon(evenodd, 50px 70px)'}, + {at: 0.6, expect: 'polygon(evenodd, 80px 100px)'}, + {at: 1, expect: 'polygon(evenodd, 120px 140px)'}, + {at: 1.5, expect: 'polygon(evenodd, 170px 190px)'}, +]); + +test_composition({ + property: 'shape-outside', + underlying: 'polygon(evenodd, 10px 20px)', + addFrom: 'polygon(evenodd, 10px 20px)', + addTo: 'polygon(nonzero, 30px 40px)', +}, [ + {at: 0.25, expect: 'polygon(evenodd, 20px 40px)'}, + {at: 0.75, expect: 'polygon(30px 40px)'}, +]); + +test_composition({ + property: 'shape-outside', + underlying: 'polygon(10px 20px, 30px 40px)', + addFrom: 'polygon(10px 20px, 30px 40px)', + addTo: 'polygon(30px 40px)', +}, [ + {at: 0.25, expect: 'polygon(20px 40px, 60px 80px)'}, + {at: 0.75, expect: 'polygon(30px 40px)'}, +]); +</script> +</body>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-sizing/animation/height-composition.html b/third_party/blink/web_tests/external/wpt/css/css-sizing/animation/height-composition.html new file mode 100644 index 0000000..094e247 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-sizing/animation/height-composition.html
@@ -0,0 +1,78 @@ +<!DOCTYPE html> +<meta charset="UTF-8"> +<title>height composition</title> +<link rel="help" href="https://drafts.csswg.org/css-sizing-3/#propdef-height"> +<meta name="assert" content="height supports animation by computed value"> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/css/support/interpolation-testcommon.js"></script> + +<body> +<script> +test_composition({ + property: 'height', + underlying: '50px', + addFrom: '100px', + addTo: '200px', +}, [ + {at: -0.3, expect: '120px'}, + {at: 0, expect: '150px'}, + {at: 0.5, expect: '200px'}, + {at: 1, expect: '250px'}, + {at: 1.5, expect: '300px'}, +]); + +test_composition({ + property: 'height', + underlying: '100px', + addFrom: '10px', + addTo: '2px', +}, [ + {at: -0.5, expect: '114px'}, + {at: 0, expect: '110px'}, + {at: 0.5, expect: '106px'}, + {at: 1, expect: '102px'}, + {at: 1.5, expect: '98px'}, // Value clamping should happen after composition. +]); + +test_composition({ + property: 'height', + underlying: '10%', + addFrom: '100px', + addTo: '20%', +}, [ + {at: -0.3, expect: 'calc(130px + 4%)'}, + {at: 0, expect: 'calc(100px + 10%)'}, + {at: 0.5, expect: 'calc(50px + 20%)'}, + {at: 1, expect: '30%'}, + {at: 1.5, expect: 'calc(-50px + 40%)'}, +]); + +test_composition({ + property: 'height', + underlying: '50px', + addFrom: '100px', + replaceTo: '200px', +}, [ + {at: -0.3, expect: '135px'}, + {at: 0, expect: '150px'}, + {at: 0.5, expect: '175px'}, + {at: 1, expect: '200px'}, + {at: 1.5, expect: '225px'}, +]); + +test_composition({ + property: 'height', + underlying: '100px', + addFrom: '100px', + addTo: 'auto', +}, [ + {at: -0.3, expect: '200px'}, + {at: 0, expect: '200px'}, + {at: 0.5, expect: 'auto'}, + {at: 1, expect: 'auto'}, + {at: 1.5, expect: 'auto'}, +]); +</script> +</body>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-sizing/animation/max-height-composition.html b/third_party/blink/web_tests/external/wpt/css/css-sizing/animation/max-height-composition.html new file mode 100644 index 0000000..fb5b241 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-sizing/animation/max-height-composition.html
@@ -0,0 +1,78 @@ +<!DOCTYPE html> +<meta charset="UTF-8"> +<title>max-height composition</title> +<link rel="help" href="https://drafts.csswg.org/css-sizing-3/#propdef-max-height"> +<meta name="assert" content="max-height supports animation by computed value"> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/css/support/interpolation-testcommon.js"></script> + +<body> +<script> +test_composition({ + property: 'max-height', + underlying: '50px', + addFrom: '100px', + addTo: '200px', +}, [ + {at: -0.3, expect: '120px'}, + {at: 0, expect: '150px'}, + {at: 0.5, expect: '200px'}, + {at: 1, expect: '250px'}, + {at: 1.5, expect: '300px'}, +]); + +test_composition({ + property: 'max-height', + underlying: '100px', + addFrom: '10px', + addTo: '2px', +}, [ + {at: -0.5, expect: '114px'}, + {at: 0, expect: '110px'}, + {at: 0.5, expect: '106px'}, + {at: 1, expect: '102px'}, + {at: 1.5, expect: '98px'}, // Value clamping should happen after composition. +]); + +test_composition({ + property: 'max-height', + underlying: '10%', + addFrom: '100px', + addTo: '20%', +}, [ + {at: -0.3, expect: 'calc(130px + 4%)'}, + {at: 0, expect: 'calc(100px + 10%)'}, + {at: 0.5, expect: 'calc(50px + 20%)'}, + {at: 1, expect: '30%'}, + {at: 1.5, expect: 'calc(-50px + 40%)'}, +]); + +test_composition({ + property: 'max-height', + underlying: '50px', + addFrom: '100px', + replaceTo: '200px', +}, [ + {at: -0.3, expect: '135px'}, + {at: 0, expect: '150px'}, + {at: 0.5, expect: '175px'}, + {at: 1, expect: '200px'}, + {at: 1.5, expect: '225px'}, +]); + +test_composition({ + property: 'max-height', + underlying: '100px', + addFrom: '100px', + addTo: 'none', +}, [ + {at: -0.3, expect: '200px'}, + {at: 0, expect: '200px'}, + {at: 0.5, expect: 'none'}, + {at: 1, expect: 'none'}, + {at: 1.5, expect: 'none'}, +]); +</script> +</body>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-sizing/animation/max-width-composition.html b/third_party/blink/web_tests/external/wpt/css/css-sizing/animation/max-width-composition.html new file mode 100644 index 0000000..8b6d8b7 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-sizing/animation/max-width-composition.html
@@ -0,0 +1,78 @@ +<!DOCTYPE html> +<meta charset="UTF-8"> +<title>max-width composition</title> +<link rel="help" href="https://drafts.csswg.org/css-sizing-3/#propdef-max-width"> +<meta name="assert" content="max-width supports animation by computed value"> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/css/support/interpolation-testcommon.js"></script> + +<body> +<script> +test_composition({ + property: 'max-width', + underlying: '50px', + addFrom: '100px', + addTo: '200px', +}, [ + {at: -0.3, expect: '120px'}, + {at: 0, expect: '150px'}, + {at: 0.5, expect: '200px'}, + {at: 1, expect: '250px'}, + {at: 1.5, expect: '300px'}, +]); + +test_composition({ + property: 'max-width', + underlying: '100px', + addFrom: '10px', + addTo: '2px', +}, [ + {at: -0.5, expect: '114px'}, + {at: 0, expect: '110px'}, + {at: 0.5, expect: '106px'}, + {at: 1, expect: '102px'}, + {at: 1.5, expect: '98px'}, // Value clamping should happen after composition. +]); + +test_composition({ + property: 'max-width', + underlying: '10%', + addFrom: '100px', + addTo: '20%', +}, [ + {at: -0.3, expect: 'calc(130px + 4%)'}, + {at: 0, expect: 'calc(100px + 10%)'}, + {at: 0.5, expect: 'calc(50px + 20%)'}, + {at: 1, expect: '30%'}, + {at: 1.5, expect: 'calc(-50px + 40%)'}, +]); + +test_composition({ + property: 'max-width', + underlying: '50px', + addFrom: '100px', + replaceTo: '200px', +}, [ + {at: -0.3, expect: '135px'}, + {at: 0, expect: '150px'}, + {at: 0.5, expect: '175px'}, + {at: 1, expect: '200px'}, + {at: 1.5, expect: '225px'}, +]); + +test_composition({ + property: 'max-width', + underlying: '100px', + addFrom: '100px', + addTo: 'none', +}, [ + {at: -0.3, expect: '200px'}, + {at: 0, expect: '200px'}, + {at: 0.5, expect: 'none'}, + {at: 1, expect: 'none'}, + {at: 1.5, expect: 'none'}, +]); +</script> +</body>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-sizing/animation/min-height-composition.html b/third_party/blink/web_tests/external/wpt/css/css-sizing/animation/min-height-composition.html new file mode 100644 index 0000000..1e92b0e --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-sizing/animation/min-height-composition.html
@@ -0,0 +1,78 @@ +<!DOCTYPE html> +<meta charset="UTF-8"> +<title>min-height composition</title> +<link rel="help" href="https://drafts.csswg.org/css-sizing-3/#propdef-min-height"> +<meta name="assert" content="min-height supports animation by computed value"> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/css/support/interpolation-testcommon.js"></script> + +<body> +<script> +test_composition({ + property: 'min-height', + underlying: '50px', + addFrom: '100px', + addTo: '200px', +}, [ + {at: -0.3, expect: '120px'}, + {at: 0, expect: '150px'}, + {at: 0.5, expect: '200px'}, + {at: 1, expect: '250px'}, + {at: 1.5, expect: '300px'}, +]); + +test_composition({ + property: 'min-height', + underlying: '100px', + addFrom: '10px', + addTo: '2px', +}, [ + {at: -0.5, expect: '114px'}, + {at: 0, expect: '110px'}, + {at: 0.5, expect: '106px'}, + {at: 1, expect: '102px'}, + {at: 1.5, expect: '98px'}, // Value clamping should happen after composition. +]); + +test_composition({ + property: 'min-height', + underlying: '10%', + addFrom: '100px', + addTo: '20%', +}, [ + {at: -0.3, expect: 'calc(130px + 4%)'}, + {at: 0, expect: 'calc(100px + 10%)'}, + {at: 0.5, expect: 'calc(50px + 20%)'}, + {at: 1, expect: '30%'}, + {at: 1.5, expect: 'calc(-50px + 40%)'}, +]); + +test_composition({ + property: 'min-height', + underlying: '50px', + addFrom: '100px', + replaceTo: '200px', +}, [ + {at: -0.3, expect: '135px'}, + {at: 0, expect: '150px'}, + {at: 0.5, expect: '175px'}, + {at: 1, expect: '200px'}, + {at: 1.5, expect: '225px'}, +]); + +test_composition({ + property: 'min-height', + underlying: '100px', + addFrom: '100px', + addTo: 'auto', +}, [ + {at: -0.3, expect: '200px'}, + {at: 0, expect: '200px'}, + {at: 0.5, expect: 'auto'}, + {at: 1, expect: 'auto'}, + {at: 1.5, expect: 'auto'}, +]); +</script> +</body>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-sizing/animation/min-width-composition.html b/third_party/blink/web_tests/external/wpt/css/css-sizing/animation/min-width-composition.html new file mode 100644 index 0000000..e8bd410 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-sizing/animation/min-width-composition.html
@@ -0,0 +1,78 @@ +<!DOCTYPE html> +<meta charset="UTF-8"> +<title>min-width composition</title> +<link rel="help" href="https://drafts.csswg.org/css-sizing-3/#propdef-min-width"> +<meta name="assert" content="min-width supports animation by computed value"> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/css/support/interpolation-testcommon.js"></script> + +<body> +<script> +test_composition({ + property: 'min-width', + underlying: '50px', + addFrom: '100px', + addTo: '200px', +}, [ + {at: -0.3, expect: '120px'}, + {at: 0, expect: '150px'}, + {at: 0.5, expect: '200px'}, + {at: 1, expect: '250px'}, + {at: 1.5, expect: '300px'}, +]); + +test_composition({ + property: 'min-width', + underlying: '100px', + addFrom: '10px', + addTo: '2px', +}, [ + {at: -0.5, expect: '114px'}, + {at: 0, expect: '110px'}, + {at: 0.5, expect: '106px'}, + {at: 1, expect: '102px'}, + {at: 1.5, expect: '98px'}, // Value clamping should happen after composition. +]); + +test_composition({ + property: 'min-width', + underlying: '10%', + addFrom: '100px', + addTo: '20%', +}, [ + {at: -0.3, expect: 'calc(130px + 4%)'}, + {at: 0, expect: 'calc(100px + 10%)'}, + {at: 0.5, expect: 'calc(50px + 20%)'}, + {at: 1, expect: '30%'}, + {at: 1.5, expect: 'calc(-50px + 40%)'}, +]); + +test_composition({ + property: 'min-width', + underlying: '50px', + addFrom: '100px', + replaceTo: '200px', +}, [ + {at: -0.3, expect: '135px'}, + {at: 0, expect: '150px'}, + {at: 0.5, expect: '175px'}, + {at: 1, expect: '200px'}, + {at: 1.5, expect: '225px'}, +]); + +test_composition({ + property: 'min-width', + underlying: '100px', + addFrom: '100px', + addTo: 'auto', +}, [ + {at: -0.3, expect: '200px'}, + {at: 0, expect: '200px'}, + {at: 0.5, expect: 'auto'}, + {at: 1, expect: 'auto'}, + {at: 1.5, expect: 'auto'}, +]); +</script> +</body>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-sizing/animation/width-composition.html b/third_party/blink/web_tests/external/wpt/css/css-sizing/animation/width-composition.html new file mode 100644 index 0000000..bfe45cb3 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-sizing/animation/width-composition.html
@@ -0,0 +1,78 @@ +<!DOCTYPE html> +<meta charset="UTF-8"> +<title>width composition</title> +<link rel="help" href="https://drafts.csswg.org/css-sizing-3/#propdef-width"> +<meta name="assert" content="width supports animation by computed value"> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/css/support/interpolation-testcommon.js"></script> + +<body> +<script> +test_composition({ + property: 'width', + underlying: '50px', + addFrom: '100px', + addTo: '200px', +}, [ + {at: -0.3, expect: '120px'}, + {at: 0, expect: '150px'}, + {at: 0.5, expect: '200px'}, + {at: 1, expect: '250px'}, + {at: 1.5, expect: '300px'}, +]); + +test_composition({ + property: 'width', + underlying: '100px', + addFrom: '10px', + addTo: '2px', +}, [ + {at: -0.5, expect: '114px'}, + {at: 0, expect: '110px'}, + {at: 0.5, expect: '106px'}, + {at: 1, expect: '102px'}, + {at: 1.5, expect: '98px'}, // Value clamping should happen after composition. +]); + +test_composition({ + property: 'width', + underlying: '10%', + addFrom: '100px', + addTo: '20%', +}, [ + {at: -0.3, expect: 'calc(130px + 4%)'}, + {at: 0, expect: 'calc(100px + 10%)'}, + {at: 0.5, expect: 'calc(50px + 20%)'}, + {at: 1, expect: '30%'}, + {at: 1.5, expect: 'calc(-50px + 40%)'}, +]); + +test_composition({ + property: 'width', + underlying: '50px', + addFrom: '100px', + replaceTo: '200px', +}, [ + {at: -0.3, expect: '135px'}, + {at: 0, expect: '150px'}, + {at: 0.5, expect: '175px'}, + {at: 1, expect: '200px'}, + {at: 1.5, expect: '225px'}, +]); + +test_composition({ + property: 'width', + underlying: '100px', + addFrom: '100px', + addTo: 'auto', +}, [ + {at: -0.3, expect: '200px'}, + {at: 0, expect: '200px'}, + {at: 0.5, expect: 'auto'}, + {at: 1, expect: 'auto'}, + {at: 1.5, expect: 'auto'}, +]); +</script> +</body>
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/outline/outline-change-invalidation-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/outline/outline-change-invalidation-expected.txt index 5f92e7d..511002e 100644 --- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/outline/outline-change-invalidation-expected.txt +++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/outline/outline-change-invalidation-expected.txt
@@ -10,11 +10,6 @@ "object": "LayoutBlockFlow A id='link'", "rect": [43, 83, 754, 30], "reason": "appeared" - }, - { - "object": "LayoutListMarker (anonymous)", - "rect": [30, 88, 7, 19], - "reason": "style change" } ] }
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/outline/outline-containing-image-in-non-standard-mode-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/outline/outline-containing-image-in-non-standard-mode-expected.txt index 8b5d067..acf093c 100644 --- a/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/outline/outline-containing-image-in-non-standard-mode-expected.txt +++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/paint/invalidation/outline/outline-containing-image-in-non-standard-mode-expected.txt
@@ -10,11 +10,6 @@ "object": "LayoutInline SPAN id='target'", "rect": [6, 6, 204, 58], "reason": "style change" - }, - { - "object": "LayoutImage IMG", - "rect": [8, 8, 200, 50], - "reason": "geometry" } ] }
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt index ce3fd626..e51a216 100644 --- a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt +++ b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
@@ -11086,6 +11086,22 @@ method requestSession method supportsSession setter ondevicechange +interface XRAnchor + attribute @@toStringTag + getter anchorSpace + getter lastChangedTime + method constructor + method detach +interface XRAnchorSet + attribute @@toStringTag + getter size + method @@iterator + method constructor + method entries + method forEach + method has + method keys + method values interface XRBoundedReferenceSpace : XRReferenceSpace attribute @@toStringTag getter boundsGeometry @@ -11093,6 +11109,8 @@ interface XRFrame attribute @@toStringTag getter session + getter trackedAnchors + getter worldInformation method constructor method getHitTestResults method getHitTestResultsForTransientInput @@ -11139,6 +11157,28 @@ getter removed getter session method constructor +interface XRPlane + attribute @@toStringTag + getter lastChangedTime + getter orientation + getter planeSpace + getter polygon + method constructor + method createAnchor +interface XRPlaneDetectionState + attribute @@toStringTag + getter enabled + method constructor +interface XRPlaneSet + attribute @@toStringTag + getter size + method @@iterator + method constructor + method entries + method forEach + method has + method keys + method values interface XRPose attribute @@toStringTag getter emulatedPosition @@ -11186,9 +11226,12 @@ getter onselectstart getter onvisibilitychange getter renderState + getter trackedAnchors getter visibilityState + getter worldTrackingState method cancelAnimationFrame method constructor + method createAnchor method end method requestAnimationFrame method requestHitTest @@ -11196,6 +11239,7 @@ method requestHitTestSourceForTransientInput method requestReferenceSpace method updateRenderState + method updateWorldTrackingState setter onend setter oninputsourceschange setter onselect @@ -11245,6 +11289,14 @@ getter ignoreDepthValues method constructor method getViewport +interface XRWorldInformation + attribute @@toStringTag + getter detectedPlanes + method constructor +interface XRWorldTrackingState + attribute @@toStringTag + getter planeDetectionState + method constructor interface XSLTProcessor attribute @@toStringTag method clearParameters
diff --git a/tools/binary_size/generate_milestone_reports.py b/tools/binary_size/generate_milestone_reports.py index 22f07663..0322a253 100755 --- a/tools/binary_size/generate_milestone_reports.py +++ b/tools/binary_size/generate_milestone_reports.py
@@ -231,6 +231,10 @@ if args.sync: subprocess.check_call(cmd) + subprocess.check_call([ + 'gsutil.py', 'setmeta', '-h', 'Cache-Control:no-cache', + _PUSH_URL + 'milestones.json' + ]) else: print() print('Sync files by running:')
diff --git a/tools/binary_size/generate_official_build_report.py b/tools/binary_size/generate_official_build_report.py index 44649c40..b08ccce 100755 --- a/tools/binary_size/generate_official_build_report.py +++ b/tools/binary_size/generate_official_build_report.py
@@ -11,45 +11,11 @@ import os import re import subprocess -import sys -import urllib2 - -_SRC_ROOT = os.path.join(os.path.dirname(__file__), os.pardir, os.pardir) - -sys.path.append(os.path.join(_SRC_ROOT, 'build', 'android', 'gyp')) -from util import build_utils +import tempfile _REPORTS_BASE_URL = 'gs://chrome-supersize/official_builds' -_REPORTS_JSON_GS_URL = os.path.join(_REPORTS_BASE_URL, 'reports.json') +_REPORTS_JSON_GS_URL = os.path.join(_REPORTS_BASE_URL, 'canary_reports.json') _REPORTS_GS_URL = os.path.join(_REPORTS_BASE_URL, 'reports') -_SUPERSIZE_PATH = os.path.join(_SRC_ROOT, 'tools', 'binary_size', 'supersize') - - -def _FetchReferenceVersion(new_version_str, platform): - all_versions = json.loads( - urllib2.urlopen('http://omahaproxy.appspot.com/history.json').read()) - - # Filter out versions newer than the last branch point. - new_version_major = new_version_str.split('.')[0] - versions = (e['version'] for e in all_versions if e['os'] == platform) - prev_versions = (e for e in versions if not e.startswith(new_version_major)) - - return max(prev_versions, key=lambda x: tuple(int(y) for y in x.split('.'))) - - -def _FetchSizeFileForVersion(gs_url, version, gs_size_path, output_path): - gs_path = '{}/{}/{}'.format(gs_url, version, gs_size_path) - cmd = ['gsutil.py', 'cp', gs_path, output_path] - subprocess.check_call(cmd) - - -def _CreateReports(report_path, diff_report_path, ref_size_path, size_path): - subprocess.check_call( - [_SUPERSIZE_PATH, 'html_report', size_path, report_path]) - subprocess.check_call([ - _SUPERSIZE_PATH, 'html_report', '--diff-with', ref_size_path, size_path, - diff_report_path - ]) def _WriteReportsJson(out): @@ -57,47 +23,18 @@ reports = [] report_re = re.compile( - _REPORTS_GS_URL + - r'/(?P<cpu>\S+)/(?P<apk>\S+)/(?P<path>report_(?P<version>[^_]+)\.ndjson)') + re.escape(_REPORTS_GS_URL) + + r'/(?P<version>.+?)/(?P<apk>.+?)/(?P<cpu>.+?)\.size') for line in output.splitlines(): m = report_re.search(line) if m: - meta = { + reports.append({ 'cpu': m.group('cpu'), 'version': m.group('version'), 'apk': m.group('apk'), - 'path': m.group('path') - } - diff_re = re.compile( - r'{}/{}/(?P<path>report_(?P<version>\S+)_{}.ndjson)'.format( - meta['cpu'], meta['apk'], meta['version'])) - m = diff_re.search(output) - if not m: - raise Exception('Missing diff report for {}'.format(str(meta))) + }) - meta['diff_path'] = m.group('path') - meta['reference_version'] = m.group('version') - reports.append(meta) - - return json.dump({'pushed': reports}, out) - - -def _UploadReports(reports_json_path, base_url, *ndjson_paths): - for path in ndjson_paths: - dst = os.path.join(base_url, os.path.basename(path)) - cmd = ['gsutil.py', 'cp', '-a', 'public-read', path, dst] - logging.warning(' '.join(cmd)) - subprocess.check_call(cmd) - - with open(reports_json_path, 'w') as f: - _WriteReportsJson(f) - - cmd = [ - 'gsutil.py', 'cp', '-a', 'public-read', reports_json_path, - _REPORTS_JSON_GS_URL - ] - logging.warning(' '.join(cmd)) - subprocess.check_call(cmd) + json.dump({'pushed': reports}, out) def main(): @@ -110,15 +47,8 @@ '--size-path', required=True, help='Path to .size file for the given version.') - parser.add_argument( - '--gs-size-url', - required=True, - help='Bucket url that contains the .size files.') - parser.add_argument( - '--gs-size-path', - required=True, - help='Path within bucket to a .size file (full path looks like ' - 'GS_SIZE_URL/VERSION/GS_SIZE_PATH) used to locate reference .size file.') + parser.add_argument('--gs-size-url', help='Unused') + parser.add_argument('--gs-size-path', help='Unused') parser.add_argument( '--arch', required=True, help='Compiler architecture of build.') parser.add_argument( @@ -129,25 +59,24 @@ args = parser.parse_args() - with build_utils.TempDir() as tmp_dir: - ref_version = _FetchReferenceVersion(args.version, args.platform) - logging.warning('Found reference version name: %s', ref_version) + report_basename = os.path.splitext(os.path.basename(args.size_path))[0] + # Maintain name through transition to bundles. + report_basename = report_basename.replace('.minimal.apks', '.apk') + dst_url = os.path.join(_REPORTS_GS_URL, args.version, args.arch, + report_basename + '.size') - ref_size_path = os.path.join(tmp_dir, ref_version) + '.size' - report_path = os.path.join(tmp_dir, 'report_{}.ndjson'.format(args.version)) - diff_report_path = os.path.join( - tmp_dir, 'report_{}_{}.ndjson'.format(ref_version, args.version)) - reports_json_path = os.path.join(tmp_dir, 'reports.json') - report_basename = os.path.splitext(os.path.basename(args.size_path))[0] - # Maintain name through transition to bundles. - report_basename = report_basename.replace('.minimal.apks', '.apk') - reports_base_url = os.path.join(_REPORTS_GS_URL, args.arch, report_basename) + cmd = ['gsutil.py', 'cp', '-a', 'public-read', args.size_path, dst_url] + logging.warning(' '.join(cmd)) + subprocess.check_call(cmd) - _FetchSizeFileForVersion(args.gs_size_url, ref_version, args.gs_size_path, - ref_size_path) - _CreateReports(report_path, diff_report_path, ref_size_path, args.size_path) - _UploadReports(reports_json_path, reports_base_url, report_path, - diff_report_path) + with tempfile.NamedTemporaryFile() as f: + _WriteReportsJson(f) + cmd = [ + 'gsutil.py', '--', '-h', 'Cache-Control:no-cache', 'cp', '-a', + 'public-read', f.name, _REPORTS_JSON_GS_URL + ] + logging.warning(' '.join(cmd)) + subprocess.check_call(cmd) if __name__ == '__main__':
diff --git a/tools/binary_size/libsupersize/static/index.html b/tools/binary_size/libsupersize/static/index.html index 5174dbd..12c2c22 100644 --- a/tools/binary_size/libsupersize/static/index.html +++ b/tools/binary_size/libsupersize/static/index.html
@@ -106,217 +106,7 @@ } </style> <link rel="icon" href="favicon.ico" sizes="16x16 32x32 256x256" type="image/x-icon"> - <script> -const DO_NOT_DIFF = "Don't diff"; - -/** - * @param {string[]} options - * @param {string} key - */ -function buildOptions(options, key) { - const fragment = document.createDocumentFragment(); - if (key) { - options = options - .map((item, i, self) => { return item[key] }) - .filter((item, i, self) => { return i === self.indexOf(item) }) - .sort(); - } - for (let option of options) { - const optionEl = document.createElement('option'); - optionEl.value = option; - optionEl.textContent = option; - fragment.appendChild(optionEl); - } - return fragment; -} - -/** - * Is `v1` a larger version than `v2`? - * @param {string} v1 - * @param {string} v2 - */ -function isGreaterOrEqual(v1, v2) { - const [version1] = v1.split('.', 1).map(n => parseInt(n, 10)); - const [version2] = v2.split('.', 1).map(n => parseInt(n, 10)); - return version1 >= version2; -} - -function selectOption(optList, index) { - const n = optList.length; - if (n > 0) optList[((index % n) + n) % n].selected = true; -} - -function setSubmitListener(form, fetchDataUrl) { - form.addEventListener('submit', event => { - event.preventDefault(); - const dataUrl = fetchDataUrl(); - // Exclude unwind_cfi via a filter as a work-around for it being included - // in the size data. It's a file that exists in dev but not beta/stable. - window.open(`viewer.html?load_url=${dataUrl}&exclude=assets%2Funwind_cfi`); - }); -} - -// Milestones. -(async () => { - // Milestones. - const milestoneResponse = await fetch('milestones/milestones.json'); - const milestonesPushed = (await milestoneResponse.json())['pushed']; - - // Official Builds - const officialBuildsResponse = await fetch('official_builds/reports.json'); - const officialBuildsPushed = (await officialBuildsResponse.json())['pushed']; - - if (document.readyState === 'loading') { - await new Promise(resolve => { - document.onreadystatechange = () => { - if (document.readyState !== 'loading') { - resolve(); - document.onreadystatechange = null; - } - } - }); - } - - /** @type {HTMLFormElement} */ - const submitButton = document.getElementById('submit-button'); - const form = document.getElementById('select-form'); - const selApk = form.elements.namedItem('apk'); - const selVersion1 = form.elements.namedItem('version1'); - const selVersion2 = form.elements.namedItem('version2'); - const btnOpen = form.querySelector('button[type="submit"]'); - - function channelIsMilestone() { - // Returns: Whether channel is set to stable/beta (i.e. is a milestone) - const channel = document.querySelector('input[name="mode"]:checked').value; - return channel == 'stable/beta'; - } - - function fmtCpuApk(cpu, apk) { - return cpu + '/' + apk; - } - - function cpuApkPairs(cpus, apks) { - let out = []; - for (let cpu of cpus) { - for (let apk of apks) { - // Chrome.apk not available for arm_64 - if(!(cpu == 'arm_64' && apk == 'Chrome.apk')) { - out.push(fmtCpuApk(cpu, apk)); - } - } - } - return out; - } - - function updateApk() { - // Overwrites the apk selector with entries of format {cpu}/{apk} - let apks = []; - if (channelIsMilestone()) { - apks = cpuApkPairs(milestonesPushed.cpu, milestonesPushed.apk); - } else { - apks = [...new Set(officialBuildsPushed.map(a => { - let apk = a.apk; - // Can safely discard minimal apks - as of 16-Sep-2019 there was only - // one entry with an attached Monochrome.minimal apk, assumed bug - if (apk === 'Monochrome.minimal.apks') apk = 'Monochrome.apk'; - return fmtCpuApk(a.cpu, a.apk); - } - ))]; - } - selApk.innerHTML = ''; - selApk.appendChild(buildOptions(apks)); - } - - function updateSubmitButton() { - if (channelIsMilestone()) { - submitButton.textContent = 'Open Milestone Report'; - } else { - submitButton.textContent = 'Open Canary Report'; - } - } - - function updateVersions() { - const prev = selVersion1.value; - let versions = []; - if (channelIsMilestone()) { - // For the selected APK - versions = milestonesPushed.version; - } else { - versions = (officialBuildsPushed - .filter(a => fmtCpuApk(a.cpu, a.apk) == selApk.value) - .map(a => a.version)); - } - selVersion1.innerHTML = ''; - selVersion1.appendChild(buildOptions(versions)); - // Selects latest version (index -1) if previous option not still in list. - selectOption(selVersion1.querySelectorAll('option'), - versions.indexOf(prev)); - } - - function updateDiffVersions() { - // Filter diff-against versions that are newer - // Preserve current options if possible - let diffVersions = []; - if (channelIsMilestone()) { - diffVersions = [...milestonesPushed.version]; - diffVersions = diffVersions.filter(v2 => !isGreaterOrEqual(v2, selVersion1.value)); - } else { - diffVersions = ['Diff with Previous Branch']; - } - diffVersions.push(DO_NOT_DIFF); - selVersion2.innerHTML = ''; - selVersion2.appendChild(buildOptions(diffVersions)); - selectOption(selVersion2.querySelectorAll('option'), -1); - } - - updateApk(); - updateVersions(); - updateDiffVersions(); - - selApk.addEventListener('change', () => { - updateVersions(); - }); - - const selChannels = document.getElementsByName('mode'); - for(let i=0; i < selChannels.length; i++) { - selChannels[i].addEventListener('click', () => { - updateSubmitButton(); - updateApk(); - updateVersions(); - selectOption(selVersion1.querySelectorAll('option'), -1); - updateDiffVersions(); - }); - } - - selVersion1.addEventListener('change', () => { - updateDiffVersions(); - }); - - function getDataUrl() { - if (channelIsMilestone()) { - let ret = `milestones/${selVersion1.value}/${apk.value}.size`; - if (selVersion2.value !== DO_NOT_DIFF) { - ret += `&before_url=milestones/${selVersion2.value}/${apk.value}.size`; - } - return ret; - } else { - let path = `official_builds/reports/${selApk.value}/`; - if (selVersion2.value === DO_NOT_DIFF) { - return path + `report_${selVersion1.value}.ndjson`; - } else { // Diff with previous version - for (const item of officialBuildsPushed) { - if (item['version'] == selVersion1.value) { - const refVersion = item['reference_version']; - return path + `report_${refVersion}_${selVersion1.value}.ndjson`; - } - } - } - } - } - - setSubmitListener(form, getDataUrl); -})(); - </script> + <script src="index.js"></script> </head> <body> @@ -329,10 +119,6 @@ <tr> <td style="width: 40%"> <form id="select-form"> - <h2 style="font-size: 16px">Channel: - <label><input type="radio" name="mode" value="stable/beta" checked> Stable/Beta</label> - <label><input type="radio" name="mode" value="canary"> Canary</label> - </h2> <p class="select-wrapper"> <select id="apk" class="sel-big" name="apk"></select> <label class="select-label" for="apk">APK</label> @@ -347,15 +133,15 @@ Diff Against </label> </p> + <p class="select-wrapper" style="font-size: 16px"> + <label><input type="checkbox" name="showall"> Show all Canary versions</label> + </p> <p class="select-wrapper"> <button type="submit" class="text-button" id="submit-button"> - Open Milestone Report + Open Size Report </button> </p> - <div style="margin:20pt 0 10pt"> - <b>Note:</b> AndroidWebview.apk size information exists only for M71 and above.<br> - </div> </form> </td> </tr>
diff --git a/tools/binary_size/libsupersize/static/index.js b/tools/binary_size/libsupersize/static/index.js new file mode 100644 index 0000000..e6611fc --- /dev/null +++ b/tools/binary_size/libsupersize/static/index.js
@@ -0,0 +1,187 @@ +// 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. + +const DO_NOT_DIFF = 'Don\'t diff'; + +function buildOptions(options) { + const fragment = document.createDocumentFragment(); + for (let option of options) { + const optionEl = document.createElement('option'); + optionEl.value = option; + optionEl.textContent = option; + fragment.appendChild(optionEl); + } + return fragment; +} + +function selectOption(optList, index) { + const n = optList.length; + if (n > 0) + optList[((index % n) + n) % n].selected = true; +} + +function setSubmitListener(form, fetchDataUrl) { + form.addEventListener('submit', event => { + event.preventDefault(); + const dataUrl = fetchDataUrl(); + // Exclude unwind_cfi via a filter as a work-around for it being included + // in the size data. It's a file that exists in dev but not beta/stable. + window.open(`viewer.html?load_url=${dataUrl}&exclude=assets%2Funwind_cfi`); + }); +} + +// Milestones. +(async () => { + // Milestones. + const milestoneResponse = await fetch('milestones/milestones.json'); + const milestonesPushed = (await milestoneResponse.json())['pushed']; + + // Official Builds + const officialBuildsResponse = + await fetch('official_builds/canary_reports.json'); + const officialBuildsPushed = (await officialBuildsResponse.json())['pushed']; + + if (document.readyState === 'loading') { + await new Promise(resolve => { + document.onreadystatechange = + () => { + if (document.readyState !== 'loading') { + resolve(); + document.onreadystatechange = null; + } + } + }); + } + + /** @type {HTMLFormElement} */ + const submitButton = document.getElementById('submit-button'); + const form = document.getElementById('select-form'); + const selApk = form.elements.namedItem('apk'); + const selVersion1 = form.elements.namedItem('version1'); + const selVersion2 = form.elements.namedItem('version2'); + const showAll = document.getElementsByName('showall')[0]; + const btnOpen = form.querySelector('button[type="submit"]'); + + let activeVersions = []; + + function fmtCpuApk(cpu, apk) { + return cpu + '/' + apk; + } + + function cpuApkPairs(cpus, apks) { + let out = []; + for (let cpu of cpus) { + for (let apk of apks) { + // Chrome.apk not available for arm_64 + if (!(cpu == 'arm_64' && apk == 'Chrome.apk')) { + out.push(fmtCpuApk(cpu, apk)); + } + } + } + return out; + } + + function updateApk() { + // Overwrites the apk selector with entries of format {cpu}/{apk} + let mainApks = cpuApkPairs(milestonesPushed.cpu, milestonesPushed.apk); + let canaryApks = officialBuildsPushed.map(a => { + return fmtCpuApk(a.cpu, a.apk); + }); + selApk.innerHTML = ''; + selApk.appendChild( + buildOptions([...new Set([...mainApks, ...canaryApks])])); + } + + function compareVersions(v1, v2) { + function toNumber(s) { + return ( + s.split('.').map(x => parseInt(x)).reduce((x, y) => x * 1000 + y)); + } + return toNumber(v1) - toNumber(v2); + } + + function updateVersions() { + const prev = selVersion1.value; + // For the selected APK + let mainVersions = milestonesPushed.version; + let canaryVersions = + (officialBuildsPushed + .filter(a => fmtCpuApk(a.cpu, a.apk) == selApk.value) + .map(a => a.version + ' (canary)')); + + if (selApk.value.indexOf('AndroidWebview.apk') != -1) { + // AndroidWebview.apk size information exists only for M71 and above. + mainVersions = + mainVersions.filter(v2 => compareVersions(v2, '71.0.0.0') > 0); + } + + if (showAll.value) { + activeVersions = [...mainVersions, ...canaryVersions]; + activeVersions.sort(compareVersions); + } else { + canaryVersions.sort(compareVersions); + activeVersions = [...mainVersions]; + if (canaryVersions.length) { + activeVersions.push(canaryVersions[canaryVersions.length - 1]); + } + } + selVersion1.innerHTML = ''; + selVersion1.appendChild(buildOptions(activeVersions)); + // Selects latest version (index -1) if previous option not still in list. + selectOption( + selVersion1.querySelectorAll('option'), activeVersions.indexOf(prev)); + } + + function updateDiffVersions() { + // Filter diff-against versions that are newer + // Preserve current options if possible + const prev = selVersion2.value; + selVersion2.innerHTML = ''; + let v1 = selVersion1.value; + if (v1) { + let diffVersions = + activeVersions.filter(v2 => compareVersions(v2, v1) < 0); + diffVersions.push(DO_NOT_DIFF); + selVersion2.appendChild(buildOptions(diffVersions)); + selectOption( + selVersion2.querySelectorAll('option'), diffVersions.indexOf(prev)); + } + } + + updateApk(); + updateVersions(); + updateDiffVersions(); + + selApk.addEventListener('change', () => { + updateVersions(); + }); + + selVersion1.addEventListener('change', () => { + updateDiffVersions(); + }); + + showAll.addEventListener('click', () => { + updateApk(); + updateVersions(); + updateDiffVersions(); + }); + + function getDataUrl() { + function sizeUrlFor(value) { + if (value.indexOf('canary') != -1) { + const strippedVersion = value.replace(/[^\d.]/g, ''); + return `official_builds/reports/${strippedVersion}/${ + selApk.value}.size`; + } + return `milestones/${value}/${selApk.value}.size`; + } + let ret = sizeUrlFor(selVersion1.value); + if (selVersion2.value !== DO_NOT_DIFF) { + ret += '&before_url=' + sizeUrlFor(selVersion2.value); + } + return ret; + } + + setSubmitListener(form, getDataUrl); +})();
diff --git a/tools/binary_size/libsupersize/upload_html_viewer.py b/tools/binary_size/libsupersize/upload_html_viewer.py index 3f1e986a..e92162e 100755 --- a/tools/binary_size/libsupersize/upload_html_viewer.py +++ b/tools/binary_size/libsupersize/upload_html_viewer.py
@@ -18,7 +18,8 @@ """Upload static files from the static directory.""" static_files = os.path.join(os.path.dirname(__file__), 'static') subprocess.check_call([ - 'gsutil.py', '-m', 'rsync', '-r', static_files, GS_BUCKET + 'gsutil.py', '--', '-m', '-h' + 'Cache-Control:no-cache', 'rsync', '-r', static_files, GS_BUCKET ]) @@ -28,8 +29,10 @@ cache_hash = uuid.uuid4().hex p = subprocess.Popen([ - 'gsutil.py', 'cp', '-p', '-', '%s/sw.js' % GS_BUCKET - ], stdin=subprocess.PIPE) + 'gsutil.py', '--', '-h' + 'Cache-Control:no-cache', 'cp', '-p', '-', GS_BUCKET + '/sw.js' + ], + stdin=subprocess.PIPE) with open(template_file, 'r') as in_file: p.communicate(in_file.read().replace('{{cache_hash}}', cache_hash)) @@ -42,9 +45,8 @@ ]) # All files in the root of the bucket are user readable - subprocess.check_call([ - 'gsutil.py', '-m', 'acl', 'ch', '-u', 'AllUsers:R', '%s/*' % GS_BUCKET - ]) + subprocess.check_call( + ['gsutil.py', '-m', 'acl', 'ch', '-u', 'AllUsers:R', GS_BUCKET + '/*']) def main():
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index 09c331d1..9a58d9f5 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -37061,6 +37061,7 @@ <int value="-977770313" label="AndroidSurfaceControl:enabled"/> <int value="-977476498" label="disable-eol-notification"/> <int value="-975787829" label="AutofillProfileServerValidation:enabled"/> + <int value="-974882918" label="WebXRIncubations:disabled"/> <int value="-974378602" label="WebAuthenticationCable:disabled"/> <int value="-973509424" label="NewTabPageIcons:disabled"/> <int value="-972945109" label="NtpRealbox:disabled"/> @@ -37693,6 +37694,7 @@ <int value="-143819280" label="google-password-manager:disabled"/> <int value="-143394485" label="SplitSettingsSync:enabled"/> <int value="-143382681" label="InstantTethering:enabled"/> + <int value="-143121333" label="WebXRIncubations:enabled"/> <int value="-141516902" label="UseModernMediaControls:enabled"/> <int value="-140168253" label="ProfileMenuRevamp:enabled"/> <int value="-138983372" label="DesktopPWAWindowing:disabled"/> @@ -50988,54 +50990,54 @@ <enum name="PrerenderFinalStatus"> <int value="0" label="USED"/> <int value="1" label="TIMED_OUT"/> - <int value="2" label="EVICTED"/> - <int value="3" label="MANAGER_SHUTDOWN"/> + <int value="2" label="EVICTED (Obsolete)"/> + <int value="3" label="MANAGER_SHUTDOWN (Obsolete)"/> <int value="4" label="CLOSED"/> <int value="5" label="CREATE_NEW_WINDOW"/> <int value="6" label="PROFILE_DESTROYED"/> <int value="7" label="APP_TERMINATING"/> - <int value="8" label="JAVASCRIPT_ALERT"/> + <int value="8" label="JAVASCRIPT_ALERT (Obsolete)"/> <int value="9" label="AUTH_NEEDED"/> - <int value="10" label="HTTPS"/> + <int value="10" label="HTTPS (Obsolete)"/> <int value="11" label="DOWNLOAD"/> <int value="12" label="MEMORY_LIMIT_EXCEEDED"/> - <int value="13" label="JS_OUT_OF_MEMORY"/> - <int value="14" label="RENDERER_UNRESPONSIVE"/> + <int value="13" label="JS_OUT_OF_MEMORY (Obsolete)"/> + <int value="14" label="RENDERER_UNRESPONSIVE (Obsolete)"/> <int value="15" label="TOO_MANY_PROCESSES"/> <int value="16" label="RATE_LIMIT_EXCEEDED"/> - <int value="17" label="PENDING_SKIPPED"/> - <int value="18" label="CONTROL_GROUP"/> - <int value="19" label="HTML5_MEDIA"/> - <int value="20" label="SOURCE_RENDER_VIEW_CLOSED"/> + <int value="17" label="PENDING_SKIPPED (Obsolete)"/> + <int value="18" label="CONTROL_GROUP (Obsolete)"/> + <int value="19" label="HTML5_MEDIA (Obsolete)"/> + <int value="20" label="SOURCE_RENDER_VIEW_CLOSED (Obsolete)"/> <int value="21" label="RENDERER_CRASHED"/> <int value="22" label="UNSUPPORTED_SCHEME"/> <int value="23" label="INVALID_HTTP_METHOD"/> <int value="24" label="WINDOW_PRINT (Obsolete)"/> <int value="25" label="RECENTLY_VISITED"/> <int value="26" label="WINDOW_OPENER"/> - <int value="27" label="PAGE_ID_CONFLICT"/> + <int value="27" label="PAGE_ID_CONFLICT (Obsolete)"/> <int value="28" label="SAFE_BROWSING"/> - <int value="29" label="FRAGMENT_MISMATCH"/> + <int value="29" label="FRAGMENT_MISMATCH (Obsolete)"/> <int value="30" label="SSL_CLIENT_CERTIFICATE_REQUESTED"/> <int value="31" label="CACHE_OR_HISTORY_CLEARED"/> <int value="32" label="CANCELLED"/> <int value="33" label="SSL_ERROR"/> - <int value="34" label="CROSS_SITE_NAVIGATION_PENDING"/> - <int value="35" label="DEVTOOLS_ATTACHED"/> - <int value="36" label="SESSION_STORAGE_NAMESPACE_MISMATCH"/> - <int value="37" label="NO_USE_GROUP"/> - <int value="38" label="MATCH_COMPLETE_DUMMY"/> + <int value="34" label="CROSS_SITE_NAVIGATION_PENDING (Obsolete)"/> + <int value="35" label="DEVTOOLS_ATTACHED (Obsolete)"/> + <int value="36" label="SESSION_STORAGE_NAMESPACE_MISMATCH (Obsolete)"/> + <int value="37" label="NO_USE_GROUP (Obsolete)"/> + <int value="38" label="MATCH_COMPLETE_DUMMY (Obsolete)"/> <int value="39" label="DUPLICATE"/> <int value="40" label="OPEN_URL"/> - <int value="41" label="WOULD_HAVE_BEEN_USED"/> + <int value="41" label="WOULD_HAVE_BEEN_USED (Obsolete)"/> <int value="42" label="REGISTER_PROTOCOL_HANDLER"/> <int value="43" label="CREATING_AUDIO_STREAM"/> <int value="44" label="PAGE_BEING_CAPTURED"/> <int value="45" label="BAD_DEFERRED_REDIRECT"/> <int value="46" label="NAVIGATION_UNCOMMITTED"/> <int value="47" label="NEW_NAVIGATION_ENTRY"/> - <int value="48" label="COOKIE_STORE_NOT_LOADED"/> - <int value="49" label="COOKIE_CONFLICT"/> + <int value="48" label="COOKIE_STORE_NOT_LOADED (Obsolete)"/> + <int value="49" label="COOKIE_CONFLICT (Obsolete)"/> <int value="50" label="NON_EMPTY_BROWSING_INSTANCE"/> <int value="51" label="NAVIGATION_INTERCEPTED"/> <int value="52" label="PRERENDERING_DISABLED"/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 9b2ae55..ec662ca 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -118809,6 +118809,9 @@ <histogram name="Prerender.TabContentsDeleterSuppressedDialog" enum="BooleanSuppressed"> + <obsolete> + Obsoleted in Dec 2019. + </obsolete> <owner>pasko@chromium.org</owner> <summary> A boolean that indicates how often we suppress a dialog from a tab when
diff --git a/tools/perf/benchmarks/benchmark_smoke_unittest.py b/tools/perf/benchmarks/benchmark_smoke_unittest.py index 7f5e0c7..9dd73b1 100644 --- a/tools/perf/benchmarks/benchmark_smoke_unittest.py +++ b/tools/perf/benchmarks/benchmark_smoke_unittest.py
@@ -71,6 +71,8 @@ options.pageset_repeat = 1 # For smoke testing only run the page once. options.output_formats = ['histograms'] options.max_values_per_test_case = MAX_VALUES_PER_TEST_CASE + results_processor.ProcessOptions(options) + return_code = benchmark_class().Run(options) # TODO(crbug.com/1019139): Make 111 be the exit code that means # "no stories were run.".
diff --git a/tools/perf/benchmarks/system_health_smoke_test.py b/tools/perf/benchmarks/system_health_smoke_test.py index a76b1aa6..5e7cd37 100644 --- a/tools/perf/benchmarks/system_health_smoke_test.py +++ b/tools/perf/benchmarks/system_health_smoke_test.py
@@ -305,6 +305,7 @@ options.browser_options.logging_verbosity = 'non-verbose' options.target_platforms = benchmark_cls.GetSupportedPlatformNames( benchmark_cls.SUPPORTED_PLATFORMS) + results_processor.ProcessOptions(options) return options
diff --git a/tools/perf/core/benchmark_runner_test.py b/tools/perf/core/benchmark_runner_test.py index 3e66a155..a47b023 100644 --- a/tools/perf/core/benchmark_runner_test.py +++ b/tools/perf/core/benchmark_runner_test.py
@@ -56,6 +56,7 @@ self.options = testing.GetRunOptions( output_dir=tempfile.mkdtemp()) self.options.output_formats = ['histograms'] + results_processor.ProcessOptions(self.options) def tearDown(self): shutil.rmtree(self.options.output_dir)
diff --git a/tools/perf/core/minidump_unittest.py b/tools/perf/core/minidump_unittest.py index 1e7784c2..5bb282d 100644 --- a/tools/perf/core/minidump_unittest.py +++ b/tools/perf/core/minidump_unittest.py
@@ -18,7 +18,8 @@ @decorators.Isolated # Minidump symbolization doesn't work in ChromeOS local mode if the rootfs is # still read-only, so skip the test in that case. - @decorators.Disabled('chromeos-local') + # TODO(crbug.com/1038043): Test is failing on chromeos-betty-chrome. + @decorators.Disabled('chromeos-local', 'chromeos') def testSymbolizeMinidump(self): # Wait for the browser to restart fully before crashing self._LoadPageThenWait('var sam = "car";', 'sam') @@ -58,7 +59,8 @@ @decorators.Isolated # Minidump symbolization doesn't work in ChromeOS local mode if the rootfs is # still read-only, so skip the test in that case. - @decorators.Disabled('chromeos-local') + # TODO(crbug.com/1038043): Test is failing on chromeos-betty-chrome. + @decorators.Disabled('chromeos-local', 'chromeos') def testMultipleCrashMinidumps(self): # Wait for the browser to restart fully before crashing self._LoadPageThenWait('var cat = "dog";', 'cat')
diff --git a/tools/perf/core/shard_maps/smoke_test_benchmark_shard_map.json b/tools/perf/core/shard_maps/smoke_test_benchmark_shard_map.json index 1524b68..992dd83 100644 --- a/tools/perf/core/shard_maps/smoke_test_benchmark_shard_map.json +++ b/tools/perf/core/shard_maps/smoke_test_benchmark_shard_map.json
@@ -4,6 +4,14 @@ "dummy_benchmark.stable_benchmark_1": { "abridged": false } + }, + "executables": { + "dummy_gtest": { + "path": "../../tools/perf/testdata/dummy_gtest", + "arguments": [ + "--argument-to-check-that-arguments-work" + ] + } } }, "1": {
diff --git a/tools/perf/scripts_smoke_unittest.py b/tools/perf/scripts_smoke_unittest.py index 418e992..83152de 100644 --- a/tools/perf/scripts_smoke_unittest.py +++ b/tools/perf/scripts_smoke_unittest.py
@@ -162,8 +162,7 @@ # Android: crbug.com/932301 # ChromeOS: crbug.com/754913 - # Linux: crbug.com/1024767 - @decorators.Disabled('chromeos', 'android', 'linux') + @decorators.Disabled('chromeos', 'android') def testRunPerformanceTestsTelemetrySharded_end2end(self): tempdir = tempfile.mkdtemp() env = os.environ.copy() @@ -188,22 +187,26 @@ self.assertEquals(return_code, 0) expected_benchmark_folders = ( 'dummy_benchmark.stable_benchmark_1', - 'dummy_benchmark.stable_benchmark_1.reference') + 'dummy_benchmark.stable_benchmark_1.reference', + 'dummy_gtest') with open(os.path.join(tempdir, 'output.json')) as f: test_results = json.load(f) self.assertIsNotNone( test_results, 'json_test_results should be populated.') - test_repeats = test_results['num_failures_by_type']['PASS'] + test_runs = test_results['num_failures_by_type']['PASS'] + # 1 gtest runs (since --isolated-script-test-repeat doesn't work for gtest + # yet) plus 2 dummy_benchmark runs = 3 runs. self.assertEqual( - test_repeats, 2, '--isolated-script-test-repeat=2 should work.') + test_runs, 3, '--isolated-script-test-repeat=2 should work.') for folder in expected_benchmark_folders: with open(os.path.join(tempdir, folder, 'test_results.json')) as f: test_results = json.load(f) self.assertIsNotNone( test_results, 'json test results should be populated.') test_repeats = test_results['num_failures_by_type']['PASS'] - self.assertEqual( - test_repeats, 2, '--isolated-script-test-repeat=2 should work.') + if 'dummy_gtest' not in folder: # Repeats don't work for gtest yet. + self.assertEqual( + test_repeats, 2, '--isolated-script-test-repeat=2 should work.') with open(os.path.join(tempdir, folder, 'perf_results.json')) as f: perf_results = json.load(f) self.assertIsNotNone( @@ -231,11 +234,22 @@ if generate_trace else '') + ' --non-telemetry=true ' '--this-arg=passthrough ' + '--argument-to-check-that-arguments-work ' '--gtest-benchmark-name dummy_gtest ' '--isolated-script-test-output=%s' % ( os.path.join(tempdir, 'output.json') )) - self.assertEquals(return_code, 0, stdout) + try: + self.assertEquals(return_code, 0, stdout) + except AssertionError: + try: + with open(os.path.join(tempdir, benchmark, 'benchmark_log.txt')) as fh: + print fh.read() + # pylint: disable=bare-except + except: + # pylint: enable=bare-except + pass + raise try: with open(os.path.join(tempdir, 'output.json')) as f: test_results = json.load(f) @@ -266,7 +280,7 @@ def testRunPerformanceTestsGtestTrace_end2end(self): self.RunGtest(generate_trace=True) - def testRunPerformanceTestsTelemetryArgsParser(self): + def testRunPerformanceTestsShardedArgsParser(self): options = run_performance_tests.parse_arguments([ '../../tools/perf/run_benchmark', '-v', '--browser=release_x64', '--upload-results', '--run-ref-build',
diff --git a/tools/perf/testdata/dummy_gtest b/tools/perf/testdata/dummy_gtest index 84c61aa..6baa671 100755 --- a/tools/perf/testdata/dummy_gtest +++ b/tools/perf/testdata/dummy_gtest
@@ -18,6 +18,8 @@ # Simulate trace file generation when "--trace-dir" switch is present. parser = argparse.ArgumentParser() parser.add_argument( + "--argument-to-check-that-arguments-work", action='store_true') +parser.add_argument( "--trace-dir", type=str, help="Simulate trace file generation to the given path.") @@ -37,3 +39,8 @@ with open( os.path.join(options.trace_dir, 'dummy_luci_test_result.json'), 'w') as f: f.write(test_result) +if options.argument_to_check_that_arguments_work: + print 'Arguments worked!' +else: + print '--argument-to-check-that-arguments-work was not passed. Failing.' + sys.exit(1)
diff --git a/ui/accessibility/BUILD.gn b/ui/accessibility/BUILD.gn index a51cbdce..9470d3ab 100644 --- a/ui/accessibility/BUILD.gn +++ b/ui/accessibility/BUILD.gn
@@ -62,6 +62,8 @@ "ax_export.h", "ax_language_detection.cc", "ax_language_detection.h", + "ax_live_region_tracker.cc", + "ax_live_region_tracker.h", "ax_mode.cc", "ax_mode.h", "ax_mode_observer.h",
diff --git a/ui/accessibility/ax_event_generator.cc b/ui/accessibility/ax_event_generator.cc index 106364a..b0c41170 100644 --- a/ui/accessibility/ax_event_generator.cc +++ b/ui/accessibility/ax_event_generator.cc
@@ -8,6 +8,7 @@ #include "base/stl_util.h" #include "ui/accessibility/ax_enums.mojom.h" +#include "ui/accessibility/ax_live_region_tracker.h" #include "ui/accessibility/ax_node.h" #include "ui/accessibility/ax_role_properties.h" @@ -100,8 +101,10 @@ AXEventGenerator::AXEventGenerator() = default; AXEventGenerator::AXEventGenerator(AXTree* tree) : tree_(tree) { - if (tree_) + if (tree_) { tree_->AddObserver(this); + live_region_tracker_ = std::make_unique<AXLiveRegionTracker>(tree_); + } } AXEventGenerator::~AXEventGenerator() { @@ -110,11 +113,15 @@ } void AXEventGenerator::SetTree(AXTree* new_tree) { - if (tree_) + if (tree_) { tree_->RemoveObserver(this); + live_region_tracker_.reset(); + } tree_ = new_tree; - if (tree_) + if (tree_) { tree_->AddObserver(this); + live_region_tracker_ = std::make_unique<AXLiveRegionTracker>(tree_); + } } void AXEventGenerator::ReleaseTree() { @@ -475,6 +482,12 @@ } void AXEventGenerator::OnNodeWillBeDeleted(AXTree* tree, AXNode* node) { + if (node->data().HasStringAttribute( + ax::mojom::StringAttribute::kContainerLiveStatus)) { + FireLiveRegionEvents(node); + live_region_tracker_->OnNodeWillBeDeleted(node); + } + DCHECK_EQ(tree_, tree); tree_events_.erase(node); } @@ -506,6 +519,14 @@ } for (const auto& change : changes) { + if ((change.type == NODE_CREATED || change.type == SUBTREE_CREATED || + change.type == NODE_REPARENTED || change.type == SUBTREE_REPARENTED)) { + if (change.node->data().HasStringAttribute( + ax::mojom::StringAttribute::kContainerLiveStatus)) { + live_region_tracker_->TrackNode(change.node); + } + } + if (change.type == SUBTREE_CREATED) { AddEvent(change.node, Event::SUBTREE_CREATED); } else if (change.type != NODE_CREATED) { @@ -525,23 +546,29 @@ } void AXEventGenerator::FireLiveRegionEvents(AXNode* node) { - AXNode* live_root = node; - while (live_root && !live_root->data().HasStringAttribute( - ax::mojom::StringAttribute::kLiveStatus)) - live_root = live_root->parent(); + AXNode* live_root = live_region_tracker_->GetLiveRoot(node); - if (live_root && - !live_root->data().GetBoolAttribute(ax::mojom::BoolAttribute::kBusy) && - live_root->data().GetStringAttribute( - ax::mojom::StringAttribute::kLiveStatus) != "off") { - // Fire LIVE_REGION_NODE_CHANGED on each node that changed. - if (!node->data() - .GetStringAttribute(ax::mojom::StringAttribute::kName) - .empty()) - AddEvent(node, Event::LIVE_REGION_NODE_CHANGED); - // Fire LIVE_REGION_CHANGED on the root of the live region. - AddEvent(live_root, Event::LIVE_REGION_CHANGED); + // Note that |live_root| might be nullptr if a live region was just added. + if (!live_root) + return; + + if (live_root->data().GetBoolAttribute(ax::mojom::BoolAttribute::kBusy)) + return; + + std::string live_status = live_root->data().GetStringAttribute( + ax::mojom::StringAttribute::kLiveStatus); + if (live_status != "polite" && live_status != "assertive") + return; + + // Fire LIVE_REGION_NODE_CHANGED on each node that changed. + if (!node->data() + .GetStringAttribute(ax::mojom::StringAttribute::kName) + .empty()) { + AddEvent(node, Event::LIVE_REGION_NODE_CHANGED); } + + // Fire LIVE_REGION_CHANGED on the root of the live region. + AddEvent(live_root, Event::LIVE_REGION_CHANGED); } void AXEventGenerator::FireActiveDescendantEvents() {
diff --git a/ui/accessibility/ax_event_generator.h b/ui/accessibility/ax_event_generator.h index 4016e91..aa58667 100644 --- a/ui/accessibility/ax_event_generator.h +++ b/ui/accessibility/ax_event_generator.h
@@ -6,8 +6,10 @@ #define UI_ACCESSIBILITY_AX_EVENT_GENERATOR_H_ #include <map> +#include <memory> #include <ostream> #include <set> +#include <string> #include <vector> #include "ui/accessibility/ax_export.h" @@ -16,6 +18,8 @@ namespace ui { +class AXLiveRegionTracker; + // Subclass of AXTreeObserver that automatically generates AXEvents to fire // based on changes to an accessibility tree. Every platform // tends to want different events, so this class lets each platform @@ -232,6 +236,9 @@ // Valid between the call to OnIntAttributeChanged and the call to // OnAtomicUpdateFinished. List of nodes whose active descendant changed. std::vector<AXNode*> active_descendant_changed_; + + // Helper that tracks live regions. + std::unique_ptr<AXLiveRegionTracker> live_region_tracker_; }; AX_EXPORT std::ostream& operator<<(std::ostream& os,
diff --git a/ui/accessibility/ax_event_generator_unittest.cc b/ui/accessibility/ax_event_generator_unittest.cc index 32a0768..fb3d0b4 100644 --- a/ui/accessibility/ax_event_generator_unittest.cc +++ b/ui/accessibility/ax_event_generator_unittest.cc
@@ -1370,4 +1370,41 @@ HasEventAtNode(AXEventGenerator::Event::STATE_CHANGED, 1))); } +TEST(AXEventGeneratorTest, LiveRegionNodeRemoved) { + AXTreeUpdate initial_state; + initial_state.root_id = 1; + initial_state.nodes.resize(3); + initial_state.nodes[0].id = 1; + initial_state.nodes[0].AddStringAttribute( + ax::mojom::StringAttribute::kLiveStatus, "polite"); + initial_state.nodes[0].AddStringAttribute( + ax::mojom::StringAttribute::kContainerLiveStatus, "polite"); + initial_state.nodes[0].child_ids = {2, 3}; + initial_state.nodes[1].id = 2; + initial_state.nodes[1].role = ax::mojom::Role::kStaticText; + initial_state.nodes[1].AddStringAttribute( + ax::mojom::StringAttribute::kContainerLiveStatus, "polite"); + initial_state.nodes[1].AddStringAttribute(ax::mojom::StringAttribute::kName, + "Before 1"); + initial_state.nodes[2].id = 3; + initial_state.nodes[2].role = ax::mojom::Role::kStaticText; + initial_state.nodes[2].AddStringAttribute( + ax::mojom::StringAttribute::kContainerLiveStatus, "polite"); + initial_state.nodes[2].AddStringAttribute(ax::mojom::StringAttribute::kName, + "Before 2"); + AXTree tree(initial_state); + + AXEventGenerator event_generator(&tree); + AXTreeUpdate update = initial_state; + update.nodes.resize(1); + update.nodes[0].child_ids = {2}; + + EXPECT_TRUE(tree.Unserialize(update)); + EXPECT_THAT( + event_generator, + UnorderedElementsAre( + HasEventAtNode(AXEventGenerator::Event::CHILDREN_CHANGED, 1), + HasEventAtNode(AXEventGenerator::Event::LIVE_REGION_CHANGED, 1))); +} + } // namespace ui
diff --git a/ui/accessibility/ax_live_region_tracker.cc b/ui/accessibility/ax_live_region_tracker.cc new file mode 100644 index 0000000..a2cf7f195 --- /dev/null +++ b/ui/accessibility/ax_live_region_tracker.cc
@@ -0,0 +1,59 @@ +// 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 "ui/accessibility/ax_live_region_tracker.h" + +#include "base/stl_util.h" +#include "ui/accessibility/ax_node.h" +#include "ui/accessibility/ax_role_properties.h" + +namespace ui { + +AXLiveRegionTracker::AXLiveRegionTracker(AXTree* tree) : tree_(tree) { + InitializeLiveRegionNodeToRoot(tree_->root(), nullptr); +} + +AXLiveRegionTracker::~AXLiveRegionTracker() {} + +void AXLiveRegionTracker::TrackNode(AXNode* node) { + LOG(ERROR) << "TrackNode " << node->data().ToString(); + AXNode* live_root = node; + while (live_root && !live_root->HasStringAttribute( + ax::mojom::StringAttribute::kLiveStatus)) + live_root = live_root->parent(); + if (live_root) { + LOG(ERROR) << " Live root: " << live_root->data().ToString(); + live_region_node_to_root_[node] = live_root; + } else + LOG(ERROR) << " No live root"; +} + +void AXLiveRegionTracker::OnNodeWillBeDeleted(AXNode* node) { + LOG(ERROR) << "OnNodeWillBeDeleted " << node->data().ToString(); + live_region_node_to_root_.erase(node); +} + +AXNode* AXLiveRegionTracker::GetLiveRoot(AXNode* node) { + LOG(ERROR) << "GetLiveRoot for " << node->data().ToString(); + auto iter = live_region_node_to_root_.find(node); + if (iter != live_region_node_to_root_.end()) + return iter->second; + return nullptr; +} + +void AXLiveRegionTracker::InitializeLiveRegionNodeToRoot(AXNode* node, + AXNode* current_root) { + if (!current_root && + node->HasStringAttribute(ax::mojom::StringAttribute::kLiveStatus)) { + current_root = node; + } + + if (current_root) + live_region_node_to_root_[node] = current_root; + + for (size_t i = 0; i < node->children().size(); i++) + InitializeLiveRegionNodeToRoot(node->children()[i], current_root); +} + +} // namespace ui
diff --git a/ui/accessibility/ax_live_region_tracker.h b/ui/accessibility/ax_live_region_tracker.h new file mode 100644 index 0000000..b530fbab --- /dev/null +++ b/ui/accessibility/ax_live_region_tracker.h
@@ -0,0 +1,41 @@ +// 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 UI_ACCESSIBILITY_AX_LIVE_REGION_TRACKER_H_ +#define UI_ACCESSIBILITY_AX_LIVE_REGION_TRACKER_H_ + +#include <map> +#include <set> +#include <vector> + +#include "ui/accessibility/ax_tree.h" + +namespace ui { + +// Class that works with AXEventGenerator to track live regions in +// an AXTree. +class AXLiveRegionTracker { + public: + explicit AXLiveRegionTracker(AXTree* tree); + + ~AXLiveRegionTracker(); + + void TrackNode(AXNode* node); + void OnNodeWillBeDeleted(AXNode* node); + AXNode* GetLiveRoot(AXNode* node); + + private: + void InitializeLiveRegionNodeToRoot(AXNode* node, AXNode* current_root); + + AXTree* tree_; // Not owned. + + // Map from live region node to its live region root. + std::map<AXNode*, AXNode*> live_region_node_to_root_; + + DISALLOW_COPY_AND_ASSIGN(AXLiveRegionTracker); +}; + +} // namespace ui + +#endif // UI_ACCESSIBILITY_AX_LIVE_REGION_TRACKER_H_
diff --git a/ui/accessibility/ax_node_position_unittest.cc b/ui/accessibility/ax_node_position_unittest.cc index eb2acb8a..ea49b09e 100644 --- a/ui/accessibility/ax_node_position_unittest.cc +++ b/ui/accessibility/ax_node_position_unittest.cc
@@ -605,6 +605,124 @@ EXPECT_EQ(AXNodePosition::INVALID_INDEX, copy_position->child_index()); } +TEST_F(AXPositionTest, ToString) { + AXNodeData root_data; + root_data.id = 1; + root_data.role = ax::mojom::Role::kRootWebArea; + + AXNodeData static_text_data_1; + static_text_data_1.id = 2; + static_text_data_1.role = ax::mojom::Role::kStaticText; + static_text_data_1.SetName("some text"); + + AXNodeData static_text_data_2; + static_text_data_2.id = 3; + static_text_data_2.role = ax::mojom::Role::kStaticText; + static_text_data_2.SetName(base::WideToUTF16(L"\xfffc")); + + AXNodeData static_text_data_3; + static_text_data_3.id = 4; + static_text_data_3.role = ax::mojom::Role::kStaticText; + static_text_data_3.SetName("more text"); + + root_data.child_ids = {static_text_data_1.id, static_text_data_2.id, + static_text_data_3.id}; + + std::unique_ptr<AXTree> new_tree = CreateAXTree( + {root_data, static_text_data_1, static_text_data_2, static_text_data_3}); + AXNodePosition::SetTree(new_tree.get()); + + TestPositionType text_position_1 = AXNodePosition::CreateTextPosition( + new_tree->data().tree_id, root_data.id, 0 /* text_offset */, + ax::mojom::TextAffinity::kDownstream); + ASSERT_TRUE(text_position_1->IsTextPosition()); + EXPECT_EQ( + "TextPosition anchor_id=1 text_offset=0 affinity=downstream " + "annotated_text=<s>ome text\xEF\xBF\xBCmore text", + text_position_1->ToString()); + + TestPositionType text_position_2 = AXNodePosition::CreateTextPosition( + new_tree->data().tree_id, root_data.id, 5 /* text_offset */, + ax::mojom::TextAffinity::kDownstream); + ASSERT_TRUE(text_position_2->IsTextPosition()); + EXPECT_EQ( + "TextPosition anchor_id=1 text_offset=5 affinity=downstream " + "annotated_text=some <t>ext\xEF\xBF\xBCmore text", + text_position_2->ToString()); + + TestPositionType text_position_3 = AXNodePosition::CreateTextPosition( + new_tree->data().tree_id, root_data.id, 9 /* text_offset */, + ax::mojom::TextAffinity::kDownstream); + ASSERT_TRUE(text_position_3->IsTextPosition()); + EXPECT_EQ( + "TextPosition anchor_id=1 text_offset=9 affinity=downstream " + "annotated_text=some text<\xEF\xBF\xBC>more text", + text_position_3->ToString()); + + TestPositionType text_position_4 = AXNodePosition::CreateTextPosition( + new_tree->data().tree_id, root_data.id, 10 /* text_offset */, + ax::mojom::TextAffinity::kDownstream); + ASSERT_TRUE(text_position_4->IsTextPosition()); + EXPECT_EQ( + "TextPosition anchor_id=1 text_offset=10 affinity=downstream " + "annotated_text=some text\xEF\xBF\xBC<m>ore text", + text_position_4->ToString()); + + TestPositionType text_position_5 = AXNodePosition::CreateTextPosition( + new_tree->data().tree_id, root_data.id, 19 /* text_offset */, + ax::mojom::TextAffinity::kDownstream); + ASSERT_TRUE(text_position_5->IsTextPosition()); + EXPECT_EQ( + "TextPosition anchor_id=1 text_offset=19 affinity=downstream " + "annotated_text=some text\xEF\xBF\xBCmore text<>", + text_position_5->ToString()); + + TestPositionType text_position_6 = AXNodePosition::CreateTextPosition( + new_tree->data().tree_id, static_text_data_2.id, 0 /* text_offset */, + ax::mojom::TextAffinity::kDownstream); + ASSERT_TRUE(text_position_6->IsTextPosition()); + EXPECT_EQ( + "TextPosition anchor_id=3 text_offset=0 affinity=downstream " + "annotated_text=<\xEF\xBF\xBC>", + text_position_6->ToString()); + + TestPositionType text_position_7 = AXNodePosition::CreateTextPosition( + new_tree->data().tree_id, static_text_data_2.id, 1 /* text_offset */, + ax::mojom::TextAffinity::kDownstream); + ASSERT_TRUE(text_position_7->IsTextPosition()); + EXPECT_EQ( + "TextPosition anchor_id=3 text_offset=1 affinity=downstream " + "annotated_text=\xEF\xBF\xBC<>", + text_position_7->ToString()); + + TestPositionType text_position_8 = AXNodePosition::CreateTextPosition( + new_tree->data().tree_id, static_text_data_3.id, 0 /* text_offset */, + ax::mojom::TextAffinity::kDownstream); + ASSERT_TRUE(text_position_8->IsTextPosition()); + EXPECT_EQ( + "TextPosition anchor_id=4 text_offset=0 affinity=downstream " + "annotated_text=<m>ore text", + text_position_8->ToString()); + + TestPositionType text_position_9 = AXNodePosition::CreateTextPosition( + new_tree->data().tree_id, static_text_data_3.id, 5 /* text_offset */, + ax::mojom::TextAffinity::kDownstream); + ASSERT_TRUE(text_position_9->IsTextPosition()); + EXPECT_EQ( + "TextPosition anchor_id=4 text_offset=5 affinity=downstream " + "annotated_text=more <t>ext", + text_position_9->ToString()); + + TestPositionType text_position_10 = AXNodePosition::CreateTextPosition( + new_tree->data().tree_id, static_text_data_3.id, 9 /* text_offset */, + ax::mojom::TextAffinity::kDownstream); + ASSERT_TRUE(text_position_10->IsTextPosition()); + EXPECT_EQ( + "TextPosition anchor_id=4 text_offset=9 affinity=downstream " + "annotated_text=more text<>", + text_position_10->ToString()); +} + TEST_F(AXPositionTest, IsIgnored) { EXPECT_FALSE(AXNodePosition::CreateNullPosition()->IsIgnored());
diff --git a/ui/accessibility/ax_position.h b/ui/accessibility/ax_position.h index 0f5935e..ed525a2 100644 --- a/ui/accessibility/ax_position.h +++ b/ui/accessibility/ax_position.h
@@ -267,18 +267,19 @@ if (!IsTextPosition() || text_offset_ > MaxTextOffset()) return str; - std::string text = base::UTF16ToUTF8(GetText()); + base::string16 text = GetText(); DCHECK_GE(text_offset_, 0); DCHECK_LE(text_offset_, int{text.length()}); - std::string annotated_text; + base::string16 annotated_text; if (text_offset_ == MaxTextOffset()) { - annotated_text = text + "<>"; + annotated_text = text + base::WideToUTF16(L"<>"); } else { - annotated_text = text.substr(0, text_offset_) + "<" + text[text_offset_] + - ">" + text.substr(text_offset_ + 1); + annotated_text = text.substr(0, text_offset_) + base::WideToUTF16(L"<") + + text[text_offset_] + base::WideToUTF16(L">") + + text.substr(text_offset_ + 1); } - return str + " annotated_text=" + annotated_text; + return str + " annotated_text=" + base::UTF16ToUTF8(annotated_text); } AXTreeID tree_id() const { return tree_id_; }
diff --git a/ui/gfx/color_space.cc b/ui/gfx/color_space.cc index 372652e..df187341 100644 --- a/ui/gfx/color_space.cc +++ b/ui/gfx/color_space.cc
@@ -350,7 +350,6 @@ PRINT_ENUM_CASE(TransferID, SMPTEST2084) PRINT_ENUM_CASE(TransferID, SMPTEST428_1) PRINT_ENUM_CASE(TransferID, ARIB_STD_B67) - PRINT_ENUM_CASE(TransferID, SMPTEST2084_NON_HDR) PRINT_ENUM_CASE(TransferID, IEC61966_2_1_HDR) PRINT_ENUM_CASE(TransferID, LINEAR_HDR) case TransferID::CUSTOM: { @@ -786,7 +785,6 @@ case ColorSpace::TransferID::LOG: case ColorSpace::TransferID::LOG_SQRT: case ColorSpace::TransferID::SMPTEST2084: - case ColorSpace::TransferID::SMPTEST2084_NON_HDR: case ColorSpace::TransferID::CUSTOM: case ColorSpace::TransferID::INVALID: break;
diff --git a/ui/gfx/color_space.h b/ui/gfx/color_space.h index b909df38..ea9b97d 100644 --- a/ui/gfx/color_space.h +++ b/ui/gfx/color_space.h
@@ -84,10 +84,6 @@ SMPTEST2084, SMPTEST428_1, ARIB_STD_B67, // AKA hybrid-log gamma, HLG. - // This is an ad-hoc transfer function that decodes SMPTE 2084 content - // into a [0, 1] range more or less suitable for viewing on a non-hdr - // display. - SMPTEST2084_NON_HDR, // The same as IEC61966_2_1 on the interval [0, 1], with the nonlinear // segment continuing beyond 1 and point symmetry defining values below 0. IEC61966_2_1_HDR,
diff --git a/ui/gfx/color_space_win.cc b/ui/gfx/color_space_win.cc index cf3425f..45b97183 100644 --- a/ui/gfx/color_space_win.cc +++ b/ui/gfx/color_space_win.cc
@@ -122,7 +122,6 @@ case gfx::ColorSpace::TransferID::BT709_APPLE: case gfx::ColorSpace::TransferID::GAMMA18: case gfx::ColorSpace::TransferID::GAMMA24: - case gfx::ColorSpace::TransferID::SMPTEST2084_NON_HDR: case gfx::ColorSpace::TransferID::CUSTOM: case gfx::ColorSpace::TransferID::INVALID: // Not handled
diff --git a/ui/gfx/color_transform.cc b/ui/gfx/color_transform.cc index 26fa712..1d908f6a 100644 --- a/ui/gfx/color_transform.cc +++ b/ui/gfx/color_transform.cc
@@ -56,10 +56,6 @@ float FromLinear(ColorSpace::TransferID id, float v) { switch (id) { - case ColorSpace::TransferID::SMPTEST2084_NON_HDR: - // Should already be handled. - break; - case ColorSpace::TransferID::LOG: if (v < 0.01f) return 0.0f; @@ -178,10 +174,6 @@ return v; } - case ColorSpace::TransferID::SMPTEST2084_NON_HDR: - v = max(0.0f, v); - return min(2.3f * pow(v, 2.8f), v / 5.0f + 0.8f); - // Spec: http://www.arib.or.jp/english/html/overview/doc/2-STD-B67v1_0.pdf case ColorSpace::TransferID::ARIB_STD_B67: { v = max(0.0f, v); @@ -224,7 +216,6 @@ class ColorTransformMatrix; class ColorTransformSkTransferFn; class ColorTransformFromLinear; -class ColorTransformToBT2020CL; class ColorTransformFromBT2020CL; class ColorTransformNull; @@ -233,7 +224,6 @@ ColorTransformStep() {} virtual ~ColorTransformStep() {} virtual ColorTransformFromLinear* GetFromLinear() { return nullptr; } - virtual ColorTransformToBT2020CL* GetToBT2020CL() { return nullptr; } virtual ColorTransformFromBT2020CL* GetFromBT2020CL() { return nullptr; } virtual ColorTransformSkTransferFn* GetSkTransferFn() { return nullptr; } virtual ColorTransformMatrix* GetMatrix() { return nullptr; } @@ -247,19 +237,14 @@ // Return true if this is a null transform. virtual bool IsNull() { return false; } virtual void Transform(ColorTransform::TriStim* color, size_t num) const = 0; - virtual bool CanAppendShaderSource() { return false; } // In the shader, |hdr| will appear before |src|, so any helper functions that // are created should be put in |hdr|. Any helper functions should have // |step_index| included in the function name, to ensure that there are no // naming conflicts. virtual void AppendShaderSource(std::stringstream* hdr, std::stringstream* src, - size_t step_index) const { - NOTREACHED(); - } - virtual void AppendSkShaderSource(std::stringstream* src) const { - NOTREACHED(); - } + size_t step_index) const = 0; + virtual void AppendSkShaderSource(std::stringstream* src) const = 0; private: DISALLOW_COPY_AND_ASSIGN(ColorTransformStep); @@ -280,16 +265,14 @@ step->Transform(colors, num); } } - bool CanGetShaderSource() const override; std::string GetShaderSource() const override; std::string GetSkShaderSource() const override; bool IsIdentity() const override { return steps_.empty(); } size_t NumberOfStepsForTesting() const override { return steps_.size(); } private: - void AppendColorSpaceToColorSpaceTransform(ColorSpace src, - const ColorSpace& dst, - ColorTransform::Intent intent); + void AppendColorSpaceToColorSpaceTransform(const ColorSpace& src, + const ColorSpace& dst); void Simplify(); std::list<std::unique_ptr<ColorTransformStep>> steps_; @@ -302,7 +285,6 @@ ColorTransformNull* GetNull() override { return this; } bool IsNull() override { return true; } void Transform(ColorTransform::TriStim* color, size_t num) const override {} - bool CanAppendShaderSource() override { return true; } void AppendShaderSource(std::stringstream* hdr, std::stringstream* src, size_t step_index) const override {} @@ -333,7 +315,6 @@ matrix_.TransformPoint(colors + i); } - bool CanAppendShaderSource() override { return true; } void AppendShaderSource(std::stringstream* hdr, std::stringstream* src, @@ -483,7 +464,6 @@ } return false; } - bool CanAppendShaderSource() override { return true; } bool IsNull() override { return SkTransferFnIsApproximatelyIdentity(fn_); } // ColorTransformPerChannelTransferFn implementation: @@ -534,7 +514,6 @@ explicit ColorTransformFromLinear(ColorSpace::TransferID transfer) : ColorTransformPerChannelTransferFn(false), transfer_(transfer) {} ColorTransformFromLinear* GetFromLinear() override { return this; } - bool CanAppendShaderSource() override { return true; } bool IsNull() override { return transfer_ == ColorSpace::TransferID::LINEAR; } // ColorTransformPerChannelTransferFn implementation: @@ -625,7 +604,6 @@ } return false; } - bool CanAppendShaderSource() override { return true; } bool IsNull() override { return transfer_ == ColorSpace::TransferID::LINEAR; } // ColorTransformPerChannelTransferFn implementation: @@ -690,10 +668,6 @@ " (c2 - c3 * pow(v2, 1.0 / m2)), 1.0 / m1);\n" " v = v2 * 10000.0 / 80.0;\n"; return; - case ColorSpace::TransferID::SMPTEST2084_NON_HDR: - *src << " v = max(0.0, v);\n" - " v = min(2.3 * pow(v, 2.8), v / 5.0 + 0.8);\n"; - return; case ColorSpace::TransferID::ARIB_STD_B67: *src << " v = max(0.0, v);\n" << " " << scalar_type << " a = 0.17883277;\n" @@ -714,43 +688,6 @@ ColorSpace::TransferID transfer_; }; -class ColorTransformSMPTEST2048NonHdrToLinear : public ColorTransformStep { - public: - // Assumes BT2020 primaries. - static float Luma(const ColorTransform::TriStim& c) { - return c.x() * 0.2627f + c.y() * 0.6780f + c.z() * 0.0593f; - } - static ColorTransform::TriStim ClipToWhite(ColorTransform::TriStim* c) { - float maximum = max(max(c->x(), c->y()), c->z()); - if (maximum > 1.0f) { - float l = Luma(*c); - c->Scale(1.0f / maximum); - ColorTransform::TriStim white(1.0f, 1.0f, 1.0f); - white.Scale((1.0f - 1.0f / maximum) * l / Luma(white)); - ColorTransform::TriStim black(0.0f, 0.0f, 0.0f); - *c += white - black; - } - return *c; - } - void Transform(ColorTransform::TriStim* colors, size_t num) const override { - for (size_t i = 0; i < num; i++) { - ColorTransform::TriStim ret( - ToLinear(ColorSpace::TransferID::SMPTEST2084_NON_HDR, colors[i].x()), - ToLinear(ColorSpace::TransferID::SMPTEST2084_NON_HDR, colors[i].y()), - ToLinear(ColorSpace::TransferID::SMPTEST2084_NON_HDR, colors[i].z())); - if (Luma(ret) > 0.0) { - ColorTransform::TriStim smpte2084( - ToLinear(ColorSpace::TransferID::SMPTEST2084, colors[i].x()), - ToLinear(ColorSpace::TransferID::SMPTEST2084, colors[i].y()), - ToLinear(ColorSpace::TransferID::SMPTEST2084, colors[i].z())); - smpte2084.Scale(Luma(ret) / Luma(smpte2084)); - ret = ClipToWhite(&smpte2084); - } - colors[i] = ret; - } - } -}; - // BT2020 Constant Luminance is different than most other // ways to encode RGB values as YUV. The basic idea is that // transfer functions are applied on the Y value instead of @@ -764,61 +701,9 @@ // Then we run the transfer function like normal, and finally // this class is inserted as an extra step which takes calculates // the U and V values. -class ColorTransformToBT2020CL : public ColorTransformStep { - public: - bool Join(ColorTransformStep* next_untyped) override { - ColorTransformFromBT2020CL* next = next_untyped->GetFromBT2020CL(); - if (!next) - return false; - if (null_) - return false; - null_ = true; - return true; - } - - bool IsNull() override { return null_; } - - void Transform(ColorTransform::TriStim* RYB, size_t num) const override { - for (size_t i = 0; i < num; i++) { - float U, V; - float B_Y = RYB[i].z() - RYB[i].y(); - if (B_Y <= 0) { - U = B_Y / (-2.0 * -0.9702); - } else { - U = B_Y / (2.0 * 0.7910); - } - float R_Y = RYB[i].x() - RYB[i].y(); - if (R_Y <= 0) { - V = R_Y / (-2.0 * -0.8591); - } else { - V = R_Y / (2.0 * 0.4969); - } - RYB[i] = ColorTransform::TriStim(RYB[i].y(), U + 0.5, V + 0.5); - } - } - - private: - bool null_ = false; -}; - -// Inverse of ColorTransformToBT2020CL, see comment above for more info. class ColorTransformFromBT2020CL : public ColorTransformStep { public: - bool Join(ColorTransformStep* next_untyped) override { - ColorTransformToBT2020CL* next = next_untyped->GetToBT2020CL(); - if (!next) - return false; - if (null_) - return false; - null_ = true; - return true; - } - - bool IsNull() override { return null_; } - void Transform(ColorTransform::TriStim* YUV, size_t num) const override { - if (null_) - return; for (size_t i = 0; i < num; i++) { float Y = YUV[i].x(); float U = YUV[i].y() - 0.5; @@ -838,7 +723,6 @@ YUV[i] = ColorTransform::TriStim(R_Y + Y, Y, B_Y + Y); } } - bool CanAppendShaderSource() override { return true; } void AppendShaderSource(std::stringstream* hdr, std::stringstream* src, size_t step_index) const override { @@ -866,14 +750,14 @@ << "(color.rgb);" << endl; } - private: - bool null_ = false; + void AppendSkShaderSource(std::stringstream* src) const override { + NOTREACHED(); + } }; void ColorTransformInternal::AppendColorSpaceToColorSpaceTransform( - ColorSpace src, - const ColorSpace& dst, - ColorTransform::Intent intent) { + const ColorSpace& src, + const ColorSpace& dst) { steps_.push_back( std::make_unique<ColorTransformMatrix>(GetRangeAdjustMatrix(src))); @@ -895,10 +779,6 @@ if (src.GetTransferFunction(&src_to_linear_fn)) { steps_.push_back(std::make_unique<ColorTransformSkTransferFn>( src_to_linear_fn, src.HasExtendedSkTransferFn())); - } else if (src.GetTransferID() == - ColorSpace::TransferID::SMPTEST2084_NON_HDR) { - steps_.push_back( - std::make_unique<ColorTransformSMPTEST2048NonHdrToLinear>()); } else { steps_.push_back( std::make_unique<ColorTransformToLinear>(src.GetTransferID())); @@ -930,7 +810,7 @@ } if (dst.GetMatrixID() == ColorSpace::MatrixID::BT2020_CL) { - steps_.push_back(std::make_unique<ColorTransformToBT2020CL>()); + NOTREACHED(); } else { steps_.push_back( std::make_unique<ColorTransformMatrix>(GetTransferMatrix(dst))); @@ -948,13 +828,7 @@ // TODO(ccameron): We may want dst assume sRGB at some point in the future. if (!src_.IsValid()) return; - - // SMPTEST2084_NON_HDR is not a valid destination. - if (dst.GetTransferID() == ColorSpace::TransferID::SMPTEST2084_NON_HDR) { - DLOG(ERROR) << "Invalid dst transfer function, returning identity."; - return; - } - AppendColorSpaceToColorSpaceTransform(src_, dst_, intent); + AppendColorSpaceToColorSpaceTransform(src_, dst_); if (intent != Intent::TEST_NO_OPT) Simplify(); } @@ -981,14 +855,6 @@ return src.str(); } -bool ColorTransformInternal::CanGetShaderSource() const { - for (const auto& step : steps_) { - if (!step->CanAppendShaderSource()) - return false; - } - return true; -} - ColorTransformInternal::~ColorTransformInternal() {} void ColorTransformInternal::Simplify() {
diff --git a/ui/gfx/color_transform.h b/ui/gfx/color_transform.h index 064ad1c..db7d75d8 100644 --- a/ui/gfx/color_transform.h +++ b/ui/gfx/color_transform.h
@@ -33,7 +33,6 @@ // Return GLSL shader source that defines a function DoColorConversion that // converts a vec3 according to this transform. - virtual bool CanGetShaderSource() const = 0; virtual std::string GetShaderSource() const = 0; // Return SKSL shader sources that modifies an "inout half4 color" according
diff --git a/ui/gfx/color_transform_unittest.cc b/ui/gfx/color_transform_unittest.cc index e98a2f4..4139839 100644 --- a/ui/gfx/color_transform_unittest.cc +++ b/ui/gfx/color_transform_unittest.cc
@@ -52,7 +52,6 @@ // This one is weird as the non-linear numbers are not between 0 and 1. ColorSpace::TransferID noninvertible_transfers[] = { ColorSpace::TransferID::SMPTEST428_1, - ColorSpace::TransferID::SMPTEST2084_NON_HDR, }; ColorSpace::TransferID extended_transfers[] = { @@ -61,15 +60,18 @@ }; ColorSpace::MatrixID all_matrices[] = { - ColorSpace::MatrixID::RGB, ColorSpace::MatrixID::BT709, - ColorSpace::MatrixID::FCC, ColorSpace::MatrixID::BT470BG, - ColorSpace::MatrixID::SMPTE170M, ColorSpace::MatrixID::SMPTE240M, + ColorSpace::MatrixID::RGB, + ColorSpace::MatrixID::BT709, + ColorSpace::MatrixID::FCC, + ColorSpace::MatrixID::BT470BG, + ColorSpace::MatrixID::SMPTE170M, + ColorSpace::MatrixID::SMPTE240M, // YCOCG produces lots of negative values which isn't compatible with many // transfer functions. // TODO(hubbe): Test this separately. // ColorSpace::MatrixID::YCOCG, - ColorSpace::MatrixID::BT2020_NCL, ColorSpace::MatrixID::BT2020_CL, + ColorSpace::MatrixID::BT2020_NCL, ColorSpace::MatrixID::YDZDX, }; @@ -513,9 +515,6 @@ for (const auto& dst : common_color_spaces) { auto transform = ColorTransform::NewColorTransform( src, dst, ColorTransform::Intent::INTENT_PERCEPTUAL); - if (!transform->CanGetShaderSource()) - continue; - std::string source = "void main(inout half4 color) {" + transform->GetSkShaderSource() + "}"; SkRuntimeColorFilterFactory factory(
diff --git a/ui/gfx/mojom/color_space.mojom b/ui/gfx/mojom/color_space.mojom index 78891112..2af7bcc5 100644 --- a/ui/gfx/mojom/color_space.mojom +++ b/ui/gfx/mojom/color_space.mojom
@@ -47,7 +47,6 @@ SMPTEST2084, SMPTEST428_1, ARIB_STD_B67, - SMPTEST2084_NON_HDR, IEC61966_2_1_HDR, LINEAR_HDR, CUSTOM
diff --git a/ui/gfx/mojom/color_space_mojom_traits.h b/ui/gfx/mojom/color_space_mojom_traits.h index 5621f95..9997436 100644 --- a/ui/gfx/mojom/color_space_mojom_traits.h +++ b/ui/gfx/mojom/color_space_mojom_traits.h
@@ -156,8 +156,6 @@ return gfx::mojom::ColorSpaceTransferID::SMPTEST428_1; case gfx::ColorSpace::TransferID::ARIB_STD_B67: return gfx::mojom::ColorSpaceTransferID::ARIB_STD_B67; - case gfx::ColorSpace::TransferID::SMPTEST2084_NON_HDR: - return gfx::mojom::ColorSpaceTransferID::SMPTEST2084_NON_HDR; case gfx::ColorSpace::TransferID::IEC61966_2_1_HDR: return gfx::mojom::ColorSpaceTransferID::IEC61966_2_1_HDR; case gfx::ColorSpace::TransferID::LINEAR_HDR: @@ -232,9 +230,6 @@ case gfx::mojom::ColorSpaceTransferID::ARIB_STD_B67: *out = gfx::ColorSpace::TransferID::ARIB_STD_B67; return true; - case gfx::mojom::ColorSpaceTransferID::SMPTEST2084_NON_HDR: - *out = gfx::ColorSpace::TransferID::SMPTEST2084_NON_HDR; - return true; case gfx::mojom::ColorSpaceTransferID::IEC61966_2_1_HDR: *out = gfx::ColorSpace::TransferID::IEC61966_2_1_HDR; return true;
diff --git a/ui/gl/yuv_to_rgb_converter.cc b/ui/gl/yuv_to_rgb_converter.cc index e85c85dd..a5169cd7 100644 --- a/ui/gl/yuv_to_rgb_converter.cc +++ b/ui/gl/yuv_to_rgb_converter.cc
@@ -98,7 +98,6 @@ gfx::ColorTransform::NewColorTransform( color_space, color_space.GetAsFullRangeRGB(), gfx::ColorTransform::Intent::INTENT_PERCEPTUAL); - DCHECK(color_transform->CanGetShaderSource()); std::string do_color_conversion = color_transform->GetShaderSource(); const char* fragment_header = nullptr;
diff --git a/ui/views/widget/native_widget_mac.mm b/ui/views/widget/native_widget_mac.mm index 137d244..83dca0de 100644 --- a/ui/views/widget/native_widget_mac.mm +++ b/ui/views/widget/native_widget_mac.mm
@@ -883,8 +883,11 @@ NativeWidgetMacNSWindowHost::GetFromNativeView(native_view); if (!window_host) return nullptr; - while (window_host->parent()) + while (window_host->parent()) { + if (window_host->native_widget_mac()->GetWidget()->is_top_level()) + break; window_host = window_host->parent(); + } return window_host->native_widget_mac(); }
diff --git a/ui/views/widget/native_widget_mac_unittest.mm b/ui/views/widget/native_widget_mac_unittest.mm index 6735f70..ff72483 100644 --- a/ui/views/widget/native_widget_mac_unittest.mm +++ b/ui/views/widget/native_widget_mac_unittest.mm
@@ -737,6 +737,7 @@ Widget* child = new Widget; Widget::InitParams init_params; init_params.parent = anchor_view.get(); + init_params.child = true; init_params.type = Widget::InitParams::TYPE_POPUP; child->Init(std::move(init_params)); return child; @@ -753,6 +754,7 @@ EXPECT_EQ(1u, children.size()); Widget* child = AttachPopupToNativeParent(native_parent); + EXPECT_FALSE(child->is_top_level()); TestWidgetObserver child_observer(child); // GetTopLevelNativeWidget() will go up through |native_parent|'s Widget.
diff --git a/ui/views/widget/widget.cc b/ui/views/widget/widget.cc index af72459..8ff27f1 100644 --- a/ui/views/widget/widget.cc +++ b/ui/views/widget/widget.cc
@@ -460,11 +460,12 @@ } void Widget::NotifyNativeViewHierarchyWillChange() { - FocusManager* focus_manager = GetFocusManager(); - // We are being removed from a window hierarchy. Treat this as - // the root_view_ being removed. - if (focus_manager) - focus_manager->ViewRemoved(root_view_.get()); + // During tear-down the top-level focus manager becomes unavailable to + // GTK tabbed panes and their children, so normal deregistration via + // |FocusManager::ViewRemoved()| calls are fouled. We clear focus here + // to avoid these redundant steps and to avoid accessing deleted views + // that may have been in focus. + ClearFocusFromWidget(); } void Widget::NotifyNativeViewHierarchyChanged() { @@ -613,14 +614,7 @@ widget_closed_ = true; closed_reason_ = closed_reason; SaveWindowPlacement(); - - // During tear-down the top-level focus manager becomes unavailable to - // GTK tabbed panes and their children, so normal deregistration via - // |FocusManager::ViewRemoved()| calls are fouled. We clear focus here - // to avoid these redundant steps and to avoid accessing deleted views - // that may have been in focus. - if (is_top_level() && focus_manager_) - focus_manager_->SetFocusedView(nullptr); + ClearFocusFromWidget(); for (WidgetObserver& observer : observers_) observer.OnWidgetClosing(this); @@ -1525,8 +1519,7 @@ } void Widget::DestroyRootView() { - if (is_top_level() && focus_manager_) - focus_manager_->SetFocusedView(nullptr); + ClearFocusFromWidget(); NotifyWillRemoveView(root_view_.get()); non_client_view_ = nullptr; // Remove all children before the unique_ptr reset so that @@ -1662,6 +1655,14 @@ widget_delegate()->OnPaintAsActiveChanged(paint_as_active); } +void Widget::ClearFocusFromWidget() { + FocusManager* focus_manager = GetFocusManager(); + // We are being removed from a window hierarchy. Treat this as + // the root_view_ being removed. + if (focus_manager) + focus_manager->ViewRemoved(root_view_.get()); +} + namespace internal { ////////////////////////////////////////////////////////////////////////////////
diff --git a/ui/views/widget/widget.h b/ui/views/widget/widget.h index 88cb98ff..1c6330d 100644 --- a/ui/views/widget/widget.h +++ b/ui/views/widget/widget.h
@@ -994,6 +994,9 @@ // Notifies the window frame that the active rendering state has changed. void UpdatePaintAsActiveState(bool paint_as_active); + // If a descendent of |root_view_| is focused, then clear the focus. + void ClearFocusFromWidget(); + static bool g_disable_activation_change_handling_; internal::NativeWidgetPrivate* native_widget_ = nullptr;
diff --git a/ui/webui/resources/html/search_highlight_utils.html b/ui/webui/resources/html/search_highlight_utils.html index 7bc5c69..933de81 100644 --- a/ui/webui/resources/html/search_highlight_utils.html +++ b/ui/webui/resources/html/search_highlight_utils.html
@@ -1 +1,2 @@ +<link rel="import" href="assert.html"> <script src="../js/search_highlight_utils.js"></script>
diff --git a/ui/webui/resources/js/BUILD.gn b/ui/webui/resources/js/BUILD.gn index baebf22b..4099959 100644 --- a/ui/webui/resources/js/BUILD.gn +++ b/ui/webui/resources/js/BUILD.gn
@@ -59,6 +59,7 @@ js_library("search_highlight_utils") { deps = [ + ":assert", ":cr", ] }
diff --git a/ui/webui/resources/js/search_highlight_utils.js b/ui/webui/resources/js/search_highlight_utils.js index 11d7cc3d..1910528 100644 --- a/ui/webui/resources/js/search_highlight_utils.js +++ b/ui/webui/resources/js/search_highlight_utils.js
@@ -95,11 +95,26 @@ * should already be visible or the bubble will render incorrectly. * @param {!HTMLElement} element The element to be highlighted. * @param {string} rawQuery The search query. + * @param {boolean=} horizontallyCenter Whether or not to horizontally center + * the shown search bubble (if any) based on |element|'s left and width. * @return {?Node} The search bubble that was added, or null if no new bubble * was added. */ - /* #export */ function highlightControlWithBubble(element, rawQuery) { - let searchBubble = element.querySelector(`.${SEARCH_BUBBLE_CSS_CLASS}`); + /* #export */ function highlightControlWithBubble( + element, rawQuery, horizontallyCenter) { + let anchor = element; + if (element.tagName === 'SELECT') { + anchor = element.parentNode; + } + // NOTE(dbeam): this is theoretically only possible in the select case, but + // callers are often fast and loose with regard to casting |element| from a + // parentNode (which can easily be a shadow root). So we leave this if for + // all branches (rather than solely inside the select branch). + if (anchor instanceof ShadowRoot) { + anchor = anchor.host.parentNode; + } + + let searchBubble = anchor.querySelector(`.${SEARCH_BUBBLE_CSS_CLASS}`); // If the element has already been highlighted, there is no need to do // anything. if (searchBubble) { @@ -112,13 +127,18 @@ innards.classList.add('search-bubble-innards'); innards.textContent = rawQuery; searchBubble.appendChild(innards); - element.appendChild(searchBubble); + anchor.appendChild(searchBubble); const updatePosition = function() { + assert(typeof element.offsetTop === 'number'); searchBubble.style.top = element.offsetTop + (innards.classList.contains('above') ? -searchBubble.offsetHeight : element.offsetHeight) + 'px'; + if (horizontallyCenter) { + const width = element.offsetWidth - searchBubble.offsetWidth; + searchBubble.style.left = element.offsetLeft + width / 2 + 'px'; + } }; updatePosition(); @@ -126,6 +146,9 @@ innards.classList.toggle('above'); updatePosition(); }); + // TODO(crbug.com/355446): create a way to programmatically update these + // bubbles (i.e. call updatePosition()) when outer scope knows they need to + // be repositioned. return searchBubble; }
diff --git a/ui/wm/test/testing_cursor_client_observer.h b/ui/wm/test/testing_cursor_client_observer.h index 2698935..e6fbccc 100644 --- a/ui/wm/test/testing_cursor_client_observer.h +++ b/ui/wm/test/testing_cursor_client_observer.h
@@ -2,6 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#ifndef UI_WM_TEST_TESTING_CURSOR_CLIENT_OBSERVER_H_ +#define UI_WM_TEST_TESTING_CURSOR_CLIENT_OBSERVER_H_ + #include "ui/aura/client/cursor_client_observer.h" #include "ui/wm/core/cursor_manager.h" @@ -32,3 +35,5 @@ }; } // namespace wm + +#endif // UI_WM_TEST_TESTING_CURSOR_CLIENT_OBSERVER_H_
diff --git a/weblayer/browser/content_browser_client_impl.cc b/weblayer/browser/content_browser_client_impl.cc index 9b1b82a7..83475eac 100644 --- a/weblayer/browser/content_browser_client_impl.cc +++ b/weblayer/browser/content_browser_client_impl.cc
@@ -32,9 +32,12 @@ #include "services/network/network_service.h" #include "services/network/public/mojom/network_context.mojom.h" #include "services/network/public/mojom/network_service.mojom.h" +#include "services/service_manager/public/cpp/binder_map.h" #include "storage/browser/quota/quota_settings.h" #include "third_party/blink/public/common/loader/url_loader_throttle.h" #include "third_party/blink/public/common/user_agent/user_agent_metadata.h" +#include "third_party/blink/public/mojom/installedapp/installed_app_provider.mojom.h" +#include "third_party/blink/public/mojom/installedapp/related_application.mojom.h" #include "url/gurl.h" #include "url/origin.h" #include "weblayer/browser/browser_main_parts_impl.h" @@ -105,6 +108,29 @@ const std::string& serialized_report) override {} }; +#if defined(OS_ANDROID) +// TODO(https://crbug.com/1037884): Remove this. +class StubInstalledAppProvider : public blink::mojom::InstalledAppProvider { + public: + StubInstalledAppProvider() {} + ~StubInstalledAppProvider() override = default; + + // InstalledAppProvider overrides: + void FilterInstalledApps( + std::vector<blink::mojom::RelatedApplicationPtr> related_apps, + FilterInstalledAppsCallback callback) override { + std::move(callback).Run(std::vector<blink::mojom::RelatedApplicationPtr>()); + } + + static void Create( + content::RenderFrameHost* rfh, + mojo::PendingReceiver<blink::mojom::InstalledAppProvider> receiver) { + mojo::MakeSelfOwnedReceiver(std::make_unique<StubInstalledAppProvider>(), + std::move(receiver)); + } +}; +#endif + } // namespace namespace weblayer { @@ -354,6 +380,16 @@ #endif // defined(OS_ANDROID) } +void ContentBrowserClientImpl::RegisterBrowserInterfaceBindersForFrame( + content::RenderFrameHost* render_frame_host, + service_manager::BinderMapWithContext<content::RenderFrameHost*>* map) { +#if defined(OS_ANDROID) + // TODO(https://crbug.com/1037884): Remove this. + map->Add<blink::mojom::InstalledAppProvider>( + base::BindRepeating(&StubInstalledAppProvider::Create)); +#endif +} + void ContentBrowserClientImpl::GetQuotaSettings( content::BrowserContext* context, content::StoragePartition* partition,
diff --git a/weblayer/browser/content_browser_client_impl.h b/weblayer/browser/content_browser_client_impl.h index dbbee63..c869f91 100644 --- a/weblayer/browser/content_browser_client_impl.h +++ b/weblayer/browser/content_browser_client_impl.h
@@ -74,6 +74,10 @@ service_manager::BinderRegistry* registry, blink::AssociatedInterfaceRegistry* associated_registry, content::RenderProcessHost* render_process_host) override; + void RegisterBrowserInterfaceBindersForFrame( + content::RenderFrameHost* render_frame_host, + service_manager::BinderMapWithContext<content::RenderFrameHost*>* map) + override; void GetQuotaSettings( content::BrowserContext* context, content::StoragePartition* partition,
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/CrashReporterControllerImpl.java b/weblayer/browser/java/org/chromium/weblayer_private/CrashReporterControllerImpl.java index dc2be0d..ed43222 100644 --- a/weblayer/browser/java/org/chromium/weblayer_private/CrashReporterControllerImpl.java +++ b/weblayer/browser/java/org/chromium/weblayer_private/CrashReporterControllerImpl.java
@@ -48,15 +48,7 @@ static CrashReporterControllerImpl sInstance = new CrashReporterControllerImpl(); } - private CrashReporterControllerImpl() { - ChildProcessCrashObserver.registerCrashCallback( - new ChildProcessCrashObserver.ChildCrashedCallback() { - @Override - public void childCrashed(int pid) { - processNewMinidumps(); - } - }); - } + private CrashReporterControllerImpl() {} public static CrashReporterControllerImpl getInstance() { return Holder.sInstance; @@ -144,6 +136,15 @@ if (mIsNativeInitialized) { processNewMinidumps(); } + + // Now that there is a client, register to observe child process crashes. + ChildProcessCrashObserver.registerCrashCallback( + new ChildProcessCrashObserver.ChildCrashedCallback() { + @Override + public void childCrashed(int pid) { + processNewMinidumps(); + } + }); } /** Start an async task to import crashes, and notify if any are found. */