diff --git a/.gn b/.gn index ff381c5..6fd1763 100644 --- a/.gn +++ b/.gn
@@ -74,7 +74,7 @@ # their includes checked for proper dependencies when you run either # "gn check" or "gn gen --check". check_targets = [ - #"//apps/*", # Medium-hard. + "//apps/*", "//ash/*", "//base/*", "//blink/*", @@ -90,8 +90,7 @@ "//chrome/browser/accessibility/*", "//chrome/browser/android/*", "//chrome/browser/app_mode/*", - - #"//chrome/browser/apps/*", # 2 errors + "//chrome/browser/apps/*", "//chrome/browser/assist_ranker/*", "//chrome/browser/autocomplete/*", "//chrome/browser/autofill/*", @@ -225,8 +224,7 @@ "//chrome/browser/upgrade_detector/*", "//chrome/browser/usb/*", "//chrome/browser/vr/*", - - #"//chrome/browser/web_applications/*", # 66 errors + "//chrome/browser/web_applications/*", "//chrome/browser/webauthn/*", "//chrome/browser/webshare/*", "//chrome/browser/win/*",
diff --git a/BUILD.gn b/BUILD.gn index 8e8650d..8f2f9af 100644 --- a/BUILD.gn +++ b/BUILD.gn
@@ -1153,7 +1153,7 @@ data_deps += [ "components/offline_pages/resources:closure_compile" ] } if (is_win && is_chrome_branded) { - data_deps += [ "components/nux_google_apps/resources:closure_compile" ] + data_deps += [ "components/nux/resources:closure_compile" ] } } }
diff --git a/DEPS b/DEPS index 69f9885..2b194c6 100644 --- a/DEPS +++ b/DEPS
@@ -105,7 +105,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Skia # and whatever else without interference from each other. - 'skia_revision': '92b161fab40fe1f90661fed6802e0cb3a1c4e1e3', + 'skia_revision': '5953a476d9f74baa9e61ab14f71b2d211fca9721', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. @@ -129,7 +129,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. - 'pdfium_revision': '7e7e0b8379c4bdcf3e16cd2298afe49f03fefdfb', + 'pdfium_revision': 'ee0c9aa662692b14ec07d21d83c80aba8a873749', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling openmax_dl # and whatever else without interference from each other. @@ -165,7 +165,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': 'c67a80df267950d61d062c90aa9ea22a43f24f2c', + 'catapult_revision': 'd95dde6e066fe1b0ef88d3e0e5ccb5cae48b05a9', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other. @@ -604,7 +604,7 @@ }, 'src/third_party/depot_tools': - Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '29361ca11fa37bfe9961af093edaf60c37d2db96', + Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '0ec9d15571fb274b817e3f0336a78bfd35b75e50', 'src/third_party/devtools-node-modules': Var('chromium_git') + '/external/github.com/ChromeDevTools/devtools-node-modules' + '@' + Var('devtools_node_modules_revision'), @@ -750,7 +750,7 @@ Var('chromium_git') + '/chromium/deps/hunspell_dictionaries.git' + '@' + 'a9bac57ce6c9d390a52ebaad3259f5fdb871210e', 'src/third_party/icu': - Var('chromium_git') + '/chromium/deps/icu.git' + '@' + '297a4dd02b9d36c92ab9b4f121e433c9c3bc14f8', + Var('chromium_git') + '/chromium/deps/icu.git' + '@' + 'a191af9d025859e8368b8b469120d78006e9f5f6', 'src/third_party/icu4j': { 'packages': [ @@ -853,7 +853,7 @@ }, 'src/third_party/libvpx/source/libvpx': - Var('chromium_git') + '/webm/libvpx.git' + '@' + '6c62530c666fc0bcf4385a35a7c49e44c9f38cf5', + Var('chromium_git') + '/webm/libvpx.git' + '@' + 'dbcb89be244e03074ee80e7bc6d5c22e6fc5dd79', 'src/third_party/libwebm/source': Var('chromium_git') + '/webm/libwebm.git' + '@' + '01c1d1d76f139345c442bfc8e61b4e1cba809059', @@ -954,7 +954,7 @@ }, 'src/third_party/perfetto': - Var('android_git') + '/platform/external/perfetto.git' + '@' + 'a4238afbd1d086db841126957d779b506dc4e2b6', + Var('android_git') + '/platform/external/perfetto.git' + '@' + '46ef92275f435ab46cfa6e848e844d50a9067da9', 'src/third_party/perl': { 'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + 'ac0d98b5cee6c024b0cffeb4f8f45b6fc5ccdb78',
diff --git a/apps/BUILD.gn b/apps/BUILD.gn index 271934ab..75a2adf 100644 --- a/apps/BUILD.gn +++ b/apps/BUILD.gn
@@ -62,5 +62,6 @@ public_deps = [ "//content/public/browser", + "//extensions/browser", ] }
diff --git a/ash/BUILD.gn b/ash/BUILD.gn index a68e6f8..7a72e4f 100644 --- a/ash/BUILD.gn +++ b/ash/BUILD.gn
@@ -23,653 +23,63 @@ assert(use_ozone) component("ash") { - friend = [ - ":ash_unittests", - ":test_support_common", - ] + # All targets in this file are allowed to access any the headers in ash. + friend = [ ":*" ] + public = [ - "accelerators/accelerator_commands.h", - "accelerators/accelerator_confirmation_dialog.h", - "accelerators/accelerator_controller.h", - "accelerators/accelerator_delegate.h", - "accelerators/accelerator_ids.h", - "accelerators/accelerator_router.h", - "accelerators/accelerator_table.h", - "accelerators/ash_focus_manager_factory.h", - "accelerators/debug_commands.h", - "accelerators/exit_warning_handler.h", - "accelerators/key_hold_detector.h", - "accelerators/magnifier_key_scroller.h", - "accelerators/spoken_feedback_toggler.h", - "accessibility/accessibility_controller.h", - "accessibility/accessibility_cursor_ring_layer.h", - "accessibility/accessibility_delegate.h", - "accessibility/accessibility_focus_ring.h", - "accessibility/accessibility_focus_ring_controller.h", - "accessibility/accessibility_focus_ring_group.h", - "accessibility/accessibility_focus_ring_layer.h", - "accessibility/accessibility_highlight_controller.h", - "accessibility/accessibility_highlight_layer.h", - "accessibility/accessibility_layer.h", - "accessibility/accessibility_observer.h", - "accessibility/accessibility_panel_layout_manager.h", - "accessibility/default_accessibility_delegate.h", - "accessibility/focus_ring_controller.h", - "accessibility/focus_ring_layer.h", - "accessibility/key_accessibility_enabler.h", - "accessibility/layer_animation_info.h", - "accessibility/spoken_feedback_enabler.h", - "accessibility/touch_accessibility_enabler.h", - "accessibility/touch_exploration_controller.h", - "accessibility/touch_exploration_manager.h", - "animation/animation_change_type.h", - "app_list/app_list_controller_impl.h", - "app_list/app_list_presenter_delegate_impl.h", - "ash_export.h", + # This is the only header that should be used externally. "ash_service.h", - "assistant/assistant_cache_controller.h", - "assistant/assistant_controller.h", - "assistant/assistant_controller_observer.h", - "assistant/assistant_interaction_controller.h", - "assistant/assistant_notification_controller.h", - "assistant/assistant_screen_context_controller.h", - "assistant/assistant_setup_controller.h", - "assistant/assistant_ui_controller.h", - "assistant/model/assistant_cache_model.h", - "assistant/model/assistant_cache_model_observer.h", - "assistant/model/assistant_interaction_model.h", - "assistant/model/assistant_interaction_model_observer.h", - "assistant/model/assistant_query.h", - "assistant/model/assistant_response.h", - "assistant/model/assistant_screen_context_model.h", - "assistant/model/assistant_screen_context_model_observer.h", - "assistant/model/assistant_ui_element.h", - "assistant/model/assistant_ui_model.h", - "assistant/model/assistant_ui_model_observer.h", - "assistant/ui/assistant_container_view.h", - "assistant/ui/assistant_main_view.h", - "assistant/ui/assistant_mini_view.h", - "assistant/ui/assistant_scroll_view.h", - "assistant/ui/assistant_web_view.h", - "assistant/ui/caption_bar.h", - "assistant/ui/dialog_plate/action_view.h", - "assistant/ui/dialog_plate/dialog_plate.h", - "assistant/ui/logo_view/base_logo_view.h", - "assistant/ui/main_stage/assistant_footer_view.h", - "assistant/ui/main_stage/assistant_header_view.h", - "assistant/ui/main_stage/assistant_main_stage.h", - "assistant/ui/main_stage/assistant_opt_in_view.h", - "assistant/ui/main_stage/assistant_progress_indicator.h", - "assistant/ui/main_stage/assistant_query_view.h", - "assistant/ui/main_stage/assistant_text_element_view.h", - "assistant/ui/main_stage/suggestion_container_view.h", - "assistant/ui/main_stage/ui_element_container_view.h", - "assistant/util/animation_util.h", - "assistant/util/deep_link_util.h", - "autoclick/autoclick_controller.h", - "cancel_mode.h", - "cast_config_controller.h", - "client_image_registry.h", - "dbus/ash_dbus_services.h", - "dbus/display_service_provider.h", - "dbus/liveness_service_provider.h", - "dbus/url_handler_service_provider.h", - "debug.h", + + # TODO: move the following to source. Do NOT add new files here. + "accelerators/accelerator_controller.h", + "accessibility/accessibility_controller.h", + "accessibility/accessibility_delegate.h", + "accessibility/focus_ring_controller.h", + "app_list/app_list_controller_impl.h", "detachable_base/detachable_base_handler.h", - "detachable_base/detachable_base_notification_controller.h", "detachable_base/detachable_base_observer.h", - "detachable_base/detachable_base_pairing_status.h", - "disconnected_app_handler.h", - "display/ash_display_controller.h", - "display/cros_display_config.h", - "display/cursor_window_controller.h", - "display/display_animator.h", - "display/display_color_manager.h", - "display/display_configuration_controller.h", - "display/display_configuration_observer.h", - "display/display_error_observer.h", - "display/display_move_window_util.h", "display/display_prefs.h", - "display/display_shutdown_observer.h", - "display/display_util.h", - "display/event_transformation_handler.h", - "display/extended_mouse_warp_controller.h", - "display/mirror_window_controller.h", - "display/mouse_cursor_event_filter.h", - "display/mouse_warp_controller.h", - "display/null_mouse_warp_controller.h", - "display/overscan_calibrator.h", - "display/persistent_window_controller.h", - "display/persistent_window_info.h", - "display/projecting_observer.h", - "display/resolution_notification_controller.h", - "display/root_window_transformers.h", - "display/screen_ash.h", "display/screen_orientation_controller.h", - "display/screen_position_controller.h", - "display/shared_display_edge_indicator.h", - "display/touch_calibrator_controller.h", - "display/touch_calibrator_view.h", - "display/unified_mouse_warp_controller.h", - "display/window_tree_host_manager.h", - "drag_drop/drag_drop_controller.h", - "drag_drop/drag_drop_tracker.h", - "drag_drop/drag_image_view.h", "events/event_rewriter_controller.h", - "events/keyboard_driven_event_rewriter.h", - "events/spoken_feedback_event_rewriter.h", - "first_run/desktop_cleaner.h", - "first_run/first_run_helper.h", "focus_cycler.h", - "frame/caption_buttons/caption_button_types.h", "frame/caption_buttons/frame_back_button.h", - "frame/caption_buttons/frame_caption_button.h", "frame/caption_buttons/frame_caption_button_container_view.h", - "frame/caption_buttons/frame_size_button.h", - "frame/caption_buttons/frame_size_button_delegate.h", "frame/custom_frame_header.h", "frame/default_frame_header.h", - "frame/detached_title_area_renderer.h", - "frame/frame_header.h", "frame/frame_header_util.h", "frame/header_view.h", "frame/non_client_frame_view_ash.h", "frame/wide_frame_view.h", - "high_contrast/high_contrast_controller.h", - "highlighter/highlighter_controller.h", - "highlighter/highlighter_gesture_util.h", - "highlighter/highlighter_result_view.h", - "highlighter/highlighter_view.h", - "host/ash_window_tree_host.h", - "host/ash_window_tree_host_init_params.h", - "host/ash_window_tree_host_mirroring_delegate.h", - "host/ash_window_tree_host_mirroring_unified.h", - "host/ash_window_tree_host_platform.h", - "host/ash_window_tree_host_unified.h", - "host/root_window_transformer.h", - "host/transformer_helper.h", - "ime/ime_controller.h", - "ime/ime_focus_handler.h", - "ime/ime_switch_type.h", - "keyboard/virtual_keyboard_container_layout_manager.h", - "keyboard/virtual_keyboard_controller.h", - "laser/laser_pointer_controller.h", - "laser/laser_pointer_view.h", - "laser/laser_segment_utils.h", - "lock_screen_action/lock_screen_action_background_controller.h", - "lock_screen_action/lock_screen_action_background_controller_impl.h", - "lock_screen_action/lock_screen_action_background_controller_stub.h", - "lock_screen_action/lock_screen_action_background_observer.h", - "lock_screen_action/lock_screen_action_background_state.h", - "lock_screen_action/lock_screen_action_background_view.h", - "lock_screen_action/lock_screen_note_display_state_handler.h", - "lock_screen_action/lock_screen_note_launcher.h", - "login/login_screen_controller.h", - "login/login_screen_controller_observer.h", - "login/ui/animated_rounded_image_view.h", - "login/ui/animation_frame.h", - "login/ui/arrow_button_view.h", - "login/ui/horizontal_image_sequence_animation_decoder.h", - "login/ui/hover_notifier.h", - "login/ui/image_parser.h", - "login/ui/lock_contents_view.h", - "login/ui/lock_debug_view.h", - "login/ui/lock_screen.h", "login/ui/lock_window.h", - "login/ui/login_auth_user_view.h", - "login/ui/login_base_bubble_view.h", - "login/ui/login_big_user_view.h", - "login/ui/login_bubble.h", - "login/ui/login_button.h", - "login/ui/login_data_dispatcher.h", - "login/ui/login_detachable_base_model.h", - "login/ui/login_expanded_public_account_view.h", - "login/ui/login_menu_view.h", - "login/ui/login_password_view.h", - "login/ui/login_pin_view.h", - "login/ui/login_public_account_user_view.h", - "login/ui/login_user_view.h", - "login/ui/non_accessible_view.h", - "login/ui/note_action_launch_button.h", - "login/ui/pin_keyboard_animation.h", - "login/ui/public_account_warning_dialog.h", - "login/ui/scrollable_users_list_view.h", - "login/ui/user_switch_flip_animation.h", - "login/ui/views_utils.h", - "login_status.h", - "magnifier/docked_magnifier_controller.h", "magnifier/magnification_controller.h", - "magnifier/magnifier_scale_utils.h", - "magnifier/partial_magnification_controller.h", - "media_controller.h", - "message_center/arc_notification_manager_delegate_impl.h", - "message_center/ash_message_center_lock_screen_controller.h", - "message_center/message_center_bubble.h", - "message_center/message_center_button_bar.h", - "message_center/message_center_controller.h", - "message_center/message_center_scroll_bar.h", - "message_center/message_center_style.h", - "message_center/message_center_ui_controller.h", - "message_center/message_center_ui_delegate.h", - "message_center/message_center_view.h", - "message_center/message_list_view.h", - "message_center/notifier_settings_view.h", - "metrics/desktop_task_switch_metric_recorder.h", - "metrics/gesture_action_type.h", - "metrics/login_metrics_recorder.h", - "metrics/pointer_metrics_recorder.h", - "metrics/task_switch_metrics_recorder.h", - "metrics/task_switch_source.h", - "metrics/task_switch_time_tracker.h", - "metrics/time_to_first_present_recorder.h", - "metrics/user_metrics_action.h", - "metrics/user_metrics_recorder.h", - "mojo_interface_factory.h", - "multi_device_setup/multi_device_notification_presenter.h", - "multi_profile_uma.h", - "network_connect_delegate_mus.h", "new_window_controller.h", - "note_taking_controller.h", - "pointer_watcher_adapter.h", - "policy/policy_recommendation_restorer.h", "root_window_controller.h", - "root_window_settings.h", - "rotator/screen_rotation_animation.h", - "rotator/screen_rotation_animator.h", - "rotator/screen_rotation_animator_observer.h", - "rotator/window_rotation.h", - "scoped_root_window_for_new_windows.h", - "screen_util.h", "screenshot_delegate.h", - "session/multiprofiles_intro_dialog.h", - "session/session_aborted_dialog.h", - "session/session_activation_observer_holder.h", "session/session_controller.h", - "session/session_observer.h", - "session/teleport_warning_dialog.h", - "shelf/app_list_button.h", - "shelf/app_list_shelf_item_delegate.h", - "shelf/assistant_overlay.h", - "shelf/back_button.h", - "shelf/ink_drop_button_listener.h", - "shelf/login_shelf_view.h", - "shelf/overflow_bubble.h", - "shelf/overflow_bubble_view.h", - "shelf/overflow_button.h", "shelf/shelf.h", - "shelf/shelf_application_menu_model.h", - "shelf/shelf_background_animator.h", - "shelf/shelf_background_animator_observer.h", - "shelf/shelf_bezel_event_handler.h", - "shelf/shelf_button.h", - "shelf/shelf_button_pressed_metric_tracker.h", - "shelf/shelf_constants.h", - "shelf/shelf_context_menu_model.h", - "shelf/shelf_controller.h", - "shelf/shelf_layout_manager.h", - "shelf/shelf_layout_manager_observer.h", - "shelf/shelf_locking_manager.h", - "shelf/shelf_menu_model_adapter.h", - "shelf/shelf_observer.h", - "shelf/shelf_tooltip_bubble.h", - "shelf/shelf_tooltip_bubble_base.h", - "shelf/shelf_tooltip_manager.h", - "shelf/shelf_tooltip_preview_bubble.h", - "shelf/shelf_view.h", "shelf/shelf_widget.h", - "shelf/shelf_window_targeter.h", - "shelf/shelf_window_watcher.h", - "shelf/shelf_window_watcher_item_delegate.h", - "shelf/window_preview.h", "shell.h", "shell_delegate.h", - "shell_delegate_mash.h", "shell_init_params.h", "shell_observer.h", - "shell_state.h", - "shutdown_controller.h", - "shutdown_reason.h", "sticky_keys/sticky_keys_controller.h", - "sticky_keys/sticky_keys_overlay.h", - "sticky_keys/sticky_keys_state.h", - "system/accessibility/dictation_button_tray.h", - "system/accessibility/select_to_speak_tray.h", "system/accessibility/select_to_speak_tray_utils.h", - "system/audio/audio_detailed_view.h", - "system/audio/display_speaker_controller.h", - "system/audio/tray_audio.h", - "system/audio/unified_audio_detailed_view_controller.h", - "system/audio/unified_volume_slider_controller.h", - "system/audio/unified_volume_view.h", - "system/audio/volume_view.h", - "system/bluetooth/bluetooth_detailed_view.h", - "system/bluetooth/bluetooth_feature_pod_controller.h", - "system/bluetooth/bluetooth_notification_controller.h", - "system/bluetooth/bluetooth_observer.h", - "system/bluetooth/bluetooth_power_controller.h", - "system/bluetooth/tray_bluetooth.h", - "system/bluetooth/tray_bluetooth_helper.h", - "system/bluetooth/unified_bluetooth_detailed_view_controller.h", - "system/brightness/brightness_controller_chromeos.h", - "system/brightness/tray_brightness.h", - "system/brightness/unified_brightness_slider_controller.h", - "system/brightness/unified_brightness_view.h", - "system/brightness_control_delegate.h", - "system/caps_lock_notification_controller.h", - "system/cast/cast_feature_pod_controller.h", - "system/cast/cast_notification_controller.h", - "system/cast/tray_cast.h", - "system/cast/unified_cast_detailed_view_controller.h", - "system/date/clock_observer.h", - "system/date/date_view.h", - "system/date/system_info_default_view.h", - "system/date/tray_system_info.h", - "system/display_scale/scale_detailed_view.h", - "system/display_scale/scale_view.h", - "system/display_scale/tray_scale.h", - "system/enterprise/enterprise_domain_observer.h", - "system/enterprise/tray_enterprise.h", - "system/flag_warning/flag_warning_tray.h", - "system/ime/ime_feature_pod_controller.h", - "system/ime/ime_observer.h", - "system/ime/tray_ime_chromeos.h", - "system/ime/unified_ime_detailed_view_controller.h", - "system/ime_menu/ime_list_view.h", - "system/ime_menu/ime_menu_tray.h", - "system/keyboard_brightness/keyboard_brightness_controller.h", - "system/keyboard_brightness/tray_keyboard_brightness.h", - "system/keyboard_brightness/unified_keyboard_brightness_slider_controller.h", - "system/keyboard_brightness_control_delegate.h", - "system/locale/locale_notification_controller.h", - "system/media_security/multi_profile_media_tray_item.h", - "system/message_center/ash_popup_alignment_delegate.h", - "system/message_center/fullscreen_notification_blocker.h", - "system/message_center/inactive_user_notification_blocker.h", - "system/message_center/notification_tray.h", - "system/message_center/session_state_notification_blocker.h", - "system/model/clock_model.h", - "system/model/enterprise_domain_model.h", - "system/model/session_length_limit_model.h", - "system/model/system_tray_model.h", - "system/model/tracing_model.h", - "system/model/update_model.h", - "system/network/auto_connect_notifier.h", - "system/network/network_feature_pod_button.h", - "system/network/network_feature_pod_controller.h", - "system/network/network_icon.h", - "system/network/network_icon_animation.h", - "system/network/network_icon_animation_observer.h", - "system/network/network_info.h", - "system/network/network_list.h", - "system/network/network_observer.h", - "system/network/network_row_title_view.h", - "system/network/network_state_list_detailed_view.h", - "system/network/network_tray_view.h", - "system/network/sms_observer.h", - "system/network/tray_network.h", - "system/network/tray_network_state_observer.h", - "system/network/tray_vpn.h", - "system/network/unified_network_detailed_view_controller.h", - "system/network/unified_vpn_detailed_view_controller.h", - "system/network/vpn_feature_pod_controller.h", - "system/network/vpn_list.h", - "system/network/vpn_list_view.h", - "system/network/wifi_toggle_notification_controller.h", - "system/night_light/night_light_controller.h", - "system/night_light/night_light_feature_pod_controller.h", - "system/night_light/night_light_toggle_button.h", - "system/night_light/time_of_day.h", - "system/night_light/tray_night_light.h", - "system/overview/overview_button_tray.h", - "system/palette/common_palette_tool.h", - "system/palette/palette_ids.h", - "system/palette/palette_tool.h", - "system/palette/palette_tool_manager.h", - "system/palette/palette_tray.h", - "system/palette/palette_utils.h", - "system/palette/palette_welcome_bubble.h", - "system/palette/tools/capture_region_mode.h", - "system/palette/tools/capture_screen_action.h", - "system/palette/tools/create_note_action.h", - "system/palette/tools/laser_pointer_mode.h", - "system/palette/tools/magnifier_mode.h", - "system/palette/tools/metalayer_mode.h", - "system/power/backlights_forced_off_setter.h", - "system/power/battery_notification.h", - "system/power/dual_role_notification.h", - "system/power/peripheral_battery_notifier.h", - "system/power/power_button_controller.h", - "system/power/power_button_display_controller.h", - "system/power/power_button_menu_item_view.h", - "system/power/power_button_menu_metrics_type.h", - "system/power/power_button_menu_screen_view.h", - "system/power/power_button_menu_view.h", - "system/power/power_button_screenshot_controller.h", - "system/power/power_event_observer.h", - "system/power/power_notification_controller.h", - "system/power/power_prefs.h", - "system/power/power_status.h", - "system/power/power_status_view.h", - "system/power/scoped_backlights_forced_off.h", - "system/power/tray_power.h", - "system/power/video_activity_notifier.h", - "system/rotation/rotation_lock_feature_pod_controller.h", - "system/rotation/tray_rotation_lock.h", - "system/screen_layout_observer.h", - "system/screen_security/screen_capture_observer.h", - "system/screen_security/screen_capture_tray_item.h", - "system/screen_security/screen_security_notification_controller.h", - "system/screen_security/screen_share_observer.h", - "system/screen_security/screen_share_tray_item.h", - "system/screen_security/screen_switch_check_controller.h", - "system/screen_security/screen_tray_item.h", - "system/session/logout_button_tray.h", - "system/session/logout_confirmation_controller.h", - "system/session/logout_confirmation_dialog.h", - "system/session/session_limit_notification_controller.h", - "system/session/tray_session_length_limit.h", - "system/status_area_layout_manager.h", "system/status_area_widget.h", "system/status_area_widget_delegate.h", - "system/supervised/supervised_icon_string.h", - "system/supervised/supervised_notification_controller.h", - "system/supervised/tray_supervised_user.h", - "system/system_notification_controller.h", "system/system_tray_focus_observer.h", - "system/tiles/tiles_default_view.h", - "system/tiles/tray_tiles.h", - "system/toast/toast_data.h", - "system/toast/toast_manager.h", - "system/toast/toast_overlay.h", - "system/tracing_notification_controller.h", - "system/tray/actionable_view.h", - "system/tray/detailed_view_delegate.h", - "system/tray/hover_highlight_view.h", - "system/tray/interacted_by_tap_recorder.h", - "system/tray/label_tray_view.h", - "system/tray/size_range_layout.h", - "system/tray/system_menu_button.h", "system/tray/system_tray.h", - "system/tray/system_tray_bubble.h", - "system/tray/system_tray_item.h", - "system/tray/system_tray_item_detailed_view_delegate.h", - "system/tray/system_tray_item_uma_type.h", "system/tray/system_tray_notifier.h", - "system/tray/system_tray_view.h", - "system/tray/time_to_click_recorder.h", - "system/tray/tray_background_view.h", - "system/tray/tray_bubble_base.h", - "system/tray/tray_bubble_wrapper.h", - "system/tray/tray_constants.h", - "system/tray/tray_container.h", - "system/tray/tray_detailed_view.h", - "system/tray/tray_event_filter.h", - "system/tray/tray_image_item.h", - "system/tray/tray_info_label.h", - "system/tray/tray_item_more.h", - "system/tray/tray_item_view.h", - "system/tray/tray_popup_ink_drop_style.h", - "system/tray/tray_popup_item_style.h", - "system/tray/tray_popup_utils.h", - "system/tray/tray_utils.h", - "system/tray/tri_view.h", - "system/tray/view_click_listener.h", - "system/tray_accessibility.h", - "system/tray_caps_lock.h", - "system/tray_drag_controller.h", - "system/tray_tracing.h", - "system/unified/accessibility_feature_pod_controller.h", - "system/unified/collapse_button.h", - "system/unified/detailed_view_controller.h", - "system/unified/feature_pod_button.h", - "system/unified/feature_pod_controller_base.h", - "system/unified/feature_pods_container_view.h", - "system/unified/ime_mode_view.h", - "system/unified/notification_counter_view.h", - "system/unified/quiet_mode_feature_pod_controller.h", - "system/unified/sign_out_button.h", - "system/unified/top_shortcut_button.h", - "system/unified/top_shortcuts_view.h", - "system/unified/unified_detailed_view_delegate.h", - "system/unified/unified_message_center_view.h", - "system/unified/unified_notifier_settings_controller.h", - "system/unified/unified_slider_bubble_controller.h", - "system/unified/unified_slider_view.h", - "system/unified/unified_system_info_view.h", "system/unified/unified_system_tray.h", - "system/unified/unified_system_tray_bubble.h", - "system/unified/unified_system_tray_controller.h", - "system/unified/unified_system_tray_model.h", - "system/unified/unified_system_tray_view.h", - "system/unified/user_chooser_view.h", - "system/unified_accessibility_detailed_view_controller.h", - "system/update/tray_update.h", - "system/update/update_notification_controller.h", - "system/user/button_from_view.h", - "system/user/login_status.h", - "system/user/rounded_image_view.h", - "system/user/tray_user.h", - "system/user/user_card_view.h", - "system/user/user_view.h", - "system/virtual_keyboard/virtual_keyboard_observer.h", - "system/virtual_keyboard/virtual_keyboard_tray.h", - "touch/ash_touch_transform_controller.h", - "touch/touch_devices_controller.h", "touch/touch_observer_hud.h", - "touch/touch_transform_setter_mus.h", - "touch/touch_uma.h", - "tray_action/tray_action.h", - "tray_action/tray_action_observer.h", - "utility/screenshot_controller.h", - "utility/transformer_util.h", - "voice_interaction/voice_interaction_controller.h", - "wallpaper/wallpaper_controller.h", - "wallpaper/wallpaper_controller_observer.h", - "wallpaper/wallpaper_info.h", - "wallpaper/wallpaper_utils/wallpaper_color_calculator.h", - "wallpaper/wallpaper_utils/wallpaper_color_calculator_observer.h", - "wallpaper/wallpaper_utils/wallpaper_color_extraction_result.h", - "wallpaper/wallpaper_utils/wallpaper_decoder.h", - "wallpaper/wallpaper_utils/wallpaper_resizer.h", - "wallpaper/wallpaper_utils/wallpaper_resizer_observer.h", - "wallpaper/wallpaper_view.h", - "wallpaper/wallpaper_widget_controller.h", - "wallpaper/wallpaper_window_state_manager.h", - "window_user_data.h", - "wm/always_on_top_controller.h", - "wm/ash_focus_rules.h", - "wm/base_state.h", "wm/client_controlled_state.h", - "wm/container_finder.h", - "wm/cursor_manager_chromeos.h", - "wm/default_state.h", - "wm/default_window_resizer.h", - "wm/drag_details.h", - "wm/drag_window_controller.h", "wm/drag_window_resizer.h", - "wm/drag_window_resizer_mash.h", - "wm/event_client_impl.h", - "wm/focus_rules.h", - "wm/fullscreen_window_finder.h", - "wm/gestures/overview_gesture_handler.h", - "wm/immersive_context_ash.h", - "wm/immersive_focus_watcher_classic.h", - "wm/immersive_gesture_handler_classic.h", - "wm/immersive_handler_factory_ash.h", - "wm/immersive_handler_factory_mash.h", - "wm/lock_action_handler_layout_manager.h", - "wm/lock_layout_manager.h", - "wm/lock_state_controller.h", - "wm/lock_state_observer.h", - "wm/lock_window_state.h", "wm/mru_window_tracker.h", - "wm/native_cursor_manager_ash.h", - "wm/native_cursor_manager_ash_classic.h", - "wm/non_client_frame_controller.h", - "wm/overlay_event_filter.h", - "wm/overlay_layout_manager.h", - "wm/overview/cleanup_animation_observer.h", - "wm/overview/overview_animation_type.h", - "wm/overview/overview_utils.h", - "wm/overview/overview_window_drag_controller.h", - "wm/overview/rounded_rect_view.h", - "wm/overview/scoped_hide_overview_windows.h", - "wm/overview/scoped_overview_animation_settings.h", - "wm/overview/scoped_transform_overview_window.h", - "wm/overview/window_grid.h", - "wm/overview/window_selector.h", "wm/overview/window_selector_controller.h", - "wm/overview/window_selector_delegate.h", - "wm/overview/window_selector_item.h", - "wm/property_util.h", - "wm/resize_handle_window_targeter.h", - "wm/resize_shadow.h", - "wm/resize_shadow_controller.h", - "wm/root_window_finder.h", - "wm/root_window_layout_manager.h", - "wm/screen_dimmer.h", - "wm/screen_pinning_controller.h", - "wm/session_state_animator.h", - "wm/session_state_animator_impl.h", - "wm/splitview/split_view_constants.h", "wm/splitview/split_view_controller.h", - "wm/splitview/split_view_divider.h", - "wm/splitview/split_view_drag_indicators.h", - "wm/splitview/split_view_highlight_view.h", - "wm/splitview/split_view_utils.h", - "wm/stacking_controller.h", - "wm/switchable_windows.h", - "wm/system_gesture_event_filter.h", - "wm/system_modal_container_event_filter.h", - "wm/system_modal_container_event_filter_delegate.h", - "wm/system_modal_container_layout_manager.h", - "wm/system_wallpaper_controller.h", - "wm/tablet_mode/scoped_disable_internal_mouse_and_keyboard.h", - "wm/tablet_mode/scoped_disable_internal_mouse_and_keyboard_ozone.h", - "wm/tablet_mode/scoped_skip_user_session_blocked_check.h", "wm/tablet_mode/tablet_mode_app_window_drag_controller.h", - "wm/tablet_mode/tablet_mode_backdrop_delegate_impl.h", - "wm/tablet_mode/tablet_mode_browser_window_drag_controller.h", - "wm/tablet_mode/tablet_mode_browser_window_drag_delegate.h", "wm/tablet_mode/tablet_mode_controller.h", - "wm/tablet_mode/tablet_mode_event_handler.h", "wm/tablet_mode/tablet_mode_observer.h", - "wm/tablet_mode/tablet_mode_window_drag_delegate.h", - "wm/tablet_mode/tablet_mode_window_manager.h", - "wm/tablet_mode/tablet_mode_window_state.h", - "wm/top_level_window_factory.h", - "wm/toplevel_window_event_handler.h", - "wm/video_detector.h", - "wm/widget_finder.h", - "wm/window_animation_types.h", - "wm/window_animations.h", - "wm/window_cycle_controller.h", - "wm/window_cycle_event_filter.h", - "wm/window_cycle_list.h", - "wm/window_dimmer.h", "wm/window_finder.h", - "wm/window_mirror_view.h", - "wm/window_parenting_utils.h", "wm/window_positioner.h", "wm/window_positioning_utils.h", "wm/window_properties.h", @@ -677,608 +87,1180 @@ "wm/window_state.h", "wm/window_state_delegate.h", "wm/window_state_observer.h", - "wm/window_state_util.h", - "wm/window_transient_descendant_iterator.h", "wm/window_util.h", "wm/wm_event.h", - "wm/wm_shadow_controller_delegate.h", - "wm/wm_snap_to_pixel_layout_manager.h", - "wm/wm_toplevel_window_event_handler.h", - "wm/wm_window_animations.h", - "wm/workspace/backdrop_controller.h", - "wm/workspace/backdrop_delegate.h", - "wm/workspace/magnetism_matcher.h", - "wm/workspace/multi_window_resize_controller.h", - "wm/workspace/phantom_window_controller.h", - "wm/workspace/two_step_edge_cycler.h", - "wm/workspace/workspace_event_handler.h", - "wm/workspace/workspace_event_handler_classic.h", - "wm/workspace/workspace_layout_manager.h", - "wm/workspace/workspace_types.h", "wm/workspace/workspace_window_resizer.h", - "wm/workspace_controller.h", - "ws/ash_gpu_interface_provider.h", - "ws/window_service_delegate_impl.h", - "ws/window_service_owner.h", ] sources = [ "accelerators/accelerator_commands.cc", + "accelerators/accelerator_commands.h", "accelerators/accelerator_confirmation_dialog.cc", + "accelerators/accelerator_confirmation_dialog.h", "accelerators/accelerator_controller.cc", "accelerators/accelerator_delegate.cc", + "accelerators/accelerator_delegate.h", + "accelerators/accelerator_ids.h", "accelerators/accelerator_router.cc", + "accelerators/accelerator_router.h", "accelerators/accelerator_table.cc", + "accelerators/accelerator_table.h", "accelerators/ash_focus_manager_factory.cc", + "accelerators/ash_focus_manager_factory.h", "accelerators/debug_commands.cc", + "accelerators/debug_commands.h", "accelerators/exit_warning_handler.cc", + "accelerators/exit_warning_handler.h", "accelerators/key_hold_detector.cc", + "accelerators/key_hold_detector.h", "accelerators/magnifier_key_scroller.cc", + "accelerators/magnifier_key_scroller.h", "accelerators/spoken_feedback_toggler.cc", + "accelerators/spoken_feedback_toggler.h", "accessibility/accessibility_controller.cc", "accessibility/accessibility_cursor_ring_layer.cc", + "accessibility/accessibility_cursor_ring_layer.h", "accessibility/accessibility_focus_ring.cc", + "accessibility/accessibility_focus_ring.h", "accessibility/accessibility_focus_ring_controller.cc", + "accessibility/accessibility_focus_ring_controller.h", "accessibility/accessibility_focus_ring_group.cc", + "accessibility/accessibility_focus_ring_group.h", "accessibility/accessibility_focus_ring_layer.cc", + "accessibility/accessibility_focus_ring_layer.h", "accessibility/accessibility_highlight_controller.cc", + "accessibility/accessibility_highlight_controller.h", "accessibility/accessibility_highlight_layer.cc", + "accessibility/accessibility_highlight_layer.h", "accessibility/accessibility_layer.cc", + "accessibility/accessibility_layer.h", + "accessibility/accessibility_observer.h", "accessibility/accessibility_panel_layout_manager.cc", + "accessibility/accessibility_panel_layout_manager.h", "accessibility/default_accessibility_delegate.cc", + "accessibility/default_accessibility_delegate.h", "accessibility/focus_ring_controller.cc", "accessibility/focus_ring_layer.cc", + "accessibility/focus_ring_layer.h", "accessibility/key_accessibility_enabler.cc", + "accessibility/key_accessibility_enabler.h", "accessibility/layer_animation_info.cc", + "accessibility/layer_animation_info.h", "accessibility/spoken_feedback_enabler.cc", + "accessibility/spoken_feedback_enabler.h", "accessibility/touch_accessibility_enabler.cc", + "accessibility/touch_accessibility_enabler.h", "accessibility/touch_exploration_controller.cc", + "accessibility/touch_exploration_controller.h", "accessibility/touch_exploration_manager.cc", + "accessibility/touch_exploration_manager.h", + "animation/animation_change_type.h", "app_list/app_list_controller_impl.cc", "app_list/app_list_presenter_delegate_impl.cc", + "app_list/app_list_presenter_delegate_impl.h", + "ash_export.h", "ash_service.cc", "assistant/assistant_cache_controller.cc", + "assistant/assistant_cache_controller.h", "assistant/assistant_controller.cc", + "assistant/assistant_controller.h", + "assistant/assistant_controller_observer.h", "assistant/assistant_interaction_controller.cc", + "assistant/assistant_interaction_controller.h", "assistant/assistant_notification_controller.cc", + "assistant/assistant_notification_controller.h", "assistant/assistant_screen_context_controller.cc", + "assistant/assistant_screen_context_controller.h", "assistant/assistant_setup_controller.cc", + "assistant/assistant_setup_controller.h", "assistant/assistant_ui_controller.cc", + "assistant/assistant_ui_controller.h", "assistant/model/assistant_cache_model.cc", + "assistant/model/assistant_cache_model.h", + "assistant/model/assistant_cache_model_observer.h", "assistant/model/assistant_interaction_model.cc", + "assistant/model/assistant_interaction_model.h", + "assistant/model/assistant_interaction_model_observer.h", "assistant/model/assistant_query.cc", + "assistant/model/assistant_query.h", "assistant/model/assistant_response.cc", + "assistant/model/assistant_response.h", "assistant/model/assistant_screen_context_model.cc", + "assistant/model/assistant_screen_context_model.h", + "assistant/model/assistant_screen_context_model_observer.h", + "assistant/model/assistant_ui_element.h", "assistant/model/assistant_ui_model.cc", + "assistant/model/assistant_ui_model.h", + "assistant/model/assistant_ui_model_observer.h", "assistant/ui/assistant_container_view.cc", + "assistant/ui/assistant_container_view.h", "assistant/ui/assistant_main_view.cc", + "assistant/ui/assistant_main_view.h", "assistant/ui/assistant_mini_view.cc", + "assistant/ui/assistant_mini_view.h", "assistant/ui/assistant_scroll_view.cc", + "assistant/ui/assistant_scroll_view.h", "assistant/ui/assistant_web_view.cc", + "assistant/ui/assistant_web_view.h", "assistant/ui/caption_bar.cc", + "assistant/ui/caption_bar.h", "assistant/ui/dialog_plate/action_view.cc", + "assistant/ui/dialog_plate/action_view.h", "assistant/ui/dialog_plate/dialog_plate.cc", + "assistant/ui/dialog_plate/dialog_plate.h", "assistant/ui/logo_view/base_logo_view.cc", + "assistant/ui/logo_view/base_logo_view.h", "assistant/ui/main_stage/assistant_footer_view.cc", + "assistant/ui/main_stage/assistant_footer_view.h", "assistant/ui/main_stage/assistant_header_view.cc", + "assistant/ui/main_stage/assistant_header_view.h", "assistant/ui/main_stage/assistant_main_stage.cc", + "assistant/ui/main_stage/assistant_main_stage.h", "assistant/ui/main_stage/assistant_opt_in_view.cc", + "assistant/ui/main_stage/assistant_opt_in_view.h", "assistant/ui/main_stage/assistant_progress_indicator.cc", + "assistant/ui/main_stage/assistant_progress_indicator.h", "assistant/ui/main_stage/assistant_query_view.cc", + "assistant/ui/main_stage/assistant_query_view.h", "assistant/ui/main_stage/assistant_text_element_view.cc", + "assistant/ui/main_stage/assistant_text_element_view.h", "assistant/ui/main_stage/suggestion_container_view.cc", + "assistant/ui/main_stage/suggestion_container_view.h", "assistant/ui/main_stage/ui_element_container_view.cc", + "assistant/ui/main_stage/ui_element_container_view.h", "assistant/util/animation_util.cc", + "assistant/util/animation_util.h", "assistant/util/deep_link_util.cc", + "assistant/util/deep_link_util.h", "autoclick/autoclick_controller.cc", + "autoclick/autoclick_controller.h", "cancel_mode.cc", + "cancel_mode.h", "cast_config_controller.cc", + "cast_config_controller.h", "client_image_registry.cc", + "client_image_registry.h", "dbus/ash_dbus_services.cc", + "dbus/ash_dbus_services.h", "dbus/display_service_provider.cc", + "dbus/display_service_provider.h", "dbus/liveness_service_provider.cc", + "dbus/liveness_service_provider.h", "dbus/url_handler_service_provider.cc", + "dbus/url_handler_service_provider.h", "debug.cc", + "debug.h", "detachable_base/detachable_base_handler.cc", "detachable_base/detachable_base_notification_controller.cc", + "detachable_base/detachable_base_notification_controller.h", + "detachable_base/detachable_base_pairing_status.h", "disconnected_app_handler.cc", + "disconnected_app_handler.h", "display/ash_display_controller.cc", + "display/ash_display_controller.h", "display/cros_display_config.cc", + "display/cros_display_config.h", "display/cursor_window_controller.cc", + "display/cursor_window_controller.h", "display/display_animator.cc", + "display/display_animator.h", "display/display_color_manager.cc", + "display/display_color_manager.h", "display/display_configuration_controller.cc", + "display/display_configuration_controller.h", "display/display_configuration_observer.cc", + "display/display_configuration_observer.h", "display/display_error_observer.cc", + "display/display_error_observer.h", "display/display_move_window_util.cc", + "display/display_move_window_util.h", "display/display_output_protection.cc", "display/display_output_protection.h", "display/display_prefs.cc", "display/display_shutdown_observer.cc", + "display/display_shutdown_observer.h", "display/display_util.cc", + "display/display_util.h", "display/event_transformation_handler.cc", + "display/event_transformation_handler.h", "display/extended_mouse_warp_controller.cc", + "display/extended_mouse_warp_controller.h", "display/mirror_window_controller.cc", + "display/mirror_window_controller.h", "display/mouse_cursor_event_filter.cc", + "display/mouse_cursor_event_filter.h", + "display/mouse_warp_controller.h", "display/null_mouse_warp_controller.cc", + "display/null_mouse_warp_controller.h", "display/overscan_calibrator.cc", + "display/overscan_calibrator.h", "display/persistent_window_controller.cc", + "display/persistent_window_controller.h", "display/persistent_window_info.cc", + "display/persistent_window_info.h", "display/projecting_observer.cc", + "display/projecting_observer.h", "display/resolution_notification_controller.cc", + "display/resolution_notification_controller.h", "display/root_window_transformers.cc", + "display/root_window_transformers.h", "display/screen_ash.cc", + "display/screen_ash.h", "display/screen_orientation_controller.cc", "display/screen_position_controller.cc", + "display/screen_position_controller.h", "display/shared_display_edge_indicator.cc", + "display/shared_display_edge_indicator.h", "display/touch_calibrator_controller.cc", + "display/touch_calibrator_controller.h", "display/touch_calibrator_view.cc", + "display/touch_calibrator_view.h", "display/unified_mouse_warp_controller.cc", + "display/unified_mouse_warp_controller.h", "display/window_tree_host_manager.cc", + "display/window_tree_host_manager.h", "drag_drop/drag_drop_controller.cc", + "drag_drop/drag_drop_controller.h", "drag_drop/drag_drop_tracker.cc", + "drag_drop/drag_drop_tracker.h", "drag_drop/drag_image_view.cc", + "drag_drop/drag_image_view.h", "events/event_rewriter_controller.cc", "events/keyboard_driven_event_rewriter.cc", + "events/keyboard_driven_event_rewriter.h", "events/spoken_feedback_event_rewriter.cc", + "events/spoken_feedback_event_rewriter.h", "first_run/desktop_cleaner.cc", + "first_run/desktop_cleaner.h", "first_run/first_run_helper.cc", + "first_run/first_run_helper.h", "focus_cycler.cc", + "frame/caption_buttons/caption_button_types.h", "frame/caption_buttons/frame_back_button.cc", "frame/caption_buttons/frame_caption_button.cc", + "frame/caption_buttons/frame_caption_button.h", "frame/caption_buttons/frame_caption_button_container_view.cc", "frame/caption_buttons/frame_size_button.cc", + "frame/caption_buttons/frame_size_button.h", + "frame/caption_buttons/frame_size_button_delegate.h", "frame/custom_frame_header.cc", "frame/default_frame_header.cc", "frame/detached_title_area_renderer.cc", + "frame/detached_title_area_renderer.h", "frame/frame_header.cc", + "frame/frame_header.h", "frame/frame_header_util.cc", "frame/header_view.cc", "frame/non_client_frame_view_ash.cc", "frame/wide_frame_view.cc", "high_contrast/high_contrast_controller.cc", + "high_contrast/high_contrast_controller.h", "highlighter/highlighter_controller.cc", + "highlighter/highlighter_controller.h", "highlighter/highlighter_gesture_util.cc", + "highlighter/highlighter_gesture_util.h", "highlighter/highlighter_result_view.cc", + "highlighter/highlighter_result_view.h", "highlighter/highlighter_view.cc", + "highlighter/highlighter_view.h", "host/ash_window_tree_host.cc", + "host/ash_window_tree_host.h", + "host/ash_window_tree_host_init_params.h", + "host/ash_window_tree_host_mirroring_delegate.h", "host/ash_window_tree_host_mirroring_unified.cc", + "host/ash_window_tree_host_mirroring_unified.h", "host/ash_window_tree_host_platform.cc", + "host/ash_window_tree_host_platform.h", "host/ash_window_tree_host_unified.cc", + "host/ash_window_tree_host_unified.h", + "host/root_window_transformer.h", "host/transformer_helper.cc", + "host/transformer_helper.h", "ime/ime_controller.cc", + "ime/ime_controller.h", "ime/ime_focus_handler.cc", + "ime/ime_focus_handler.h", "ime/ime_mode_indicator_view.cc", "ime/ime_mode_indicator_view.h", + "ime/ime_switch_type.h", "ime/mode_indicator_observer.cc", "ime/mode_indicator_observer.h", "keyboard/virtual_keyboard_container_layout_manager.cc", + "keyboard/virtual_keyboard_container_layout_manager.h", "keyboard/virtual_keyboard_controller.cc", + "keyboard/virtual_keyboard_controller.h", "laser/laser_pointer_controller.cc", + "laser/laser_pointer_controller.h", "laser/laser_pointer_view.cc", + "laser/laser_pointer_view.h", "laser/laser_segment_utils.cc", + "laser/laser_segment_utils.h", "lock_screen_action/lock_screen_action_background_controller.cc", + "lock_screen_action/lock_screen_action_background_controller.h", "lock_screen_action/lock_screen_action_background_controller_impl.cc", + "lock_screen_action/lock_screen_action_background_controller_impl.h", "lock_screen_action/lock_screen_action_background_controller_stub.cc", + "lock_screen_action/lock_screen_action_background_controller_stub.h", + "lock_screen_action/lock_screen_action_background_observer.h", + "lock_screen_action/lock_screen_action_background_state.h", "lock_screen_action/lock_screen_action_background_view.cc", + "lock_screen_action/lock_screen_action_background_view.h", "lock_screen_action/lock_screen_note_display_state_handler.cc", + "lock_screen_action/lock_screen_note_display_state_handler.h", "lock_screen_action/lock_screen_note_launcher.cc", + "lock_screen_action/lock_screen_note_launcher.h", "login/login_screen_controller.cc", + "login/login_screen_controller.h", "login/login_screen_controller_observer.cc", + "login/login_screen_controller_observer.h", "login/ui/animated_rounded_image_view.cc", + "login/ui/animated_rounded_image_view.h", + "login/ui/animation_frame.h", "login/ui/arrow_button_view.cc", + "login/ui/arrow_button_view.h", "login/ui/horizontal_image_sequence_animation_decoder.cc", + "login/ui/horizontal_image_sequence_animation_decoder.h", "login/ui/hover_notifier.cc", + "login/ui/hover_notifier.h", "login/ui/image_parser.cc", + "login/ui/image_parser.h", "login/ui/lock_contents_view.cc", + "login/ui/lock_contents_view.h", "login/ui/lock_debug_view.cc", + "login/ui/lock_debug_view.h", "login/ui/lock_screen.cc", + "login/ui/lock_screen.h", "login/ui/lock_window.cc", "login/ui/login_auth_user_view.cc", + "login/ui/login_auth_user_view.h", "login/ui/login_base_bubble_view.cc", + "login/ui/login_base_bubble_view.h", "login/ui/login_big_user_view.cc", + "login/ui/login_big_user_view.h", "login/ui/login_bubble.cc", + "login/ui/login_bubble.h", "login/ui/login_button.cc", + "login/ui/login_button.h", "login/ui/login_data_dispatcher.cc", + "login/ui/login_data_dispatcher.h", "login/ui/login_detachable_base_model.cc", + "login/ui/login_detachable_base_model.h", "login/ui/login_expanded_public_account_view.cc", + "login/ui/login_expanded_public_account_view.h", "login/ui/login_menu_view.cc", + "login/ui/login_menu_view.h", "login/ui/login_password_view.cc", + "login/ui/login_password_view.h", "login/ui/login_pin_view.cc", + "login/ui/login_pin_view.h", "login/ui/login_public_account_user_view.cc", + "login/ui/login_public_account_user_view.h", "login/ui/login_user_view.cc", + "login/ui/login_user_view.h", "login/ui/non_accessible_view.cc", + "login/ui/non_accessible_view.h", "login/ui/note_action_launch_button.cc", + "login/ui/note_action_launch_button.h", "login/ui/pin_keyboard_animation.cc", + "login/ui/pin_keyboard_animation.h", "login/ui/public_account_warning_dialog.cc", + "login/ui/public_account_warning_dialog.h", "login/ui/scrollable_users_list_view.cc", + "login/ui/scrollable_users_list_view.h", "login/ui/user_switch_flip_animation.cc", + "login/ui/user_switch_flip_animation.h", "login/ui/views_utils.cc", + "login/ui/views_utils.h", + "login_status.h", "magnifier/docked_magnifier_controller.cc", + "magnifier/docked_magnifier_controller.h", "magnifier/magnification_controller.cc", "magnifier/magnifier_scale_utils.cc", + "magnifier/magnifier_scale_utils.h", "magnifier/partial_magnification_controller.cc", + "magnifier/partial_magnification_controller.h", "media_controller.cc", + "media_controller.h", "message_center/arc_notification_manager_delegate_impl.cc", + "message_center/arc_notification_manager_delegate_impl.h", "message_center/ash_message_center_lock_screen_controller.cc", + "message_center/ash_message_center_lock_screen_controller.h", "message_center/message_center_bubble.cc", + "message_center/message_center_bubble.h", "message_center/message_center_button_bar.cc", + "message_center/message_center_button_bar.h", "message_center/message_center_controller.cc", + "message_center/message_center_controller.h", "message_center/message_center_scroll_bar.cc", + "message_center/message_center_scroll_bar.h", + "message_center/message_center_style.h", "message_center/message_center_ui_controller.cc", + "message_center/message_center_ui_controller.h", + "message_center/message_center_ui_delegate.h", "message_center/message_center_view.cc", + "message_center/message_center_view.h", "message_center/message_list_view.cc", + "message_center/message_list_view.h", "message_center/notifier_settings_view.cc", + "message_center/notifier_settings_view.h", "metrics/desktop_task_switch_metric_recorder.cc", + "metrics/desktop_task_switch_metric_recorder.h", + "metrics/gesture_action_type.h", "metrics/login_metrics_recorder.cc", + "metrics/login_metrics_recorder.h", "metrics/pointer_metrics_recorder.cc", + "metrics/pointer_metrics_recorder.h", "metrics/task_switch_metrics_recorder.cc", + "metrics/task_switch_metrics_recorder.h", + "metrics/task_switch_source.h", "metrics/task_switch_time_tracker.cc", + "metrics/task_switch_time_tracker.h", "metrics/time_to_first_present_recorder.cc", + "metrics/time_to_first_present_recorder.h", + "metrics/user_metrics_action.h", "metrics/user_metrics_recorder.cc", + "metrics/user_metrics_recorder.h", "mojo_interface_factory.cc", + "mojo_interface_factory.h", "multi_device_setup/multi_device_notification_presenter.cc", + "multi_device_setup/multi_device_notification_presenter.h", "multi_profile_uma.cc", + "multi_profile_uma.h", "network_connect_delegate_mus.cc", + "network_connect_delegate_mus.h", "new_window_controller.cc", "note_taking_controller.cc", + "note_taking_controller.h", "pointer_watcher_adapter.cc", + "pointer_watcher_adapter.h", "policy/policy_recommendation_restorer.cc", + "policy/policy_recommendation_restorer.h", "root_window_controller.cc", "root_window_settings.cc", + "root_window_settings.h", "rotator/screen_rotation_animation.cc", + "rotator/screen_rotation_animation.h", "rotator/screen_rotation_animator.cc", + "rotator/screen_rotation_animator.h", + "rotator/screen_rotation_animator_observer.h", "rotator/window_rotation.cc", + "rotator/window_rotation.h", "scoped_root_window_for_new_windows.cc", + "scoped_root_window_for_new_windows.h", "screen_util.cc", + "screen_util.h", "session/multiprofiles_intro_dialog.cc", + "session/multiprofiles_intro_dialog.h", "session/session_aborted_dialog.cc", + "session/session_aborted_dialog.h", "session/session_activation_observer_holder.cc", + "session/session_activation_observer_holder.h", "session/session_controller.cc", "session/session_observer.cc", + "session/session_observer.h", "session/teleport_warning_dialog.cc", + "session/teleport_warning_dialog.h", "shelf/app_list_button.cc", + "shelf/app_list_button.h", "shelf/app_list_shelf_item_delegate.cc", + "shelf/app_list_shelf_item_delegate.h", "shelf/assistant_overlay.cc", + "shelf/assistant_overlay.h", "shelf/back_button.cc", + "shelf/back_button.h", + "shelf/ink_drop_button_listener.h", "shelf/login_shelf_view.cc", + "shelf/login_shelf_view.h", "shelf/overflow_bubble.cc", + "shelf/overflow_bubble.h", "shelf/overflow_bubble_view.cc", + "shelf/overflow_bubble_view.h", "shelf/overflow_button.cc", + "shelf/overflow_button.h", "shelf/shelf.cc", "shelf/shelf_application_menu_model.cc", + "shelf/shelf_application_menu_model.h", "shelf/shelf_background_animator.cc", + "shelf/shelf_background_animator.h", + "shelf/shelf_background_animator_observer.h", "shelf/shelf_bezel_event_handler.cc", + "shelf/shelf_bezel_event_handler.h", "shelf/shelf_button.cc", + "shelf/shelf_button.h", "shelf/shelf_button_pressed_metric_tracker.cc", + "shelf/shelf_button_pressed_metric_tracker.h", + "shelf/shelf_constants.h", "shelf/shelf_context_menu_model.cc", + "shelf/shelf_context_menu_model.h", "shelf/shelf_controller.cc", + "shelf/shelf_controller.h", "shelf/shelf_layout_manager.cc", + "shelf/shelf_layout_manager.h", + "shelf/shelf_layout_manager_observer.h", "shelf/shelf_locking_manager.cc", + "shelf/shelf_locking_manager.h", "shelf/shelf_menu_model_adapter.cc", + "shelf/shelf_menu_model_adapter.h", + "shelf/shelf_observer.h", "shelf/shelf_tooltip_bubble.cc", + "shelf/shelf_tooltip_bubble.h", "shelf/shelf_tooltip_bubble_base.cc", + "shelf/shelf_tooltip_bubble_base.h", "shelf/shelf_tooltip_manager.cc", + "shelf/shelf_tooltip_manager.h", "shelf/shelf_tooltip_preview_bubble.cc", + "shelf/shelf_tooltip_preview_bubble.h", "shelf/shelf_view.cc", + "shelf/shelf_view.h", "shelf/shelf_widget.cc", "shelf/shelf_window_targeter.cc", + "shelf/shelf_window_targeter.h", "shelf/shelf_window_watcher.cc", + "shelf/shelf_window_watcher.h", "shelf/shelf_window_watcher_item_delegate.cc", + "shelf/shelf_window_watcher_item_delegate.h", "shelf/window_preview.cc", + "shelf/window_preview.h", "shell.cc", "shell_delegate_mash.cc", + "shell_delegate_mash.h", "shell_init_params.cc", "shell_state.cc", + "shell_state.h", "shutdown_controller.cc", + "shutdown_controller.h", "shutdown_reason.cc", + "shutdown_reason.h", "sticky_keys/sticky_keys_controller.cc", "sticky_keys/sticky_keys_overlay.cc", + "sticky_keys/sticky_keys_overlay.h", + "sticky_keys/sticky_keys_state.h", "system/accessibility/dictation_button_tray.cc", + "system/accessibility/dictation_button_tray.h", "system/accessibility/select_to_speak_tray.cc", + "system/accessibility/select_to_speak_tray.h", "system/accessibility/select_to_speak_tray_utils.cc", "system/audio/audio_detailed_view.cc", + "system/audio/audio_detailed_view.h", "system/audio/display_speaker_controller.cc", + "system/audio/display_speaker_controller.h", "system/audio/tray_audio.cc", + "system/audio/tray_audio.h", "system/audio/unified_audio_detailed_view_controller.cc", + "system/audio/unified_audio_detailed_view_controller.h", "system/audio/unified_volume_slider_controller.cc", + "system/audio/unified_volume_slider_controller.h", "system/audio/unified_volume_view.cc", + "system/audio/unified_volume_view.h", "system/audio/volume_view.cc", + "system/audio/volume_view.h", "system/bluetooth/bluetooth_detailed_view.cc", + "system/bluetooth/bluetooth_detailed_view.h", "system/bluetooth/bluetooth_feature_pod_controller.cc", + "system/bluetooth/bluetooth_feature_pod_controller.h", "system/bluetooth/bluetooth_notification_controller.cc", + "system/bluetooth/bluetooth_notification_controller.h", + "system/bluetooth/bluetooth_observer.h", "system/bluetooth/bluetooth_power_controller.cc", + "system/bluetooth/bluetooth_power_controller.h", "system/bluetooth/tray_bluetooth.cc", + "system/bluetooth/tray_bluetooth.h", "system/bluetooth/tray_bluetooth_helper.cc", + "system/bluetooth/tray_bluetooth_helper.h", "system/bluetooth/unified_bluetooth_detailed_view_controller.cc", + "system/bluetooth/unified_bluetooth_detailed_view_controller.h", "system/brightness/brightness_controller_chromeos.cc", + "system/brightness/brightness_controller_chromeos.h", "system/brightness/tray_brightness.cc", + "system/brightness/tray_brightness.h", "system/brightness/unified_brightness_slider_controller.cc", + "system/brightness/unified_brightness_slider_controller.h", "system/brightness/unified_brightness_view.cc", + "system/brightness/unified_brightness_view.h", + "system/brightness_control_delegate.h", "system/caps_lock_notification_controller.cc", + "system/caps_lock_notification_controller.h", "system/cast/cast_feature_pod_controller.cc", + "system/cast/cast_feature_pod_controller.h", "system/cast/cast_notification_controller.cc", + "system/cast/cast_notification_controller.h", "system/cast/tray_cast.cc", + "system/cast/tray_cast.h", "system/cast/unified_cast_detailed_view_controller.cc", + "system/cast/unified_cast_detailed_view_controller.h", + "system/date/clock_observer.h", "system/date/date_view.cc", + "system/date/date_view.h", "system/date/system_info_default_view.cc", + "system/date/system_info_default_view.h", "system/date/tray_system_info.cc", + "system/date/tray_system_info.h", "system/display_scale/scale_detailed_view.cc", + "system/display_scale/scale_detailed_view.h", "system/display_scale/scale_view.cc", + "system/display_scale/scale_view.h", "system/display_scale/tray_scale.cc", + "system/display_scale/tray_scale.h", + "system/enterprise/enterprise_domain_observer.h", "system/enterprise/tray_enterprise.cc", + "system/enterprise/tray_enterprise.h", "system/flag_warning/flag_warning_tray.cc", + "system/flag_warning/flag_warning_tray.h", "system/ime/ime_feature_pod_controller.cc", + "system/ime/ime_feature_pod_controller.h", + "system/ime/ime_observer.h", "system/ime/tray_ime_chromeos.cc", + "system/ime/tray_ime_chromeos.h", "system/ime/unified_ime_detailed_view_controller.cc", + "system/ime/unified_ime_detailed_view_controller.h", "system/ime_menu/ime_list_view.cc", + "system/ime_menu/ime_list_view.h", "system/ime_menu/ime_menu_tray.cc", + "system/ime_menu/ime_menu_tray.h", "system/keyboard_brightness/keyboard_brightness_controller.cc", + "system/keyboard_brightness/keyboard_brightness_controller.h", "system/keyboard_brightness/tray_keyboard_brightness.cc", + "system/keyboard_brightness/tray_keyboard_brightness.h", "system/keyboard_brightness/unified_keyboard_brightness_slider_controller.cc", + "system/keyboard_brightness/unified_keyboard_brightness_slider_controller.h", + "system/keyboard_brightness_control_delegate.h", "system/locale/locale_notification_controller.cc", + "system/locale/locale_notification_controller.h", "system/media_security/multi_profile_media_tray_item.cc", + "system/media_security/multi_profile_media_tray_item.h", "system/message_center/ash_popup_alignment_delegate.cc", + "system/message_center/ash_popup_alignment_delegate.h", "system/message_center/fullscreen_notification_blocker.cc", + "system/message_center/fullscreen_notification_blocker.h", "system/message_center/inactive_user_notification_blocker.cc", + "system/message_center/inactive_user_notification_blocker.h", "system/message_center/notification_tray.cc", + "system/message_center/notification_tray.h", "system/message_center/session_state_notification_blocker.cc", + "system/message_center/session_state_notification_blocker.h", "system/model/clock_model.cc", + "system/model/clock_model.h", "system/model/enterprise_domain_model.cc", + "system/model/enterprise_domain_model.h", "system/model/session_length_limit_model.cc", + "system/model/session_length_limit_model.h", "system/model/system_tray_model.cc", + "system/model/system_tray_model.h", "system/model/tracing_model.cc", + "system/model/tracing_model.h", "system/model/update_model.cc", + "system/model/update_model.h", "system/network/auto_connect_notifier.cc", + "system/network/auto_connect_notifier.h", "system/network/network_feature_pod_button.cc", + "system/network/network_feature_pod_button.h", "system/network/network_feature_pod_controller.cc", + "system/network/network_feature_pod_controller.h", "system/network/network_icon.cc", + "system/network/network_icon.h", "system/network/network_icon_animation.cc", + "system/network/network_icon_animation.h", + "system/network/network_icon_animation_observer.h", "system/network/network_info.cc", + "system/network/network_info.h", "system/network/network_list.cc", + "system/network/network_list.h", + "system/network/network_observer.h", "system/network/network_row_title_view.cc", + "system/network/network_row_title_view.h", "system/network/network_state_list_detailed_view.cc", + "system/network/network_state_list_detailed_view.h", "system/network/network_tray_view.cc", + "system/network/network_tray_view.h", "system/network/sms_observer.cc", + "system/network/sms_observer.h", "system/network/tray_network.cc", + "system/network/tray_network.h", "system/network/tray_network_state_observer.cc", + "system/network/tray_network_state_observer.h", "system/network/tray_vpn.cc", + "system/network/tray_vpn.h", "system/network/unified_network_detailed_view_controller.cc", + "system/network/unified_network_detailed_view_controller.h", "system/network/unified_vpn_detailed_view_controller.cc", + "system/network/unified_vpn_detailed_view_controller.h", "system/network/vpn_feature_pod_controller.cc", + "system/network/vpn_feature_pod_controller.h", "system/network/vpn_list.cc", + "system/network/vpn_list.h", "system/network/vpn_list_view.cc", + "system/network/vpn_list_view.h", "system/network/wifi_toggle_notification_controller.cc", + "system/network/wifi_toggle_notification_controller.h", "system/night_light/night_light_controller.cc", + "system/night_light/night_light_controller.h", "system/night_light/night_light_feature_pod_controller.cc", + "system/night_light/night_light_feature_pod_controller.h", "system/night_light/night_light_toggle_button.cc", + "system/night_light/night_light_toggle_button.h", "system/night_light/time_of_day.cc", + "system/night_light/time_of_day.h", "system/night_light/tray_night_light.cc", + "system/night_light/tray_night_light.h", "system/overview/overview_button_tray.cc", + "system/overview/overview_button_tray.h", "system/palette/common_palette_tool.cc", + "system/palette/common_palette_tool.h", "system/palette/palette_ids.cc", + "system/palette/palette_ids.h", "system/palette/palette_tool.cc", + "system/palette/palette_tool.h", "system/palette/palette_tool_manager.cc", + "system/palette/palette_tool_manager.h", "system/palette/palette_tray.cc", + "system/palette/palette_tray.h", "system/palette/palette_utils.cc", + "system/palette/palette_utils.h", "system/palette/palette_welcome_bubble.cc", + "system/palette/palette_welcome_bubble.h", "system/palette/tools/capture_region_mode.cc", + "system/palette/tools/capture_region_mode.h", "system/palette/tools/capture_screen_action.cc", + "system/palette/tools/capture_screen_action.h", "system/palette/tools/create_note_action.cc", + "system/palette/tools/create_note_action.h", "system/palette/tools/laser_pointer_mode.cc", + "system/palette/tools/laser_pointer_mode.h", "system/palette/tools/magnifier_mode.cc", + "system/palette/tools/magnifier_mode.h", "system/palette/tools/metalayer_mode.cc", + "system/palette/tools/metalayer_mode.h", "system/power/backlights_forced_off_setter.cc", + "system/power/backlights_forced_off_setter.h", "system/power/battery_notification.cc", + "system/power/battery_notification.h", "system/power/dual_role_notification.cc", + "system/power/dual_role_notification.h", "system/power/peripheral_battery_notifier.cc", + "system/power/peripheral_battery_notifier.h", "system/power/power_button_controller.cc", + "system/power/power_button_controller.h", "system/power/power_button_display_controller.cc", + "system/power/power_button_display_controller.h", "system/power/power_button_menu_item_view.cc", + "system/power/power_button_menu_item_view.h", "system/power/power_button_menu_metrics_type.cc", + "system/power/power_button_menu_metrics_type.h", "system/power/power_button_menu_screen_view.cc", + "system/power/power_button_menu_screen_view.h", "system/power/power_button_menu_view.cc", + "system/power/power_button_menu_view.h", "system/power/power_button_screenshot_controller.cc", + "system/power/power_button_screenshot_controller.h", "system/power/power_event_observer.cc", + "system/power/power_event_observer.h", "system/power/power_notification_controller.cc", + "system/power/power_notification_controller.h", "system/power/power_prefs.cc", + "system/power/power_prefs.h", "system/power/power_status.cc", + "system/power/power_status.h", "system/power/power_status_view.cc", + "system/power/power_status_view.h", "system/power/scoped_backlights_forced_off.cc", + "system/power/scoped_backlights_forced_off.h", "system/power/tray_power.cc", + "system/power/tray_power.h", "system/power/video_activity_notifier.cc", + "system/power/video_activity_notifier.h", "system/rotation/rotation_lock_feature_pod_controller.cc", + "system/rotation/rotation_lock_feature_pod_controller.h", "system/rotation/tray_rotation_lock.cc", + "system/rotation/tray_rotation_lock.h", "system/screen_layout_observer.cc", + "system/screen_layout_observer.h", + "system/screen_security/screen_capture_observer.h", "system/screen_security/screen_capture_tray_item.cc", + "system/screen_security/screen_capture_tray_item.h", "system/screen_security/screen_security_notification_controller.cc", + "system/screen_security/screen_security_notification_controller.h", + "system/screen_security/screen_share_observer.h", "system/screen_security/screen_share_tray_item.cc", + "system/screen_security/screen_share_tray_item.h", "system/screen_security/screen_switch_check_controller.cc", + "system/screen_security/screen_switch_check_controller.h", "system/screen_security/screen_tray_item.cc", + "system/screen_security/screen_tray_item.h", "system/session/logout_button_tray.cc", + "system/session/logout_button_tray.h", "system/session/logout_confirmation_controller.cc", + "system/session/logout_confirmation_controller.h", "system/session/logout_confirmation_dialog.cc", + "system/session/logout_confirmation_dialog.h", "system/session/session_limit_notification_controller.cc", + "system/session/session_limit_notification_controller.h", "system/session/tray_session_length_limit.cc", + "system/session/tray_session_length_limit.h", "system/status_area_layout_manager.cc", + "system/status_area_layout_manager.h", "system/status_area_widget.cc", "system/status_area_widget_delegate.cc", "system/supervised/supervised_icon_string.cc", + "system/supervised/supervised_icon_string.h", "system/supervised/supervised_notification_controller.cc", + "system/supervised/supervised_notification_controller.h", "system/supervised/tray_supervised_user.cc", + "system/supervised/tray_supervised_user.h", "system/system_notification_controller.cc", + "system/system_notification_controller.h", "system/tiles/tiles_default_view.cc", + "system/tiles/tiles_default_view.h", "system/tiles/tray_tiles.cc", + "system/tiles/tray_tiles.h", "system/toast/toast_data.cc", + "system/toast/toast_data.h", "system/toast/toast_manager.cc", + "system/toast/toast_manager.h", "system/toast/toast_overlay.cc", + "system/toast/toast_overlay.h", "system/tracing_notification_controller.cc", + "system/tracing_notification_controller.h", "system/tray/actionable_view.cc", + "system/tray/actionable_view.h", + "system/tray/detailed_view_delegate.h", "system/tray/hover_highlight_view.cc", + "system/tray/hover_highlight_view.h", "system/tray/interacted_by_tap_recorder.cc", + "system/tray/interacted_by_tap_recorder.h", "system/tray/label_tray_view.cc", + "system/tray/label_tray_view.h", "system/tray/size_range_layout.cc", + "system/tray/size_range_layout.h", "system/tray/system_menu_button.cc", + "system/tray/system_menu_button.h", "system/tray/system_tray.cc", "system/tray/system_tray_bubble.cc", + "system/tray/system_tray_bubble.h", "system/tray/system_tray_item.cc", + "system/tray/system_tray_item.h", "system/tray/system_tray_item_detailed_view_delegate.cc", + "system/tray/system_tray_item_detailed_view_delegate.h", + "system/tray/system_tray_item_uma_type.h", "system/tray/system_tray_notifier.cc", "system/tray/system_tray_view.cc", + "system/tray/system_tray_view.h", "system/tray/time_to_click_recorder.cc", + "system/tray/time_to_click_recorder.h", "system/tray/tray_background_view.cc", + "system/tray/tray_background_view.h", + "system/tray/tray_bubble_base.h", "system/tray/tray_bubble_wrapper.cc", + "system/tray/tray_bubble_wrapper.h", "system/tray/tray_constants.cc", + "system/tray/tray_constants.h", "system/tray/tray_container.cc", + "system/tray/tray_container.h", "system/tray/tray_detailed_view.cc", + "system/tray/tray_detailed_view.h", "system/tray/tray_event_filter.cc", + "system/tray/tray_event_filter.h", "system/tray/tray_image_item.cc", + "system/tray/tray_image_item.h", "system/tray/tray_info_label.cc", + "system/tray/tray_info_label.h", "system/tray/tray_item_more.cc", + "system/tray/tray_item_more.h", "system/tray/tray_item_view.cc", + "system/tray/tray_item_view.h", + "system/tray/tray_popup_ink_drop_style.h", "system/tray/tray_popup_item_style.cc", + "system/tray/tray_popup_item_style.h", "system/tray/tray_popup_utils.cc", + "system/tray/tray_popup_utils.h", "system/tray/tray_utils.cc", + "system/tray/tray_utils.h", "system/tray/tri_view.cc", + "system/tray/tri_view.h", + "system/tray/view_click_listener.h", "system/tray_accessibility.cc", + "system/tray_accessibility.h", "system/tray_caps_lock.cc", + "system/tray_caps_lock.h", "system/tray_drag_controller.cc", + "system/tray_drag_controller.h", "system/tray_tracing.cc", + "system/tray_tracing.h", "system/unified/accessibility_feature_pod_controller.cc", + "system/unified/accessibility_feature_pod_controller.h", "system/unified/collapse_button.cc", + "system/unified/collapse_button.h", + "system/unified/detailed_view_controller.h", "system/unified/feature_pod_button.cc", + "system/unified/feature_pod_button.h", "system/unified/feature_pod_controller_base.cc", + "system/unified/feature_pod_controller_base.h", "system/unified/feature_pods_container_view.cc", + "system/unified/feature_pods_container_view.h", "system/unified/ime_mode_view.cc", + "system/unified/ime_mode_view.h", "system/unified/notification_counter_view.cc", + "system/unified/notification_counter_view.h", "system/unified/quiet_mode_feature_pod_controller.cc", + "system/unified/quiet_mode_feature_pod_controller.h", "system/unified/sign_out_button.cc", + "system/unified/sign_out_button.h", "system/unified/top_shortcut_button.cc", + "system/unified/top_shortcut_button.h", "system/unified/top_shortcuts_view.cc", + "system/unified/top_shortcuts_view.h", "system/unified/unified_detailed_view_delegate.cc", + "system/unified/unified_detailed_view_delegate.h", "system/unified/unified_message_center_view.cc", + "system/unified/unified_message_center_view.h", "system/unified/unified_notifier_settings_controller.cc", + "system/unified/unified_notifier_settings_controller.h", "system/unified/unified_slider_bubble_controller.cc", + "system/unified/unified_slider_bubble_controller.h", "system/unified/unified_slider_view.cc", + "system/unified/unified_slider_view.h", "system/unified/unified_system_info_view.cc", + "system/unified/unified_system_info_view.h", "system/unified/unified_system_tray.cc", "system/unified/unified_system_tray_bubble.cc", + "system/unified/unified_system_tray_bubble.h", "system/unified/unified_system_tray_controller.cc", + "system/unified/unified_system_tray_controller.h", "system/unified/unified_system_tray_model.cc", + "system/unified/unified_system_tray_model.h", "system/unified/unified_system_tray_view.cc", + "system/unified/unified_system_tray_view.h", "system/unified/user_chooser_view.cc", + "system/unified/user_chooser_view.h", "system/unified_accessibility_detailed_view_controller.cc", + "system/unified_accessibility_detailed_view_controller.h", "system/update/tray_update.cc", + "system/update/tray_update.h", "system/update/update_notification_controller.cc", + "system/update/update_notification_controller.h", "system/user/button_from_view.cc", + "system/user/button_from_view.h", "system/user/login_status.cc", + "system/user/login_status.h", "system/user/rounded_image_view.cc", + "system/user/rounded_image_view.h", "system/user/tray_user.cc", + "system/user/tray_user.h", "system/user/user_card_view.cc", + "system/user/user_card_view.h", "system/user/user_view.cc", + "system/user/user_view.h", + "system/virtual_keyboard/virtual_keyboard_observer.h", "system/virtual_keyboard/virtual_keyboard_tray.cc", + "system/virtual_keyboard/virtual_keyboard_tray.h", "touch/ash_touch_transform_controller.cc", + "touch/ash_touch_transform_controller.h", "touch/touch_devices_controller.cc", + "touch/touch_devices_controller.h", "touch/touch_observer_hud.cc", "touch/touch_transform_setter_mus.cc", + "touch/touch_transform_setter_mus.h", "touch/touch_uma.cc", + "touch/touch_uma.h", "tray_action/tray_action.cc", + "tray_action/tray_action.h", + "tray_action/tray_action_observer.h", "utility/screenshot_controller.cc", + "utility/screenshot_controller.h", "utility/transformer_util.cc", + "utility/transformer_util.h", "voice_interaction/voice_interaction_controller.cc", + "voice_interaction/voice_interaction_controller.h", "wallpaper/wallpaper_controller.cc", + "wallpaper/wallpaper_controller.h", + "wallpaper/wallpaper_controller_observer.h", + "wallpaper/wallpaper_info.h", "wallpaper/wallpaper_utils/wallpaper_color_calculator.cc", + "wallpaper/wallpaper_utils/wallpaper_color_calculator.h", + "wallpaper/wallpaper_utils/wallpaper_color_calculator_observer.h", + "wallpaper/wallpaper_utils/wallpaper_color_extraction_result.h", "wallpaper/wallpaper_utils/wallpaper_decoder.cc", + "wallpaper/wallpaper_utils/wallpaper_decoder.h", "wallpaper/wallpaper_utils/wallpaper_resizer.cc", + "wallpaper/wallpaper_utils/wallpaper_resizer.h", + "wallpaper/wallpaper_utils/wallpaper_resizer_observer.h", "wallpaper/wallpaper_view.cc", + "wallpaper/wallpaper_view.h", "wallpaper/wallpaper_widget_controller.cc", + "wallpaper/wallpaper_widget_controller.h", "wallpaper/wallpaper_window_state_manager.cc", + "wallpaper/wallpaper_window_state_manager.h", "window_factory.cc", "window_factory.h", + "window_user_data.h", "wm/always_on_top_controller.cc", + "wm/always_on_top_controller.h", "wm/ash_focus_rules.cc", + "wm/ash_focus_rules.h", "wm/base_state.cc", + "wm/base_state.h", "wm/client_controlled_state.cc", "wm/container_finder.cc", + "wm/container_finder.h", "wm/cursor_manager_chromeos.cc", + "wm/cursor_manager_chromeos.h", "wm/default_state.cc", + "wm/default_state.h", "wm/default_window_resizer.cc", + "wm/default_window_resizer.h", "wm/drag_details.cc", + "wm/drag_details.h", "wm/drag_window_controller.cc", + "wm/drag_window_controller.h", "wm/drag_window_resizer.cc", "wm/drag_window_resizer_mash.cc", + "wm/drag_window_resizer_mash.h", "wm/event_client_impl.cc", + "wm/event_client_impl.h", "wm/focus_rules.cc", + "wm/focus_rules.h", "wm/fullscreen_window_finder.cc", + "wm/fullscreen_window_finder.h", "wm/gestures/overview_gesture_handler.cc", + "wm/gestures/overview_gesture_handler.h", "wm/immersive_context_ash.cc", + "wm/immersive_context_ash.h", "wm/immersive_focus_watcher_classic.cc", + "wm/immersive_focus_watcher_classic.h", "wm/immersive_gesture_handler_classic.cc", + "wm/immersive_gesture_handler_classic.h", "wm/immersive_handler_factory_ash.cc", + "wm/immersive_handler_factory_ash.h", "wm/immersive_handler_factory_mash.cc", + "wm/immersive_handler_factory_mash.h", "wm/lock_action_handler_layout_manager.cc", + "wm/lock_action_handler_layout_manager.h", "wm/lock_layout_manager.cc", + "wm/lock_layout_manager.h", "wm/lock_state_controller.cc", + "wm/lock_state_controller.h", + "wm/lock_state_observer.h", "wm/lock_window_state.cc", + "wm/lock_window_state.h", "wm/mru_window_tracker.cc", + "wm/native_cursor_manager_ash.h", "wm/native_cursor_manager_ash_classic.cc", + "wm/native_cursor_manager_ash_classic.h", "wm/non_client_frame_controller.cc", + "wm/non_client_frame_controller.h", "wm/overlay_event_filter.cc", + "wm/overlay_event_filter.h", "wm/overlay_layout_manager.cc", + "wm/overlay_layout_manager.h", "wm/overview/cleanup_animation_observer.cc", + "wm/overview/cleanup_animation_observer.h", + "wm/overview/overview_animation_type.h", "wm/overview/overview_utils.cc", + "wm/overview/overview_utils.h", "wm/overview/overview_window_drag_controller.cc", + "wm/overview/overview_window_drag_controller.h", "wm/overview/rounded_rect_view.cc", + "wm/overview/rounded_rect_view.h", "wm/overview/scoped_hide_overview_windows.cc", + "wm/overview/scoped_hide_overview_windows.h", "wm/overview/scoped_overview_animation_settings.cc", + "wm/overview/scoped_overview_animation_settings.h", "wm/overview/scoped_transform_overview_window.cc", + "wm/overview/scoped_transform_overview_window.h", "wm/overview/window_grid.cc", + "wm/overview/window_grid.h", "wm/overview/window_selector.cc", + "wm/overview/window_selector.h", "wm/overview/window_selector_controller.cc", + "wm/overview/window_selector_delegate.h", "wm/overview/window_selector_item.cc", + "wm/overview/window_selector_item.h", "wm/property_util.cc", + "wm/property_util.h", "wm/resize_handle_window_targeter.cc", + "wm/resize_handle_window_targeter.h", "wm/resize_shadow.cc", + "wm/resize_shadow.h", "wm/resize_shadow_controller.cc", + "wm/resize_shadow_controller.h", "wm/root_window_finder.cc", + "wm/root_window_finder.h", "wm/root_window_layout_manager.cc", + "wm/root_window_layout_manager.h", "wm/screen_dimmer.cc", + "wm/screen_dimmer.h", "wm/screen_pinning_controller.cc", + "wm/screen_pinning_controller.h", "wm/session_state_animator.cc", + "wm/session_state_animator.h", "wm/session_state_animator_impl.cc", + "wm/session_state_animator_impl.h", + "wm/splitview/split_view_constants.h", "wm/splitview/split_view_controller.cc", "wm/splitview/split_view_divider.cc", + "wm/splitview/split_view_divider.h", "wm/splitview/split_view_drag_indicators.cc", + "wm/splitview/split_view_drag_indicators.h", "wm/splitview/split_view_highlight_view.cc", + "wm/splitview/split_view_highlight_view.h", "wm/splitview/split_view_utils.cc", + "wm/splitview/split_view_utils.h", "wm/stacking_controller.cc", + "wm/stacking_controller.h", "wm/switchable_windows.cc", + "wm/switchable_windows.h", "wm/system_gesture_event_filter.cc", + "wm/system_gesture_event_filter.h", "wm/system_modal_container_event_filter.cc", + "wm/system_modal_container_event_filter.h", + "wm/system_modal_container_event_filter_delegate.h", "wm/system_modal_container_layout_manager.cc", + "wm/system_modal_container_layout_manager.h", "wm/system_wallpaper_controller.cc", + "wm/system_wallpaper_controller.h", + "wm/tablet_mode/scoped_disable_internal_mouse_and_keyboard.h", "wm/tablet_mode/scoped_disable_internal_mouse_and_keyboard_ozone.cc", + "wm/tablet_mode/scoped_disable_internal_mouse_and_keyboard_ozone.h", "wm/tablet_mode/scoped_skip_user_session_blocked_check.cc", + "wm/tablet_mode/scoped_skip_user_session_blocked_check.h", "wm/tablet_mode/tablet_mode_app_window_drag_controller.cc", "wm/tablet_mode/tablet_mode_backdrop_delegate_impl.cc", + "wm/tablet_mode/tablet_mode_backdrop_delegate_impl.h", "wm/tablet_mode/tablet_mode_browser_window_drag_controller.cc", + "wm/tablet_mode/tablet_mode_browser_window_drag_controller.h", "wm/tablet_mode/tablet_mode_browser_window_drag_delegate.cc", + "wm/tablet_mode/tablet_mode_browser_window_drag_delegate.h", "wm/tablet_mode/tablet_mode_controller.cc", "wm/tablet_mode/tablet_mode_event_handler.cc", + "wm/tablet_mode/tablet_mode_event_handler.h", "wm/tablet_mode/tablet_mode_window_drag_delegate.cc", + "wm/tablet_mode/tablet_mode_window_drag_delegate.h", "wm/tablet_mode/tablet_mode_window_manager.cc", + "wm/tablet_mode/tablet_mode_window_manager.h", "wm/tablet_mode/tablet_mode_window_state.cc", + "wm/tablet_mode/tablet_mode_window_state.h", "wm/top_level_window_factory.cc", + "wm/top_level_window_factory.h", "wm/toplevel_window_event_handler.cc", + "wm/toplevel_window_event_handler.h", "wm/video_detector.cc", + "wm/video_detector.h", "wm/widget_finder.cc", + "wm/widget_finder.h", + "wm/window_animation_types.h", "wm/window_animations.cc", + "wm/window_animations.h", "wm/window_cycle_controller.cc", + "wm/window_cycle_controller.h", "wm/window_cycle_event_filter.cc", + "wm/window_cycle_event_filter.h", "wm/window_cycle_list.cc", + "wm/window_cycle_list.h", "wm/window_dimmer.cc", + "wm/window_dimmer.h", "wm/window_finder.cc", "wm/window_mirror_view.cc", + "wm/window_mirror_view.h", "wm/window_parenting_utils.cc", + "wm/window_parenting_utils.h", "wm/window_positioner.cc", "wm/window_positioning_utils.cc", "wm/window_properties.cc", @@ -1286,26 +1268,46 @@ "wm/window_state.cc", "wm/window_state_delegate.cc", "wm/window_state_util.cc", + "wm/window_state_util.h", "wm/window_transient_descendant_iterator.cc", + "wm/window_transient_descendant_iterator.h", "wm/window_util.cc", "wm/wm_event.cc", "wm/wm_shadow_controller_delegate.cc", + "wm/wm_shadow_controller_delegate.h", "wm/wm_snap_to_pixel_layout_manager.cc", + "wm/wm_snap_to_pixel_layout_manager.h", "wm/wm_toplevel_window_event_handler.cc", + "wm/wm_toplevel_window_event_handler.h", "wm/wm_window_animations.cc", + "wm/wm_window_animations.h", "wm/workspace/backdrop_controller.cc", + "wm/workspace/backdrop_controller.h", + "wm/workspace/backdrop_delegate.h", "wm/workspace/magnetism_matcher.cc", + "wm/workspace/magnetism_matcher.h", "wm/workspace/multi_window_resize_controller.cc", + "wm/workspace/multi_window_resize_controller.h", "wm/workspace/phantom_window_controller.cc", + "wm/workspace/phantom_window_controller.h", "wm/workspace/two_step_edge_cycler.cc", + "wm/workspace/two_step_edge_cycler.h", "wm/workspace/workspace_event_handler.cc", + "wm/workspace/workspace_event_handler.h", "wm/workspace/workspace_event_handler_classic.cc", + "wm/workspace/workspace_event_handler_classic.h", "wm/workspace/workspace_layout_manager.cc", + "wm/workspace/workspace_layout_manager.h", + "wm/workspace/workspace_types.h", "wm/workspace/workspace_window_resizer.cc", "wm/workspace_controller.cc", + "wm/workspace_controller.h", "ws/ash_gpu_interface_provider.cc", + "ws/ash_gpu_interface_provider.h", "ws/window_service_delegate_impl.cc", + "ws/window_service_delegate_impl.h", "ws/window_service_owner.cc", + "ws/window_service_owner.h", ] configs += [ "//build/config:precompiled_headers" ]
diff --git a/ash/app_list/views/search_result_suggestion_chip_view.cc b/ash/app_list/views/search_result_suggestion_chip_view.cc index 6a4ac34..f5261bb 100644 --- a/ash/app_list/views/search_result_suggestion_chip_view.cc +++ b/ash/app_list/views/search_result_suggestion_chip_view.cc
@@ -11,6 +11,7 @@ #include "ash/app_list/model/search/search_result.h" #include "ash/public/cpp/app_list/app_list_constants.h" #include "ash/public/cpp/app_list/internal_app_id_constants.h" +#include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_macros.h" #include "base/metrics/user_metrics.h" #include "ui/accessibility/ax_node_data.h" @@ -22,9 +23,14 @@ namespace { // Records an app being launched. -void LogAppLaunch() { +void LogAppLaunch(int index_in_suggestion_chip_container) { + DCHECK_GE(index_in_suggestion_chip_container, 0); + base::UmaHistogramSparse("Apps.AppListSuggestedChipLaunched", + index_in_suggestion_chip_container); + UMA_HISTOGRAM_BOOLEAN(kAppListAppLaunchedFullscreen, true /* suggested app */); + base::RecordAction(base::UserMetricsAction("AppList_OpenSuggestedApp")); } @@ -52,6 +58,11 @@ UpdateSuggestionChipView(); } +void SearchResultSuggestionChipView::SetIndexInSuggestionChipContainer( + size_t index) { + index_in_suggestion_chip_container_ = index; +} + void SearchResultSuggestionChipView::OnMetadataChanged() { UpdateSuggestionChipView(); } @@ -63,7 +74,7 @@ void SearchResultSuggestionChipView::ButtonPressed(views::Button* sender, const ui::Event& event) { DCHECK(item_); - LogAppLaunch(); + LogAppLaunch(index_in_suggestion_chip_container_); RecordSearchResultOpenSource(item_, view_delegate_->GetModel(), view_delegate_->GetSearchModel()); view_delegate_->OpenSearchResult(item_->id(), event.flags());
diff --git a/ash/app_list/views/search_result_suggestion_chip_view.h b/ash/app_list/views/search_result_suggestion_chip_view.h index ff0b4938..ce7d90b 100644 --- a/ash/app_list/views/search_result_suggestion_chip_view.h +++ b/ash/app_list/views/search_result_suggestion_chip_view.h
@@ -26,6 +26,7 @@ SearchResult* result() { return item_; } void SetSearchResult(SearchResult* item); + void SetIndexInSuggestionChipContainer(size_t index); // SearchResultObserver: void OnMetadataChanged() override; @@ -54,6 +55,9 @@ // The view that actually shows the icon and title. SuggestionChipView* suggestion_chip_view_ = nullptr; + // The index of this view in the suggestion_chip_container, only used for uma + // logging. + int index_in_suggestion_chip_container_ = -1; base::WeakPtrFactory<SearchResultSuggestionChipView> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(SearchResultSuggestionChipView);
diff --git a/ash/app_list/views/suggestion_chip_container_view.cc b/ash/app_list/views/suggestion_chip_container_view.cc index 079290f5..fa3d44b 100644 --- a/ash/app_list/views/suggestion_chip_container_view.cc +++ b/ash/app_list/views/suggestion_chip_container_view.cc
@@ -62,10 +62,12 @@ // Create a suggestion chip for each search result, but wait until layout to // add them as child views when we know this view's bounds. - for (auto* result : display_results) { + for (size_t i = 0; i < display_results.size(); ++i) { + auto* result = display_results[i]; SearchResultSuggestionChipView* chip = new SearchResultSuggestionChipView(view_delegate_); chip->SetSearchResult(result); + chip->SetIndexInSuggestionChipContainer(i); suggestion_chip_views_.emplace_back(chip); }
diff --git a/ash/keyboard/virtual_keyboard_controller.cc b/ash/keyboard/virtual_keyboard_controller.cc index cc4ed450..06a3ad0 100644 --- a/ash/keyboard/virtual_keyboard_controller.cc +++ b/ash/keyboard/virtual_keyboard_controller.cc
@@ -36,15 +36,23 @@ keyboard::switches::kEnableVirtualKeyboard); } -void DisableVirtualKeyboard() { - // Reset the accessibility keyboard settings. - AccessibilityController* accessibility_controller = - Shell::Get()->accessibility_controller(); - if (!accessibility_controller) - return; +void ResetVirtualKeyboard(bool disable_accessibility_keyboard) { + if (disable_accessibility_keyboard) { + // Reset the accessibility keyboard settings. + AccessibilityController* accessibility_controller = + Shell::Get()->accessibility_controller(); + if (!accessibility_controller) + return; - DCHECK(accessibility_controller->IsVirtualKeyboardEnabled()); - accessibility_controller->SetVirtualKeyboardEnabled(false); + DCHECK(accessibility_controller->IsVirtualKeyboardEnabled()); + accessibility_controller->SetVirtualKeyboardEnabled(false); + } + + // Reset the keyset after disabling the virtual keyboard to prevent the IME + // extension from accidentally loading the default keyset while it's shutting + // down. See https://crbug.com/875456. + Shell::Get()->ime_controller()->OverrideKeyboardKeyset( + chromeos::input_method::mojom::ImeKeyset::kNone); } void MoveKeyboardToDisplayInternal(const display::Display& display) { @@ -307,16 +315,11 @@ if (is_temporary_hide) return; - Shell::Get()->ime_controller()->OverrideKeyboardKeyset( - chromeos::input_method::mojom::ImeKeyset::kNone); - - if (keyboard_enabled_using_accessibility_prefs_) { - keyboard_enabled_using_accessibility_prefs_ = false; - - // Posts a task to disable the virtual keyboard. - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::BindOnce(DisableVirtualKeyboard)); - } + // Post a task to reset the virtual keyboard to its original state. + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::BindOnce(ResetVirtualKeyboard, + keyboard_enabled_using_accessibility_prefs_)); + keyboard_enabled_using_accessibility_prefs_ = false; } void VirtualKeyboardController::OnActiveUserSessionChanged(
diff --git a/ash/public/cpp/shelf_model.cc b/ash/public/cpp/shelf_model.cc index ddc5f0a..e16ac99 100644 --- a/ash/public/cpp/shelf_model.cc +++ b/ash/public/cpp/shelf_model.cc
@@ -185,6 +185,24 @@ } } +// TODO(manucornet): Add some simple unit tests for this method. +void ShelfModel::SetActiveShelfID(const ShelfID& shelf_id) { + if (active_shelf_id_ == shelf_id) + return; + + ShelfID old_active_id = active_shelf_id_; + active_shelf_id_ = shelf_id; + if (!old_active_id.IsNull()) + OnItemStatusChanged(old_active_id); + if (!active_shelf_id_.IsNull()) + OnItemStatusChanged(active_shelf_id_); +} + +void ShelfModel::OnItemStatusChanged(const ShelfID& id) { + for (auto& observer : observers_) + observer.ShelfItemStatusChanged(id); +} + void ShelfModel::RemoveNotificationRecord(const std::string& notification_id) { auto notification_id_it = notification_id_to_app_id_.find(notification_id);
diff --git a/ash/public/cpp/shelf_model.h b/ash/public/cpp/shelf_model.h index f1db8596..fd438acfc 100644 --- a/ash/public/cpp/shelf_model.h +++ b/ash/public/cpp/shelf_model.h
@@ -65,6 +65,17 @@ // Resets the item at the specified index. The item's id should not change. void Set(int index, const ShelfItem& item); + // Returns the ID of the currently active item, or an empty ShelfID if + // nothing is currently active. + const ShelfID& active_shelf_id() const { return active_shelf_id_; } + + // Sets |shelf_id| to be the newly active shelf item. + void SetActiveShelfID(const ShelfID& shelf_id); + + // Notifies observers that the status of the item corresponding to |id| + // has changed. + void OnItemStatusChanged(const ShelfID& id); + // Adds a record of the notification with this app id and notifies observers. void AddNotificationRecord(const std::string& app_id, const std::string& notification_id); @@ -123,6 +134,10 @@ ShelfItems items_; + // The shelf ID of the currently active shelf item, or an empty ID if + // nothing is active. + ShelfID active_shelf_id_; + // Maps one app id to a set of all matching notification ids. std::map<std::string, std::set<std::string>> app_id_to_notification_id_; // Maps one notification id to one app id.
diff --git a/ash/public/cpp/shelf_model_observer.h b/ash/public/cpp/shelf_model_observer.h index fa8487e..364c3ce 100644 --- a/ash/public/cpp/shelf_model_observer.h +++ b/ash/public/cpp/shelf_model_observer.h
@@ -36,6 +36,11 @@ ShelfItemDelegate* old_delegate, ShelfItemDelegate* delegate) {} + // Invoked when the status of the item corresponding to |id| changes. Only + // observers within ash (typically the shelf views) need to respond to this + // event. + virtual void ShelfItemStatusChanged(const ShelfID& id) {} + protected: virtual ~ShelfModelObserver() {} };
diff --git a/ash/public/cpp/shelf_struct_mojom_traits.h b/ash/public/cpp/shelf_struct_mojom_traits.h index 4806b1c9..623ff8e 100644 --- a/ash/public/cpp/shelf_struct_mojom_traits.h +++ b/ash/public/cpp/shelf_struct_mojom_traits.h
@@ -66,8 +66,6 @@ return ash::mojom::ShelfItemStatus::CLOSED; case ash::STATUS_RUNNING: return ash::mojom::ShelfItemStatus::RUNNING; - case ash::STATUS_ACTIVE: - return ash::mojom::ShelfItemStatus::ACTIVE; case ash::STATUS_ATTENTION: return ash::mojom::ShelfItemStatus::ATTENTION; } @@ -84,8 +82,6 @@ case ash::mojom::ShelfItemStatus::RUNNING: *out = ash::STATUS_RUNNING; return true; - case ash::mojom::ShelfItemStatus::ACTIVE: - *out = ash::STATUS_ACTIVE; return true; case ash::mojom::ShelfItemStatus::ATTENTION: *out = ash::STATUS_ATTENTION;
diff --git a/ash/public/cpp/shelf_types.h b/ash/public/cpp/shelf_types.h index 0527851..c0f5bcd 100644 --- a/ash/public/cpp/shelf_types.h +++ b/ash/public/cpp/shelf_types.h
@@ -142,8 +142,6 @@ STATUS_CLOSED, // A shelf item that has live instance. STATUS_RUNNING, - // A shelf item one of whose windows is currently active. - STATUS_ACTIVE, // A shelf item that needs user's attention. STATUS_ATTENTION, };
diff --git a/ash/public/interfaces/shelf.mojom b/ash/public/interfaces/shelf.mojom index ba09d3d..36d5defa 100644 --- a/ash/public/interfaces/shelf.mojom +++ b/ash/public/interfaces/shelf.mojom
@@ -24,7 +24,6 @@ enum ShelfItemStatus { CLOSED, // A closed shelf item, i.e. has no live instance. RUNNING, // A shelf item that has live instance. - ACTIVE, // A shelf item that owns the currently active window. ATTENTION, // A shelf item that needs user's attention. };
diff --git a/ash/shelf/shelf_view.cc b/ash/shelf/shelf_view.cc index e89225f..8c4678a 100644 --- a/ash/shelf/shelf_view.cc +++ b/ash/shelf/shelf_view.cc
@@ -226,26 +226,29 @@ }; void ReflectItemStatus(const ShelfItem& item, ShelfButton* button) { + ShelfID active_id = Shell::Get()->shelf_model()->active_shelf_id(); + if (!active_id.IsNull() && item.id == active_id) { + // The active status trumps all other statuses. + button->AddState(ShelfButton::STATE_ACTIVE); + button->ClearState(ShelfButton::STATE_RUNNING); + button->ClearState(ShelfButton::STATE_ATTENTION); + return; + } + + button->ClearState(ShelfButton::STATE_ACTIVE); + switch (item.status) { case STATUS_CLOSED: button->ClearState(ShelfButton::STATE_RUNNING); - button->ClearState(ShelfButton::STATE_ACTIVE); - button->ClearState(ShelfButton::STATE_ATTENTION); - break; - case STATUS_ACTIVE: - button->AddState(ShelfButton::STATE_ACTIVE); - button->AddState(ShelfButton::STATE_RUNNING); button->ClearState(ShelfButton::STATE_ATTENTION); break; case STATUS_RUNNING: button->AddState(ShelfButton::STATE_RUNNING); - button->ClearState(ShelfButton::STATE_ACTIVE); button->ClearState(ShelfButton::STATE_ATTENTION); break; case STATUS_ATTENTION: button->ClearState(ShelfButton::STATE_RUNNING); button->AddState(ShelfButton::STATE_ATTENTION); - button->ClearState(ShelfButton::STATE_ACTIVE); break; } @@ -1956,6 +1959,20 @@ ShelfItemDelegate* old_delegate, ShelfItemDelegate* delegate) {} +void ShelfView::ShelfItemStatusChanged(const ShelfID& id) { + int index = model_->ItemIndexByID(id); + if (index < 0) + return; + + const ShelfItem item = model_->items()[index]; + views::View* view = view_model_->view_at(index); + CHECK_EQ(ShelfButton::kViewClassName, view->GetClassName()); + // TODO(manucornet): Add a helper to get the button. + ShelfButton* button = static_cast<ShelfButton*>(view); + ReflectItemStatus(item, button); + button->SchedulePaint(); +} + void ShelfView::AfterItemSelected( const ShelfItem& item, views::Button* sender,
diff --git a/ash/shelf/shelf_view.h b/ash/shelf/shelf_view.h index 3301bb8..c8c20bc 100644 --- a/ash/shelf/shelf_view.h +++ b/ash/shelf/shelf_view.h
@@ -401,6 +401,7 @@ void ShelfItemDelegateChanged(const ShelfID& id, ShelfItemDelegate* old_delegate, ShelfItemDelegate* delegate) override; + void ShelfItemStatusChanged(const ShelfID& id) override; // Handles the result when querying ShelfItemDelegates for context menu items. // Shows a default shelf context menu with optional extra custom |menu_items|.
diff --git a/ash/shelf/shelf_window_watcher.cc b/ash/shelf/shelf_window_watcher.cc index 1675018b..efaa3a29 100644 --- a/ash/shelf/shelf_window_watcher.cc +++ b/ash/shelf/shelf_window_watcher.cc
@@ -253,6 +253,9 @@ OnUserWindowPropertyChanged(gained_active); if (lost_active && user_windows_with_items_.count(lost_active) > 0) OnUserWindowPropertyChanged(lost_active); + + model_->SetActiveShelfID(gained_active ? GetShelfID(gained_active) + : ShelfID()); } void ShelfWindowWatcher::OnRootWindowAdded(aura::Window* root_window) {
diff --git a/ash/system/accessibility/select_to_speak_tray.cc b/ash/system/accessibility/select_to_speak_tray.cc index 79028e58..cd50de3 100644 --- a/ash/system/accessibility/select_to_speak_tray.cc +++ b/ash/system/accessibility/select_to_speak_tray.cc
@@ -6,11 +6,13 @@ #include "ash/accessibility/accessibility_controller.h" #include "ash/resources/vector_icons/vector_icons.h" +#include "ash/session/session_controller.h" #include "ash/shelf/shelf_constants.h" #include "ash/shell.h" #include "ash/strings/grit/ash_strings.h" #include "ash/system/tray/tray_constants.h" #include "ash/system/tray/tray_container.h" +#include "ash/system/tray/tray_utils.h" #include "ui/base/l10n/l10n_util.h" #include "ui/gfx/paint_vector_icon.h" #include "ui/views/border.h" @@ -31,11 +33,7 @@ : TrayBackgroundView(shelf), icon_(new views::ImageView()) { SetInkDropMode(InkDropMode::ON); - inactive_image_ = - gfx::CreateVectorIcon(kSystemTraySelectToSpeakIcon, kShelfIconColor); - selecting_image_ = gfx::CreateVectorIcon(kSystemTraySelectToSpeakActiveIcon, - kShelfIconColor); - speaking_image_ = gfx::CreateVectorIcon(kSystemTrayStopIcon, kShelfIconColor); + UpdateIconsForSession(); icon_->SetImage(inactive_image_); const int vertical_padding = (kTrayItemSize - inactive_image_.height()) / 2; const int horizontal_padding = (kTrayItemSize - inactive_image_.width()) / 2; @@ -73,10 +71,27 @@ CheckStatusAndUpdateIcon(); } +void SelectToSpeakTray::OnSessionStateChanged( + session_manager::SessionState state) { + UpdateIconsForSession(); + CheckStatusAndUpdateIcon(); +} + bool SelectToSpeakTray::ContainsPointInScreen(const gfx::Point& point) { return GetBoundsInScreen().Contains(point); } +void SelectToSpeakTray::UpdateIconsForSession() { + session_manager::SessionState session_state = + Shell::Get()->session_controller()->GetSessionState(); + SkColor color = TrayIconColor(session_state); + + inactive_image_ = gfx::CreateVectorIcon(kSystemTraySelectToSpeakIcon, color); + selecting_image_ = + gfx::CreateVectorIcon(kSystemTraySelectToSpeakActiveIcon, color); + speaking_image_ = gfx::CreateVectorIcon(kSystemTrayStopIcon, color); +} + void SelectToSpeakTray::CheckStatusAndUpdateIcon() { if (!Shell::Get()->accessibility_controller()->IsSelectToSpeakEnabled()) { SetVisible(false);
diff --git a/ash/system/accessibility/select_to_speak_tray.h b/ash/system/accessibility/select_to_speak_tray.h index 96419c52..3f38158 100644 --- a/ash/system/accessibility/select_to_speak_tray.h +++ b/ash/system/accessibility/select_to_speak_tray.h
@@ -7,6 +7,7 @@ #include "ash/accessibility/accessibility_observer.h" #include "ash/ash_export.h" +#include "ash/session/session_observer.h" #include "ash/system/tray/tray_background_view.h" #include "base/macros.h" #include "ui/views/controls/image_view.h" @@ -19,7 +20,8 @@ // A button in the tray that lets users start/stop Select-to-Speak. class ASH_EXPORT SelectToSpeakTray : public TrayBackgroundView, - public AccessibilityObserver { + public AccessibilityObserver, + public SessionObserver { public: explicit SelectToSpeakTray(Shelf* shelf); ~SelectToSpeakTray() override; @@ -34,6 +36,9 @@ // AccessibilityObserver: void OnAccessibilityStatusChanged() override; + // SessionObserver: + void OnSessionStateChanged(session_manager::SessionState state) override; + // Returns true if the screen point passed in is contained within this tray's // bounds. bool ContainsPointInScreen(const gfx::Point& point); @@ -41,6 +46,9 @@ private: friend class SelectToSpeakTrayTest; + // Updates the icons color depending on if the user is logged-in or not. + void UpdateIconsForSession(); + // Sets the icon when select-to-speak is activated (speaking) / deactivated. // Also updates visibility when select-to-speak is enabled / disabled. void CheckStatusAndUpdateIcon(); @@ -52,6 +60,8 @@ // Weak pointer, will be parented by TrayContainer for its lifetime. views::ImageView* icon_; + ScopedSessionObserver session_observer_{this}; + DISALLOW_COPY_AND_ASSIGN(SelectToSpeakTray); };
diff --git a/ash/system/tray/tray_constants.h b/ash/system/tray/tray_constants.h index 6cae145f..7fcb580 100644 --- a/ash/system/tray/tray_constants.h +++ b/ash/system/tray/tray_constants.h
@@ -140,7 +140,7 @@ SkColorSetA(kUnifiedMenuBackgroundColor, 0x99); constexpr float kUnifiedMenuBackgroundBlur = 30.f; constexpr SkColor kUnifiedMenuTextColor = SkColorSetRGB(0xf1, 0xf3, 0xf4); -constexpr SkColor kUnifiedMenuIconColor = SkColorSetRGB(0xf1, 0xf3, 0xf4); +constexpr SkColor kUnifiedMenuIconColor = SkColorSetRGB(0xe8, 0xea, 0xed); constexpr SkColor kUnifiedMenuSecondaryTextColor = SkColorSetA(kUnifiedMenuIconColor, 0xa3); constexpr SkColor kUnifiedMenuIconColorDisabled = @@ -176,7 +176,9 @@ constexpr int kStackingNotificationCounterDistanceX = 10; constexpr int kStackingNotificationCounterHeight = 20; constexpr SkColor kStackingNotificationCounterColor = - SkColorSetRGB(0xeb, 0xea, 0xed); + SkColorSetRGB(0x5f, 0x63, 0x68); +constexpr SkColor kStackingNotificationCounterBorderColor = + SkColorSetRGB(0xe0, 0xe0, 0xe0); // Size of an icon drawn inside top shortcut buttons. // A dark disc with |kTrayItemSize| diameter is drawn in the background.
diff --git a/ash/system/unified/unified_message_center_view.cc b/ash/system/unified/unified_message_center_view.cc index dd321ca7..f7ca722d 100644 --- a/ash/system/unified/unified_message_center_view.cc +++ b/ash/system/unified/unified_message_center_view.cc
@@ -13,9 +13,11 @@ #include "ui/gfx/canvas.h" #include "ui/message_center/message_center.h" #include "ui/message_center/message_center_types.h" +#include "ui/message_center/public/cpp/message_center_constants.h" #include "ui/message_center/views/message_view.h" #include "ui/message_center/views/message_view_factory.h" #include "ui/message_center/views/notification_control_buttons_view.h" +#include "ui/views/border.h" #include "ui/views/controls/scroll_view.h" #include "ui/views/layout/box_layout.h" #include "ui/views/widget/widget.h" @@ -33,7 +35,10 @@ } // namespace -StackingNotificationCounterView::StackingNotificationCounterView() = default; +StackingNotificationCounterView::StackingNotificationCounterView() { + SetBorder(views::CreateSolidSidedBorder( + 0, 0, 1, 0, kStackingNotificationCounterBorderColor)); +} StackingNotificationCounterView::~StackingNotificationCounterView() = default; @@ -48,15 +53,25 @@ const int y = kStackingNotificationCounterHeight / 2; cc::PaintFlags flags; - flags.setColor(kStackingNotificationCounterColor); + flags.setColor(message_center::kNotificationBackgroundColor); flags.setStyle(cc::PaintFlags::kFill_Style); flags.setAntiAlias(true); + SkPath background_path; + SkScalar top_radius = SkIntToScalar(kUnifiedTrayCornerRadius); + SkScalar radii[8] = {top_radius, top_radius, top_radius, top_radius, + 0, 0, 0, 0}; + background_path.addRoundRect(gfx::RectToSkRect(GetLocalBounds()), radii); + canvas->DrawPath(background_path, flags); + + flags.setColor(kStackingNotificationCounterColor); for (int i = 0; i < stacking_count_; ++i) { canvas->DrawCircle(gfx::Point(x, y), kStackingNotificationCounterRadius, flags); x += kStackingNotificationCounterDistanceX; } + + views::View::OnPaint(canvas); } // UnifiedMessageCenterView
diff --git a/ash/wm/overview/window_grid.cc b/ash/wm/overview/window_grid.cc index 22aae517..2c5b415 100644 --- a/ash/wm/overview/window_grid.cc +++ b/ash/wm/overview/window_grid.cc
@@ -64,7 +64,6 @@ // The color and opacity of the screen shield in overview. constexpr SkColor kShieldColor = SkColorSetARGB(255, 0, 0, 0); -constexpr float kShieldOpacity = 0.6f; // The color and opacity of the overview selector. constexpr SkColor kWindowSelectionColor = SkColorSetARGB(36, 255, 255, 255); @@ -347,6 +346,22 @@ WindowGrid::~WindowGrid() = default; +// static +SkColor WindowGrid::GetShieldColor() { + SkColor shield_color = kShieldColor; + // Extract the dark muted color from the wallpaper and mix it with + // |kShieldBaseColor|. Just use |kShieldBaseColor| if the dark muted color + // could not be extracted. + SkColor dark_muted_color = + Shell::Get()->wallpaper_controller()->GetProminentColor( + color_utils::ColorProfile()); + if (dark_muted_color != ash::kInvalidWallpaperColor) { + shield_color = + color_utils::GetResultingPaintColor(kShieldBaseColor, dark_muted_color); + } + return shield_color; +} + void WindowGrid::Shutdown() { for (const auto& window : window_list_) window->Shutdown(); @@ -1076,17 +1091,6 @@ SHELF_BACKGROUND_MAXIMIZED) ? 1.f : 0.f; - SkColor shield_color = kShieldColor; - // Extract the dark muted color from the wallpaper and mix it with - // |kShieldBaseColor|. Just use |kShieldBaseColor| if the dark muted color - // could not be extracted. - SkColor dark_muted_color = - Shell::Get()->wallpaper_controller()->GetProminentColor( - color_utils::ColorProfile()); - if (dark_muted_color != ash::kInvalidWallpaperColor) { - shield_color = - color_utils::GetResultingPaintColor(kShieldBaseColor, dark_muted_color); - } shield_widget_ = CreateBackgroundWidget( root_window_, ui::LAYER_SOLID_COLOR, SK_ColorTRANSPARENT, 0, 0, SK_ColorTRANSPARENT, initial_opacity, /*parent=*/nullptr, @@ -1098,7 +1102,7 @@ // Create |shield_view_| and animate its background and label if needed. shield_view_ = new ShieldView(); - shield_view_->SetBackgroundColor(shield_color); + shield_view_->SetBackgroundColor(GetShieldColor()); shield_view_->SetGridBounds(bounds_); shield_widget_->SetContentsView(shield_view_); shield_widget_->SetOpacity(initial_opacity);
diff --git a/ash/wm/overview/window_grid.h b/ash/wm/overview/window_grid.h index 8746c48..50fa510 100644 --- a/ash/wm/overview/window_grid.h +++ b/ash/wm/overview/window_grid.h
@@ -58,6 +58,13 @@ const gfx::Rect& bounds_in_screen); ~WindowGrid() override; + // The opacity of the shield widget that is used to darden the background of + // the grid. + static constexpr float kShieldOpacity = 0.6f; + + // Returns the shield color that is used to darken the background of the grid. + static SkColor GetShieldColor(); + // Exits overview mode, fading out the |shield_widget_| if necessary. void Shutdown();
diff --git a/ash/wm/overview/window_selector_controller.cc b/ash/wm/overview/window_selector_controller.cc index 382b8be..49482d4 100644 --- a/ash/wm/overview/window_selector_controller.cc +++ b/ash/wm/overview/window_selector_controller.cc
@@ -38,7 +38,6 @@ // when this is true. bool g_disable_wallpaper_blur_for_tests = false; -constexpr double kWallpaperClearBlurSigma = 0.f; constexpr int kBlurSlideDurationMs = 250; // Returns true if |window| should be hidden when entering overview. @@ -144,17 +143,17 @@ if (state_ == WallpaperAnimationState::kNormal) return; - double value = state_ == WallpaperAnimationState::kAddingBlur - ? kWallpaperBlurSigma - : kWallpaperClearBlurSigma; + float value = state_ == WallpaperAnimationState::kAddingBlur + ? kWallpaperBlurSigma + : kWallpaperClearBlurSigma; for (aura::Window* root : roots_to_animate_) ApplyBlur(root, value); state_ = WallpaperAnimationState::kNormal; } void AnimationProgressed(const gfx::Animation* animation) override { - double value = animation_.CurrentValueBetween(kWallpaperClearBlurSigma, - kWallpaperBlurSigma); + float value = animation_.CurrentValueBetween(kWallpaperClearBlurSigma, + kWallpaperBlurSigma); for (aura::Window* root : roots_to_animate_) ApplyBlur(root, value); } @@ -177,7 +176,7 @@ void ApplyBlur(aura::Window* root, float blur_sigma) { RootWindowController::ForWindow(root) ->wallpaper_widget_controller() - ->SetWallpaperBlur(static_cast<float>(blur_sigma)); + ->SetWallpaperBlur(blur_sigma); } // Called when the wallpaper is to be changed. Checks to see which root @@ -186,7 +185,7 @@ // the wallpaper does not need blur animation. void OnBlurChange() { const bool should_blur = state_ == WallpaperAnimationState::kAddingBlur; - const double value = + const float value = should_blur ? kWallpaperBlurSigma : kWallpaperClearBlurSigma; for (aura::Window* root : roots_to_animate_) root->RemoveObserver(this);
diff --git a/ash/wm/overview/window_selector_controller.h b/ash/wm/overview/window_selector_controller.h index 03f30f5f..dcf32633c 100644 --- a/ash/wm/overview/window_selector_controller.h +++ b/ash/wm/overview/window_selector_controller.h
@@ -27,7 +27,8 @@ // Amount of blur to apply on the wallpaper when we enter or exit overview // mode. - static constexpr double kWallpaperBlurSigma = 10.f; + static constexpr float kWallpaperBlurSigma = 10.f; + static constexpr float kWallpaperClearBlurSigma = 0.f; // Returns true if selecting windows in an overview is enabled. This is false // at certain times, such as when the lock screen is visible.
diff --git a/ash/wm/splitview/split_view_controller_unittest.cc b/ash/wm/splitview/split_view_controller_unittest.cc index 5123de9..0173e81 100644 --- a/ash/wm/splitview/split_view_controller_unittest.cc +++ b/ash/wm/splitview/split_view_controller_unittest.cc
@@ -4,6 +4,7 @@ #include "ash/wm/splitview/split_view_controller.h" +#include "ash/app_list/app_list_controller_impl.h" #include "ash/display/screen_orientation_controller.h" #include "ash/display/screen_orientation_controller_test_api.h" #include "ash/public/cpp/app_types.h" @@ -18,6 +19,7 @@ #include "ash/system/status_area_widget.h" #include "ash/system/status_area_widget_test_helper.h" #include "ash/test/ash_test_base.h" +#include "ash/wallpaper/wallpaper_controller.h" #include "ash/wm/drag_window_resizer.h" #include "ash/wm/drag_window_resizer_mash.h" #include "ash/wm/mru_window_tracker.h" @@ -2549,6 +2551,52 @@ EXPECT_FALSE(shadow_controller->IsShadowVisibleForWindow(window2.get())); } +// Test that if the source window needs to be scaled up/down because of dragging +// a tab window out of it, other windows' visibilities and the home launcher's +// visibility should change accordingly. +TEST_F(SplitViewTabDraggingTest, SourceWindowBackgroundTest) { + const gfx::Rect bounds(0, 0, 400, 400); + std::unique_ptr<aura::Window> window1(CreateWindow(bounds)); + std::unique_ptr<aura::Window> window2(CreateWindow(bounds)); + std::unique_ptr<aura::Window> window3(CreateWindow(bounds)); + std::unique_ptr<aura::Window> window4(CreateWindow(bounds)); + EXPECT_TRUE(window1->IsVisible()); + EXPECT_TRUE(window2->IsVisible()); + EXPECT_TRUE(window3->IsVisible()); + EXPECT_TRUE(window4->IsVisible()); + + // 1) Start dragging |window1|. |window2| is the source window. + std::unique_ptr<WindowResizer> resizer = + StartDrag(window1.get(), window2.get()); + DragWindowWithOffset(resizer.get(), 10, 10); + + // Test that |window3| should be hidden now. |window1| and |window2| should + // stay visible during dragging. + EXPECT_TRUE(window1->IsVisible()); + EXPECT_TRUE(window2->IsVisible()); + EXPECT_FALSE(window3->IsVisible()); + EXPECT_FALSE(window4->IsVisible()); + + // Test that home launcher should be dismissed. + if (Shell::Get()->app_list_controller()->IsHomeLauncherEnabledInTabletMode()) + EXPECT_FALSE(Shell::Get()->app_list_controller()->IsVisible()); + + // Test that during dragging, we could not show a hidden window. + window3->Show(); + EXPECT_FALSE(window3->IsVisible()); + + // After dragging, the windows' visibilities should have restored. + CompleteDrag(std::move(resizer)); + EXPECT_TRUE(window1->IsVisible()); + EXPECT_TRUE(window2->IsVisible()); + EXPECT_TRUE(window3->IsVisible()); + EXPECT_TRUE(window4->IsVisible()); + + // Test that home launcher should be reshown. + if (Shell::Get()->app_list_controller()->IsHomeLauncherEnabledInTabletMode()) + EXPECT_TRUE(Shell::Get()->app_list_controller()->IsVisible()); +} + class TestWindowDelegateWithWidget : public views::WidgetDelegate { public: TestWindowDelegateWithWidget(bool can_activate)
diff --git a/ash/wm/tablet_mode/tablet_mode_browser_window_drag_delegate.cc b/ash/wm/tablet_mode/tablet_mode_browser_window_drag_delegate.cc index ddd47ab..2c250eaa 100644 --- a/ash/wm/tablet_mode/tablet_mode_browser_window_drag_delegate.cc +++ b/ash/wm/tablet_mode/tablet_mode_browser_window_drag_delegate.cc
@@ -4,7 +4,13 @@ #include "ash/wm/tablet_mode/tablet_mode_browser_window_drag_delegate.h" +#include <vector> + +#include "ash/app_list/app_list_controller_impl.h" +#include "ash/root_window_controller.h" #include "ash/shell.h" +#include "ash/wallpaper/wallpaper_widget_controller.h" +#include "ash/wm/mru_window_tracker.h" #include "ash/wm/overview/overview_utils.h" #include "ash/wm/overview/window_grid.h" #include "ash/wm/overview/window_selector_controller.h" @@ -130,6 +136,141 @@ } // namespace +// WindowsHider hides all visible windows except the currently dragged window +// and the dragged window's source window upon its creation, and restores the +// windows' visibility upon its destruction. It also blurs and darkens the +// background, hides the home launcher if home launcher is enabled. Only need to +// do so if we need to scale up and down the source window when dragging a tab +// window out of it. +class TabletModeBrowserWindowDragDelegate::WindowsHider + : public aura::WindowObserver { + public: + explicit WindowsHider(aura::Window* dragged_window) + : dragged_window_(dragged_window) { + DCHECK(dragged_window); + aura::Window* source_window = + dragged_window->GetProperty(ash::kTabDraggingSourceWindowKey); + DCHECK(source_window); + + // Disable the backdrop for |source_window| during dragging. + source_window_backdrop_ = source_window->GetProperty(kBackdropWindowMode); + source_window->SetProperty(kBackdropWindowMode, + BackdropWindowMode::kDisabled); + + DCHECK(!Shell::Get()->window_selector_controller()->IsSelecting()); + + aura::Window* root_window = dragged_window->GetRootWindow(); + std::vector<aura::Window*> windows = + Shell::Get()->mru_window_tracker()->BuildMruWindowList(); + for (aura::Window* window : windows) { + if (window == dragged_window || window == source_window || + window->GetRootWindow() != root_window) { + continue; + } + + window_visibility_map_.emplace(window, window->IsVisible()); + if (window->IsVisible()) + window->Hide(); + window->AddObserver(this); + } + + // Hide the home launcher if it's enabled during dragging. + AppListControllerImpl* app_list_controller = + Shell::Get()->app_list_controller(); + if (app_list_controller->IsHomeLauncherEnabledInTabletMode()) + app_list_controller->DismissAppList(); + + // Blurs the wallpaper background. + RootWindowController::ForWindow(root_window) + ->wallpaper_widget_controller() + ->SetWallpaperBlur( + static_cast<float>(WindowSelectorController::kWallpaperBlurSigma)); + + // Darken the background. + shield_widget_ = CreateBackgroundWidget( + root_window, ui::LAYER_SOLID_COLOR, SK_ColorTRANSPARENT, 0, 0, + SK_ColorTRANSPARENT, /*initial_opacity*/ 1.f, /*parent=*/nullptr, + /*stack_on_top=*/true); + aura::Window* widget_window = shield_widget_->GetNativeWindow(); + const gfx::Rect bounds = widget_window->parent()->bounds(); + widget_window->SetBounds(bounds); + views::View* shield_view = new views::View(); + shield_view->SetPaintToLayer(ui::LAYER_SOLID_COLOR); + shield_view->layer()->SetColor(WindowGrid::GetShieldColor()); + shield_view->layer()->SetOpacity(WindowGrid::kShieldOpacity); + shield_widget_->SetContentsView(shield_view); + } + + ~WindowsHider() override { + // It might be possible that |source_window| is destroyed during dragging. + aura::Window* source_window = + dragged_window_->GetProperty(ash::kTabDraggingSourceWindowKey); + if (source_window) + source_window->SetProperty(kBackdropWindowMode, source_window_backdrop_); + + for (auto iter = window_visibility_map_.begin(); + iter != window_visibility_map_.end(); ++iter) { + iter->first->RemoveObserver(this); + if (iter->second) + iter->first->Show(); + } + + DCHECK(!Shell::Get()->window_selector_controller()->IsSelecting()); + + // Reshow the home launcher if it's enabled after dragging. + AppListControllerImpl* app_list_controller = + Shell::Get()->app_list_controller(); + if (app_list_controller->IsHomeLauncherEnabledInTabletMode()) + app_list_controller->ShowAppList(); + + // Clears the background wallpaper blur. + RootWindowController::ForWindow(dragged_window_->GetRootWindow()) + ->wallpaper_widget_controller() + ->SetWallpaperBlur(WindowSelectorController::kWallpaperClearBlurSigma); + + // Clears the background darken widget. + shield_widget_.reset(); + } + + // aura::WindowObserver: + void OnWindowDestroying(aura::Window* window) override { + window->RemoveObserver(this); + window_visibility_map_.erase(window); + } + + void OnWindowVisibilityChanged(aura::Window* window, bool visible) override { + if (visible) { + // Do not let |window| change to visible during the lifetime of |this|. + // Also update |window_visibility_map_| so that we can restore the window + // visibility correctly. + window->Hide(); + window_visibility_map_[window] = visible; + } + // else do nothing. It must come from Hide() function above thus should be + // ignored. + } + + private: + // The currently dragged window. Guaranteed to be non-nullptr during the + // lifetime of |this|. + aura::Window* dragged_window_; + + // A shield that darkens the entire background during dragging. It should + // have the same effect as in overview. + std::unique_ptr<views::Widget> shield_widget_; + + // Maintains the map between windows and their visibilities. All windows + // except the dragged window and the source window should stay hidden during + // dragging. + std::map<aura::Window*, bool> window_visibility_map_; + + // The original backdrop mode of the source window. Should be disabled during + // dragging. + BackdropWindowMode source_window_backdrop_ = BackdropWindowMode::kAuto; + + DISALLOW_COPY_AND_ASSIGN(WindowsHider); +}; + TabletModeBrowserWindowDragDelegate::TabletModeBrowserWindowDragDelegate() = default; @@ -172,6 +313,7 @@ wm::GetWindowState(source_window)); } scrim_.reset(); + windows_hider_.reset(); } bool TabletModeBrowserWindowDragDelegate::ShouldOpenOverviewWhenDragStarts() { @@ -196,6 +338,10 @@ return; } + // Only create WindowHider if we need to scale up/down the source window. + if (!windows_hider_) + windows_hider_ = std::make_unique<WindowsHider>(dragged_window_); + const gfx::Rect work_area_bounds = display::Screen::GetScreen() ->GetDisplayNearestWindow(dragged_window_)
diff --git a/ash/wm/tablet_mode/tablet_mode_browser_window_drag_delegate.h b/ash/wm/tablet_mode/tablet_mode_browser_window_drag_delegate.h index 34cda533d..d568788 100644 --- a/ash/wm/tablet_mode/tablet_mode_browser_window_drag_delegate.h +++ b/ash/wm/tablet_mode/tablet_mode_browser_window_drag_delegate.h
@@ -24,6 +24,8 @@ ~TabletModeBrowserWindowDragDelegate() override; private: + class WindowsHider; + // TabletModeWindowDragDelegate: void PrepareForDraggedWindow(const gfx::Point& location_in_screen) override; void UpdateForDraggedWindow(const gfx::Point& location_in_screen) override; @@ -50,6 +52,13 @@ // browser window beneath it during dragging. std::unique_ptr<views::Widget> scrim_; + // It's used to hide all visible windows if the source window needs to be + // scaled up/down during dragging a tab out of the source window. It also + // hides the home launcher if home launcher is enabled, blurs and darkens the + // background upon its creation. All of these will be restored upon its + // destruction. + std::unique_ptr<WindowsHider> windows_hider_; + DISALLOW_COPY_AND_ASSIGN(TabletModeBrowserWindowDragDelegate); };
diff --git a/base/fuchsia/async_dispatcher.cc b/base/fuchsia/async_dispatcher.cc index 5df94b8..ac01930e 100644 --- a/base/fuchsia/async_dispatcher.cc +++ b/base/fuchsia/async_dispatcher.cc
@@ -24,6 +24,27 @@ } // namespace +class AsyncDispatcher::ExceptionState : public LinkNode<ExceptionState> { + public: + explicit ExceptionState(AsyncDispatcher* async_dispatcher) { + async_dispatcher->exception_list_.Append(this); + } + ~ExceptionState() { RemoveFromList(); } + + async_exception_t* exception() { + // ExceptionState objects are allocated in-place in the |state| field of an + // enclosing async_exceptionwait_t, so async_exception_t address can be + // calculated by subtracting state offset in async_exception_t from |this|. + static_assert(std::is_standard_layout<async_exception_t>(), + "async_wait_t is expected to have standard layout."); + return reinterpret_cast<async_exception_t*>( + reinterpret_cast<uint8_t*>(this) - offsetof(async_exception_t, state)); + } + + private: + DISALLOW_COPY_AND_ASSIGN(ExceptionState); +}; + class AsyncDispatcher::WaitState : public LinkNode<WaitState> { public: explicit WaitState(AsyncDispatcher* async_dispatcher) { @@ -82,6 +103,7 @@ ZX_EVENT_SIGNALED, ZX_WAIT_ASYNC_REPEATING); ZX_DCHECK(status == ZX_OK, status); + ops_storage_.version = ASYNC_OPS_V2; ops_storage_.v1.now = NowOp; ops_storage_.v1.begin_wait = BeginWaitOp; ops_storage_.v1.cancel_wait = CancelWaitOp; @@ -89,6 +111,8 @@ ops_storage_.v1.cancel_task = CancelTaskOp; ops_storage_.v1.queue_packet = QueuePacketOp; ops_storage_.v1.set_guest_bell_trap = SetGuestBellTrapOp; + ops_storage_.v2.bind_exception_port = BindExceptionPortOp; + ops_storage_.v2.unbind_exception_port = UnbindExceptionPortOp; ops = &ops_storage_; DCHECK(!async_get_default_dispatcher()); @@ -102,6 +126,13 @@ // Some waits and tasks may be canceled while the dispatcher is being // destroyed, so pop-from-head until none remain. + while (!exception_list_.empty()) { + ExceptionState* state = exception_list_.head()->value(); + async_exception_t* exception = state->exception(); + state->~ExceptionState(); + exception->handler(this, exception, ZX_ERR_CANCELED, nullptr); + } + while (!wait_list_.empty()) { WaitState* state = wait_list_.head()->value(); async_wait_t* wait = state->wait(); @@ -127,8 +158,7 @@ if (status != ZX_OK) return status; - if (packet.type == ZX_PKT_TYPE_SIGNAL_ONE || - packet.type == ZX_PKT_TYPE_SIGNAL_REP) { + if (ZX_PKT_IS_SIGNAL_ONE(packet.type) || ZX_PKT_IS_SIGNAL_REP(packet.type)) { if (packet.key == key_from_ptr(&timer_)) { // |timer_| has expired. DCHECK(packet.signal.observed & ZX_TIMER_SIGNALED); @@ -142,16 +172,23 @@ return ZX_ERR_CANCELED; } else { DCHECK_EQ(packet.type, ZX_PKT_TYPE_SIGNAL_ONE); - async_wait_t* wait = reinterpret_cast<async_wait_t*>(packet.key); + auto* wait = reinterpret_cast<async_wait_t*>(packet.key); - // Clean the state before invoking the handler: it may destroy the wait. - WaitState* state = reinterpret_cast<WaitState*>(&wait->state); + // Clean the state before invoking the handler: it may destroy |*wait|. + auto* state = reinterpret_cast<WaitState*>(&wait->state); state->~WaitState(); wait->handler(this, wait, packet.status, &packet.signal); return ZX_OK; } + } else if (ZX_PKT_IS_EXCEPTION(packet.type)) { + auto* exception = reinterpret_cast<async_exception_t*>(packet.key); + + // |exception| may have been deleted by the time |handler| returns. + exception->handler(this, exception, packet.status, &packet); + + return ZX_OK; } NOTREACHED(); @@ -204,6 +241,17 @@ return ZX_ERR_NOT_SUPPORTED; } +zx_status_t AsyncDispatcher::BindExceptionPortOp(async_dispatcher_t* async, + async_exception_t* exception) { + return static_cast<AsyncDispatcher*>(async)->BindExceptionPort(exception); +} + +zx_status_t AsyncDispatcher::UnbindExceptionPortOp( + async_dispatcher_t* async, + async_exception_t* exception) { + return static_cast<AsyncDispatcher*>(async)->UnbindExceptionPort(exception); +} + zx_status_t AsyncDispatcher::BeginWait(async_wait_t* wait) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); @@ -224,10 +272,13 @@ zx_status_t AsyncDispatcher::CancelWait(async_wait_t* wait) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + if (!wait->state.reserved[0]) + return ZX_ERR_NOT_FOUND; + zx_status_t status = port_.cancel(*zx::unowned_handle(wait->object), reinterpret_cast<uintptr_t>(wait)); if (status == ZX_OK) { - WaitState* state = reinterpret_cast<WaitState*>(&(wait->state)); + auto* state = reinterpret_cast<WaitState*>(&(wait->state)); state->~WaitState(); } @@ -272,12 +323,46 @@ if (!task->state.reserved[0]) return ZX_ERR_NOT_FOUND; - TaskState* state = reinterpret_cast<TaskState*>(&task->state); + auto* state = reinterpret_cast<TaskState*>(&task->state); state->~TaskState(); return ZX_OK; } +zx_status_t AsyncDispatcher::BindExceptionPort(async_exception_t* exception) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + + static_assert( + sizeof(AsyncDispatcher::ExceptionState) <= sizeof(async_state_t), + "ExceptionState is too big"); + ExceptionState* state = new (&exception->state) ExceptionState(this); + + zx_status_t status = zx_task_bind_exception_port( + exception->task, port_.get(), reinterpret_cast<uintptr_t>(exception), + exception->options); + if (status != ZX_OK) + state->~ExceptionState(); + + return status; +} + +zx_status_t AsyncDispatcher::UnbindExceptionPort(async_exception_t* exception) { + DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + + if (!exception->state.reserved[0]) + return ZX_ERR_NOT_FOUND; + + zx_status_t status = zx_task_bind_exception_port( + exception->task, ZX_HANDLE_INVALID, + reinterpret_cast<uintptr_t>(exception), exception->options); + if (status == ZX_OK) { + auto* state = reinterpret_cast<ExceptionState*>(&exception->state); + state->~ExceptionState(); + } + + return status; +} + void AsyncDispatcher::DispatchTasks() { // Snapshot now value to set implicit bound for the tasks that will run before // DispatchTasks() returns. This also helps to avoid calling zx_clock_get()
diff --git a/base/fuchsia/async_dispatcher.h b/base/fuchsia/async_dispatcher.h index 0d6d59641..9f1d610 100644 --- a/base/fuchsia/async_dispatcher.h +++ b/base/fuchsia/async_dispatcher.h
@@ -6,6 +6,7 @@ #define BASE_FUCHSIA_ASYNC_DISPATCHER_H_ #include <lib/async/dispatcher.h> +#include <lib/async/exception.h> #include <lib/zx/event.h> #include <lib/zx/port.h> #include <lib/zx/timer.h> @@ -35,9 +36,11 @@ void Stop(); private: + class ExceptionState; class WaitState; class TaskState; + // ASYNC_OPS_V1 operations. static zx_time_t NowOp(async_dispatcher_t* async); static zx_status_t BeginWaitOp(async_dispatcher_t* async, async_wait_t* wait); static zx_status_t CancelWaitOp(async_dispatcher_t* async, @@ -54,11 +57,19 @@ zx_vaddr_t addr, size_t length); + // ASYNC_OPS_V2 operations. + static zx_status_t BindExceptionPortOp(async_dispatcher_t* dispatcher, + async_exception_t* exception); + static zx_status_t UnbindExceptionPortOp(async_dispatcher_t* dispatcher, + async_exception_t* exception); + // async_ops_t implementation. Called by corresponding *Op() methods above. zx_status_t BeginWait(async_wait_t* wait); zx_status_t CancelWait(async_wait_t* wait); zx_status_t PostTask(async_task_t* task); zx_status_t CancelTask(async_task_t* task); + zx_status_t BindExceptionPort(async_exception_t* exception); + zx_status_t UnbindExceptionPort(async_exception_t* exception); // Runs tasks in |task_list_| that have deadline in the past. void DispatchTasks(); @@ -73,6 +84,7 @@ zx::event stop_event_; LinkedList<WaitState> wait_list_; + LinkedList<ExceptionState> exception_list_; async_ops_t ops_storage_;
diff --git a/base/fuchsia/async_dispatcher_unittest.cc b/base/fuchsia/async_dispatcher_unittest.cc index 74a5ae13..1b368a7 100644 --- a/base/fuchsia/async_dispatcher_unittest.cc +++ b/base/fuchsia/async_dispatcher_unittest.cc
@@ -7,12 +7,16 @@ #include <lib/async/default.h> #include <lib/async/task.h> #include <lib/async/wait.h> +#include <lib/zx/job.h> #include <lib/zx/socket.h> #include "base/callback.h" +#include "base/process/launch.h" +#include "base/test/multiprocess_test.h" #include "base/test/test_timeouts.h" #include "base/time/time.h" #include "testing/gtest/include/gtest/gtest.h" +#include "testing/multiprocess_func_list.h" namespace base { @@ -47,7 +51,7 @@ test_task->num_calls++; test_task->last_status = status; - if (!test_task->on_call.is_null()) + if (test_task->on_call) std::move(test_task->on_call).Run(); if (test_task->num_calls < test_task->repeats) @@ -86,13 +90,46 @@ test_wait->num_calls++; test_wait->last_status = status; - if (!test_wait->on_call.is_null()) + if (test_wait->on_call) + std::move(test_wait->on_call).Run(); +} + +struct TestException : public async_exception_t { + TestException(zx_handle_t handle) { + state = ASYNC_STATE_INIT; + handler = &HandleProc; + task = handle; + options = 0; + } + + static void HandleProc(async_dispatcher_t* async, + async_exception_t* wait, + zx_status_t status, + const zx_port_packet_t* packet); + int num_calls = 0; + OnceClosure on_call; + zx_status_t last_status = ZX_OK; +}; + +// static +void TestException::HandleProc(async_dispatcher_t* async, + async_exception_t* wait, + zx_status_t status, + const zx_port_packet_t* packet) { + EXPECT_EQ(async, async_get_default_dispatcher()); + + auto* test_wait = static_cast<TestException*>(wait); + + test_wait->num_calls++; + test_wait->last_status = status; + + if (test_wait->on_call) std::move(test_wait->on_call).Run(); } } // namespace -class AsyncDispatcherTest : public testing::Test { +class AsyncDispatcherTest : public MultiProcessTest { public: AsyncDispatcherTest() { dispatcher_ = std::make_unique<AsyncDispatcher>(); @@ -217,4 +254,53 @@ EXPECT_EQ(wait.last_status, ZX_ERR_CANCELED); } +// Sub-process which crashes itself, to generate an exception-port event. +MULTIPROCESS_TEST_MAIN(AsyncDispatcherCrashingChild) { + IMMEDIATE_CRASH(); + return 0; +} + +TEST_F(AsyncDispatcherTest, BindExceptionPort) { + zx::job child_job; + ASSERT_EQ(zx::job::create(*zx::job::default_job(), 0, &child_job), ZX_OK); + + // Bind |child_job|'s exception port to the dispatcher. + TestException exception(child_job.get()); + EXPECT_EQ(async_bind_exception_port(async_, &exception), ZX_OK); + + // Launch a child process in the job, that will immediately crash. + LaunchOptions options; + options.job_handle = child_job.get(); + Process child = + SpawnChildWithOptions("AsyncDispatcherCrashingChild", options); + ASSERT_TRUE(child.IsValid()); + + // Wait for the exception event to be handled. + EXPECT_EQ( + dispatcher_->DispatchOrWaitUntil( + (TimeTicks::Now() + TestTimeouts::action_max_timeout()).ToZxTime()), + ZX_OK); + EXPECT_EQ(exception.num_calls, 1); + EXPECT_EQ(exception.last_status, ZX_OK); + + EXPECT_EQ(async_unbind_exception_port(async_, &exception), ZX_OK); + ASSERT_EQ(child_job.kill(), ZX_OK); +} + +TEST_F(AsyncDispatcherTest, CancelExceptionPort) { + zx::job child_job; + ASSERT_EQ(zx::job::create(*zx::job::default_job(), 0, &child_job), ZX_OK); + + // Bind |child_job|'s exception port to the dispatcher. + TestException exception(child_job.get()); + EXPECT_EQ(async_bind_exception_port(async_, &exception), ZX_OK); + + // Tear-down the dispatcher, and verify that the |exception| is cancelled. + dispatcher_ = nullptr; + EXPECT_EQ(exception.num_calls, 1); + EXPECT_EQ(exception.last_status, ZX_ERR_CANCELED); + + ASSERT_EQ(child_job.kill(), ZX_OK); +} + } // namespace base
diff --git a/base/memory/weak_ptr.h b/base/memory/weak_ptr.h index 71309f2..6b94b0e 100644 --- a/base/memory/weak_ptr.h +++ b/base/memory/weak_ptr.h
@@ -270,7 +270,7 @@ // Returns whether the object |this| points to has been invalidated. This can // be used to distinguish a WeakPtr to a destroyed object from one that has - // been explicitly set to null. A null WeakPtr is always valid. + // been explicitly set to null. bool WasInvalidated() const { return ptr_ && !ref_.IsValid(); } private:
diff --git a/base/memory/weak_ptr_unittest.cc b/base/memory/weak_ptr_unittest.cc index 123a66bb..a4629df 100644 --- a/base/memory/weak_ptr_unittest.cc +++ b/base/memory/weak_ptr_unittest.cc
@@ -393,27 +393,31 @@ } // Tests that WasInvalidated() is true only for invalidated WeakPtrs (not -// nullptr) and doesn't DCHECK. +// nullptr) and doesn't DCHECK (e.g. because of a dereference attempt). TEST(WeakPtrTest, WasInvalidatedByFactoryDestruction) { WeakPtr<int> ptr; EXPECT_FALSE(ptr.WasInvalidated()); - // Test |data| destroyed. + // Test |data| destroyed. That is, the typical pattern when |data| (and its + // associated factory) go out of scope. { - int data; + int data = 0; WeakPtrFactory<int> factory(&data); ptr = factory.GetWeakPtr(); + // Verify that a live WeakPtr is not reported as Invalidated. EXPECT_FALSE(ptr.WasInvalidated()); } - EXPECT_TRUE(ptr.WasInvalidated()); // Shouldn't tickle asan. + + // Checking validity shouldn't read beyond the stack frame. + EXPECT_TRUE(ptr.WasInvalidated()); ptr = nullptr; EXPECT_FALSE(ptr.WasInvalidated()); } // As above, but testing InvalidateWeakPtrs(). TEST(WeakPtrTest, WasInvalidatedByInvalidateWeakPtrs) { - int data; + int data = 0; WeakPtrFactory<int> factory(&data); WeakPtr<int> ptr = factory.GetWeakPtr(); EXPECT_FALSE(ptr.WasInvalidated()); @@ -423,9 +427,10 @@ EXPECT_FALSE(ptr.WasInvalidated()); } -// Test WasInvalidated() when assigning null before invalidating. +// A WeakPtr should not be reported as 'invalidated' if nullptr was assigned to +// it. TEST(WeakPtrTest, WasInvalidatedWhilstNull) { - int data; + int data = 0; WeakPtrFactory<int> factory(&data); WeakPtr<int> ptr = factory.GetWeakPtr(); EXPECT_FALSE(ptr.WasInvalidated());
diff --git a/base/observer_list.h b/base/observer_list.h index 447f045a..541bd2d5 100644 --- a/base/observer_list.h +++ b/base/observer_list.h
@@ -104,8 +104,8 @@ public: // Allow declaring an ObserverList<...>::Unchecked that replaces the default // ObserverStorageType to use raw pointers. This is required to support legacy - // observers that do not inherit from CheckedObserver. The majority of NEW - // CODE SHOULD NOT USE THIS, but it may be suited for performance-critical + // observers that do not inherit from CheckedObserver. The majority of new + // code should not use this, but it may be suited for performance-critical // situations to avoid overheads of a CHECK(). Note the type can't be chosen // based on ObserverType's definition because ObserverLists are often declared // in headers using a forward-declare of ObserverType. @@ -285,8 +285,8 @@ // Determine whether a particular observer is in the list. bool HasObserver(const ObserverType* obs) const { // Client code passing null could be confused by the treatment of observers - // removed mid-iteration. TODO(tapted): This should probably DCHECK, but - // some client code currently does pass null to HasObserver(). + // removed mid-iteration. TODO(https://crbug.com/876588): This should + // probably DCHECK, but some client code currently does pass null. if (obs == nullptr) return false; return std::find_if(observers_.begin(), observers_.end(),
diff --git a/base/observer_list_internal.h b/base/observer_list_internal.h index 14d5e22..4d72a2b 100644 --- a/base/observer_list_internal.h +++ b/base/observer_list_internal.h
@@ -39,8 +39,6 @@ private: void* ptr_; - // Although copying works, disallow it to be consistent with - // CheckedObserverAdapter. DISALLOW_COPY_AND_ASSIGN(UncheckedObserverAdapter); }; @@ -61,7 +59,7 @@ void MarkForRemoval() { DCHECK(weak_ptr_); - weak_ptr_.reset(); + weak_ptr_ = nullptr; } bool IsMarkedForRemoval() const {
diff --git a/base/win/pe_image.cc b/base/win/pe_image.cc index ec1c4734f..5056915 100644 --- a/base/win/pe_image.cc +++ b/base/win/pe_image.cc
@@ -545,7 +545,8 @@ return true; } -bool PEImage::ImageRVAToOnDiskOffset(DWORD rva, DWORD* on_disk_offset) const { +bool PEImage::ImageRVAToOnDiskOffset(uintptr_t rva, + DWORD* on_disk_offset) const { LPVOID address = RVAToAddr(rva); return ImageAddrToOnDiskOffset(address, on_disk_offset); } @@ -570,7 +571,7 @@ return true; } -PVOID PEImage::RVAToAddr(DWORD rva) const { +PVOID PEImage::RVAToAddr(uintptr_t rva) const { if (rva == 0) return NULL; @@ -594,7 +595,7 @@ return &nt_headers->OptionalHeader.DataDirectory[directory]; } -PVOID PEImageAsData::RVAToAddr(DWORD rva) const { +PVOID PEImageAsData::RVAToAddr(uintptr_t rva) const { if (rva == 0) return NULL;
diff --git a/base/win/pe_image.h b/base/win/pe_image.h index cb13c0d..311fde5 100644 --- a/base/win/pe_image.h +++ b/base/win/pe_image.h
@@ -11,6 +11,8 @@ #ifndef BASE_WIN_PE_IMAGE_H_ #define BASE_WIN_PE_IMAGE_H_ +#include <stdint.h> + #include <windows.h> #if defined(_WIN32_WINNT_WIN8) @@ -231,11 +233,11 @@ bool VerifyMagic() const; // Converts an rva value to the appropriate address. - virtual PVOID RVAToAddr(DWORD rva) const; + virtual PVOID RVAToAddr(uintptr_t rva) const; // Converts an rva value to an offset on disk. // Returns true on success. - bool ImageRVAToOnDiskOffset(DWORD rva, DWORD *on_disk_offset) const; + bool ImageRVAToOnDiskOffset(uintptr_t rva, DWORD* on_disk_offset) const; // Converts an address to an offset on disk. // Returns true on success. @@ -255,7 +257,7 @@ public: explicit PEImageAsData(HMODULE hModule) : PEImage(hModule) {} - PVOID RVAToAddr(DWORD rva) const override; + PVOID RVAToAddr(uintptr_t rva) const override; }; inline bool PEImage::IsOrdinal(LPCSTR name) {
diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn index 43bd05c5..d6033f0 100644 --- a/build/config/compiler/BUILD.gn +++ b/build/config/compiler/BUILD.gn
@@ -626,20 +626,13 @@ cflags += [ "-flto=thin" ] - # Limit the size of the ThinLTO cache to the lesser of 10% of available disk - # space, 10GB and 100000 files. - if (use_lld) { - cache_policy = - "cache_size=10%:cache_size_bytes=10g:cache_size_files=100000" - } if (is_win) { - # This is a straight translation of the non-Windows flags below. + # This is a straight translation of the non-Windows flags below, + # except we do not use the ThinLTO cache, which leaks temporary + # files on Windows (https://crbug.com/871962). ldflags += [ "/opt:lldlto=0", "/opt:lldltojobs=8", - "/lldltocache:" + - rebase_path("$root_out_dir/thinlto-cache", root_build_dir), - "/lldltocachepolicy:$cache_policy", ] } else { ldflags += [ "-flto=thin" ] @@ -648,6 +641,10 @@ # linker jobs. This is still suboptimal to a potential dynamic # resource allocation scheme, but should be good enough. if (use_lld) { + # Limit the size of the ThinLTO cache to the lesser of 10% of available disk + # space, 10GB and 100000 files. + cache_policy = + "cache_size=10%:cache_size_bytes=10g:cache_size_files=100000" ldflags += [ "-Wl,--thinlto-jobs=8", "-Wl,--thinlto-cache-dir=" +
diff --git a/chrome/android/java/res/OWNERS b/chrome/android/java/res/OWNERS index 48593ff..5d7443b 100644 --- a/chrome/android/java/res/OWNERS +++ b/chrome/android/java/res/OWNERS
@@ -3,7 +3,7 @@ # we don't want them. set noparent -file://content/public/android/java/res/OWNERS +file://ui/android/java/res/OWNERS # New Tab Page changes only: mvanouwerkerk@chromium.org
diff --git a/chrome/android/java/res/layout/data_reduction_stats_layout.xml b/chrome/android/java/res/layout/data_reduction_stats_layout.xml index a42efe8..0ef83a2 100644 --- a/chrome/android/java/res/layout/data_reduction_stats_layout.xml +++ b/chrome/android/java/res/layout/data_reduction_stats_layout.xml
@@ -3,108 +3,105 @@ Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. --> -<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" - android:id="@+id/data_reduction_stats_container" +<org.chromium.ui.widget.OptimizedFrameLayout + xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" - android:layout_height="wrap_content" - android:clipChildren="false" - android:clipToPadding="false" - android:orientation="vertical" > + android:layout_height="match_parent"> <TextView android:id="@+id/initial_data_savings" - android:layout_width="match_parent" + android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_marginTop="8dp" - android:gravity="center_horizontal" + android:layout_gravity="center" android:drawablePadding="3dp" android:text="@string/data_reduction_initial_title" android:textAppearance="@style/BlackDisabledText1" /> <LinearLayout - android:id="@+id/data_savings_summary_container" + android:id="@+id/data_reduction_stats_container" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_marginTop="8dp" - android:gravity="center_horizontal" android:baselineAligned="false" - android:orientation="vertical" > + android:orientation="vertical"> - <LinearLayout + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginTop="8dp" + android:gravity="center_horizontal" + android:orientation="horizontal" > + + <TextView + android:id="@+id/data_reduction_savings" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:orientation="horizontal" > + android:layout_marginTop="3dp" + android:singleLine="true" + android:textAppearance="@style/TextAppearance.DataReductionHeadline" /> - <TextView - android:id="@+id/data_reduction_savings" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:layout_marginTop="3dp" - android:singleLine="true" - android:textAppearance="@style/TextAppearance.DataReductionHeadline" /> - - <TextView - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_marginTop="3dp" - android:paddingStart="3dp" - android:text="@string/data_reduction_savings_label" - android:textAppearance="@style/BlueLink2" /> - - </LinearLayout> - - <LinearLayout + <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" - android:layout_marginTop="4dp" - android:orientation="horizontal" > + android:layout_marginTop="3dp" + android:paddingStart="3dp" + android:text="@string/data_reduction_savings_label" + android:textAppearance="@style/BlueLink2" /> - <TextView - android:id="@+id/data_reduction_usage" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:singleLine="true" - android:textAppearance="@style/BlackBody" /> + </LinearLayout> - <TextView - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:paddingStart="3dp" - android:text="@string/data_reduction_usage_label" - android:textAppearance="@style/BlackBody" /> - </LinearLayout> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:gravity="center_horizontal" + android:layout_marginTop="4dp" + android:orientation="horizontal" > + + <TextView + android:id="@+id/data_reduction_usage" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:singleLine="true" + android:textAppearance="@style/BlackBody" /> + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:paddingStart="3dp" + android:text="@string/data_reduction_usage_label" + android:textAppearance="@style/BlackBody" /> + </LinearLayout> + + <include layout="@layout/data_usage_chart" /> + + <FrameLayout + android:id="@+id/chart_dates" + android:layout_width="match_parent" + android:layout_height="wrap_content" > + + <TextView + android:id="@+id/data_reduction_start_date" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:textAppearance="@style/BlackBody" /> + + <TextView + android:id="@+id/data_reduction_end_date" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:textAppearance="@style/BlackBody" /> + + </FrameLayout> + + <include layout="@layout/data_usage_breakdown" /> + + <Button + android:id="@+id/data_reduction_reset_statistics" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_gravity="center" + android:layout_marginTop="24dp" + android:text="@string/data_reduction_usage_reset_statistics_button" /> </LinearLayout> - <include layout="@layout/data_usage_chart" /> - - <FrameLayout - android:id="@+id/chart_dates" - android:layout_width="match_parent" - android:layout_height="wrap_content" > - - <TextView - android:id="@+id/data_reduction_start_date" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:textAppearance="@style/BlackBody" /> - - <TextView - android:id="@+id/data_reduction_end_date" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:textAppearance="@style/BlackBody" /> - - </FrameLayout> - - <include layout="@layout/data_usage_breakdown" /> - - <Button - android:id="@+id/data_reduction_reset_statistics" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_gravity="center" - android:layout_marginTop="24dp" - android:text="@string/data_reduction_usage_reset_statistics_button" /> - -</LinearLayout> +</org.chromium.ui.widget.OptimizedFrameLayout>
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/init/ChromeBrowserInitializer.java b/chrome/android/java/src/org/chromium/chrome/browser/init/ChromeBrowserInitializer.java index 412eff8..cc58edc 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/init/ChromeBrowserInitializer.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/init/ChromeBrowserInitializer.java
@@ -272,12 +272,16 @@ + "ChromeBrowserInitializer.postInflationStartup has been run."); } final ChainedTasks tasks = new ChainedTasks(); - tasks.add(new Runnable() { - @Override - public void run() { - ProcessInitializationHandler.getInstance().initializePostNative(); - } - }); + // If full browser process is not going to be launched, it is up to individual service to + // launch its required components. + if (!delegate.startServiceManagerOnly()) { + tasks.add(new Runnable() { + @Override + public void run() { + ProcessInitializationHandler.getInstance().initializePostNative(); + } + }); + } tasks.add(new Runnable() { @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/datareduction/DataReductionStatsPreference.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/datareduction/DataReductionStatsPreference.java index b72f787..f17cbba0 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/datareduction/DataReductionStatsPreference.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/datareduction/DataReductionStatsPreference.java
@@ -38,6 +38,8 @@ import org.chromium.third_party.android.datausagechart.ChartDataUsageView; import org.chromium.third_party.android.datausagechart.NetworkStats; import org.chromium.third_party.android.datausagechart.NetworkStatsHistory; +import org.chromium.ui.widget.RectProvider; +import org.chromium.ui.widget.ViewRectProvider; import java.util.List; import java.util.TimeZone; @@ -64,9 +66,9 @@ private NetworkStatsHistory mReceivedNetworkStatsHistory; private List<DataReductionDataUseItem> mSiteBreakdownItems; + private ViewRectProvider mDataReductionStatsPreferenceViewRectProvider; + private LinearLayout mDataReductionStatsContainer; private TextView mInitialDataSavingsTextView; - private LinearLayout mDataSavingsSummaryContainer; - private FrameLayout mDataSavingsChartDatesContainer; private TextView mDataSavingsTextView; private TextView mDataUsageTextView; private TextView mStartDateTextView; @@ -235,13 +237,8 @@ if (mShouldShowRealData) updateDetailData(); mInitialDataSavingsTextView.setVisibility(mShouldShowRealData ? View.GONE : View.VISIBLE); + mDataReductionStatsContainer.setVisibility(mShouldShowRealData ? View.VISIBLE : View.GONE); - mDataSavingsSummaryContainer.setVisibility(mShouldShowRealData ? View.VISIBLE : View.GONE); - mChartDataUsageView.setVisibility(mShouldShowRealData ? View.VISIBLE : View.GONE); - mResetStatisticsButton.setVisibility(mShouldShowRealData ? View.VISIBLE : View.GONE); - - mDataSavingsChartDatesContainer.setVisibility( - mShouldShowRealData ? View.VISIBLE : View.GONE); mStartDateTextView.setText(mShouldShowRealData ? mStartDatePhrase : ""); mStartDateTextView.setContentDescription(mShouldShowRealData ? context.getString(R.string.data_reduction_start_date_content_description, @@ -268,22 +265,49 @@ } /** + * Initializes a view rect observer to listen for when the bounds of the view has changed, so we + * can update the minimum height of the view accordingly. + * + * @param view The view to listen for bounds changes on. + */ + private void initializeViewBounds(final View view) { + if (mDataReductionStatsPreferenceViewRectProvider != null) { + mDataReductionStatsPreferenceViewRectProvider.stopObserving(); + } + mDataReductionStatsPreferenceViewRectProvider = new ViewRectProvider(view); + mDataReductionStatsPreferenceViewRectProvider.startObserving(new RectProvider.Observer() { + @Override + public void onRectChanged() { + int screenHeight = getContext().getResources().getDisplayMetrics().heightPixels; + int offset = mDataReductionStatsPreferenceViewRectProvider.getRect().top; + view.setMinimumHeight(screenHeight - offset); + } + + @Override + public void onRectHidden() {} + }); + } + + /** * Sets up a data usage chart and text views containing data reduction statistics. * @param view The current view. */ @Override protected void onBindView(View view) { super.onBindView(view); + + initializeViewBounds(view); + mInitialDataSavingsTextView = (TextView) view.findViewById(R.id.initial_data_savings); mInitialDataSavingsTextView.setCompoundDrawablesWithIntrinsicBounds(null, VectorDrawableCompat.create(getContext().getResources(), R.drawable.data_reduction_big, getContext().getTheme()), null, null); - mDataSavingsSummaryContainer = - (LinearLayout) view.findViewById(R.id.data_savings_summary_container); + + mDataReductionStatsContainer = + (LinearLayout) view.findViewById(R.id.data_reduction_stats_container); mDataUsageTextView = (TextView) view.findViewById(R.id.data_reduction_usage); mDataSavingsTextView = (TextView) view.findViewById(R.id.data_reduction_savings); - mDataSavingsChartDatesContainer = (FrameLayout) view.findViewById(R.id.chart_dates); mStartDateTextView = (TextView) view.findViewById(R.id.data_reduction_start_date); mEndDateTextView = (TextView) view.findViewById(R.id.data_reduction_end_date); mDataReductionBreakdownView =
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/survey/ChromeSurveyController.java b/chrome/android/java/src/org/chromium/chrome/browser/survey/ChromeSurveyController.java index 6edb6d4..f2f1c6d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/survey/ChromeSurveyController.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/survey/ChromeSurveyController.java
@@ -18,6 +18,7 @@ import org.chromium.base.metrics.RecordHistogram; import org.chromium.base.metrics.RecordUserAction; import org.chromium.chrome.R; +import org.chromium.chrome.browser.ChromeFeatureList; import org.chromium.chrome.browser.ChromeSwitches; import org.chromium.chrome.browser.infobar.InfoBarContainer; import org.chromium.chrome.browser.infobar.InfoBarContainerLayout.Item; @@ -31,7 +32,6 @@ import org.chromium.chrome.browser.tabmodel.EmptyTabModelSelectorObserver; import org.chromium.chrome.browser.tabmodel.TabModelSelector; import org.chromium.chrome.browser.tabmodel.TabModelSelectorObserver; -import org.chromium.chrome.browser.util.FeatureUtilities; import org.chromium.components.variations.VariationsAssociatedData; import java.lang.annotation.Retention; @@ -142,8 +142,10 @@ } }; - String siteContext = String.format( - "Is Modern Design Enabled? %s", FeatureUtilities.isChromeModernDesignEnabled()); + String siteContext = + ChromeFeatureList.isEnabled(ChromeFeatureList.HORIZONTAL_TAB_SWITCHER_ANDROID) + ? "HorizontalTabSwitcher" + : "NotHorizontalTabSwitcher"; surveyController.downloadSurvey(context, siteId, onSuccessRunnable, siteContext); } @@ -321,6 +323,20 @@ } int maxNumber = getMaxNumber(); + + int maxForHorizontalTabSwitcher = -1; + if (ChromeFeatureList.isEnabled(ChromeFeatureList.HORIZONTAL_TAB_SWITCHER_ANDROID)) { + maxForHorizontalTabSwitcher = ChromeFeatureList.getFieldTrialParamByFeatureAsInt( + ChromeFeatureList.HORIZONTAL_TAB_SWITCHER_ANDROID, MAX_NUMBER, -1); + } + if (maxForHorizontalTabSwitcher != -1) { + if (maxNumber == -1) { + maxNumber = maxForHorizontalTabSwitcher; + } else { + maxNumber = Math.min(maxNumber, maxForHorizontalTabSwitcher); + } + } + if (maxNumber == -1) { recordSurveyFilteringResult(FilteringResult.MAX_NUMBER_MISSING); return false;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/BottomToolbarViewBinder.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/BottomToolbarViewBinder.java index fa962b12..00ecf1b 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/BottomToolbarViewBinder.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/BottomToolbarViewBinder.java
@@ -115,10 +115,9 @@ private static void updateButton( TintedImageButton button, ToolbarButtonData buttonData, boolean useLightIcons) { if (buttonData == null) { - button.setVisibility(View.INVISIBLE); + ToolbarButtonData.clearButton(button); } else { buttonData.updateButton(button, useLightIcons); - button.setVisibility(View.VISIBLE); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/OWNERS b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/OWNERS index 4a7fb31..a88874e8 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/OWNERS +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/OWNERS
@@ -1,4 +1,6 @@ +mdjones@chromium.org tedchoc@chromium.org yusufo@chromium.org -per-file BottomToolbar*=mdjones@chromium.org +# COMPONENT: UI>Browser>Mobile +# OS: Android
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarButtonSlotData.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarButtonSlotData.java index c01f058..07566e2 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarButtonSlotData.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarButtonSlotData.java
@@ -4,15 +4,21 @@ package org.chromium.chrome.browser.toolbar; +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.AnimatorSet; +import android.animation.ObjectAnimator; import android.content.Context; import android.content.res.ColorStateList; import android.graphics.drawable.Drawable; import android.support.v4.graphics.drawable.DrawableCompat; import android.support.v7.content.res.AppCompatResources; +import android.view.View; import android.view.View.OnClickListener; import org.chromium.chrome.R; import org.chromium.chrome.browser.widget.TintedImageButton; +import org.chromium.ui.interpolators.BakedBezierInterpolator; /** * This class can hold two buttons, one to be shown in browsing mode and one for tab switching mode. @@ -24,6 +30,9 @@ /** The button to be shown when in tab switcher mode. */ public ToolbarButtonData tabSwitcherModeButtonData; + /** Fade in/out time in milliseconds. */ + private static final int FADE_DURATION = 300; + /** * @param browsingModeButton The button to be shown when in browsing mode. * @param tabSwitcherModeButton The button to be shown when in tab switcher mode. @@ -78,11 +87,42 @@ * @param isLight Whether or not to use light mode. */ void updateButtonDrawable(TintedImageButton imageButton, boolean isLight) { - DrawableCompat.setTintList(mDrawable, isLight ? mLightTint : mDarkTint); - imageButton.setImageDrawable(mDrawable); - imageButton.setContentDescription( - isLight ? mLightAccessibilityString : mDarkAccessibilityString); - imageButton.invalidate(); + ObjectAnimator fadeOutAnim = + ObjectAnimator.ofFloat(imageButton, View.ALPHA, 1.0f, 0.0f); + fadeOutAnim.setDuration(FADE_DURATION / 2); + fadeOutAnim.setInterpolator(BakedBezierInterpolator.FADE_OUT_CURVE); + + ObjectAnimator fadeInAnim = ObjectAnimator.ofFloat(imageButton, View.ALPHA, 0.0f, 1.0f); + fadeInAnim.setDuration(FADE_DURATION / 2); + fadeInAnim.setInterpolator(BakedBezierInterpolator.FADE_IN_CURVE); + fadeInAnim.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationStart(Animator animator) { + if (mDrawable != null) { + DrawableCompat.setTintList(mDrawable, isLight ? mLightTint : mDarkTint); + } + imageButton.setImageDrawable(mDrawable); + imageButton.setContentDescription( + isLight ? mLightAccessibilityString : mDarkAccessibilityString); + imageButton.invalidate(); + } + + @Override + public void onAnimationEnd(Animator animator) { + imageButton.setEnabled(true); + } + }); + + imageButton.setEnabled(false); + AnimatorSet animatorSet = new AnimatorSet(); + animatorSet.playSequentially(fadeOutAnim, fadeInAnim); + animatorSet.start(); + } + + static void clearButton(TintedImageButton button) { + ToolbarButtonData emptyButtonData = + new ToolbarButtonData(null, "", "", null, button.getContext()); + emptyButtonData.updateButton(button, false); } } }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/VrBrowserDialogTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/VrBrowserDialogTest.java index b9f7f5c..421c057 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/vr/VrBrowserDialogTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/vr/VrBrowserDialogTest.java
@@ -289,15 +289,37 @@ mVrBrowserTestFramework.assertNoJavaScriptErrors(); } + /** + * Tests that the keyboard appears when clicking on the URL bar. + * Also contains a regression test for https://crbug.com/874671 where inputting text into the + * URL bar would cause a browser crash. + */ @Test @LargeTest @HeadTrackingMode(HeadTrackingMode.SupportedMode.FROZEN) public void testKeyboardAppearsOnUrlBarClick() throws InterruptedException, TimeoutException { clickElement("test_navigation_2d_page", UserFriendlyElementName.URL); captureScreen("KeyboardAppearsOnUrlBarClick_Visible"); + // Regression test for https://crbug.com/874671 + // We need to use the VrCore-side emulated controller because the keyboard isn't a UI + // element, meaning we can't specify it as a click target for the Chrome-side controller. + // We also can't use the MockBrowserKeyboardInterface like we do for web input testing, as + // that does not seem to work with the omnibox. + NativeUiUtils.revertToRealController(); + // Point at the keyboard and click an arbitrary key + EmulatedVrController controller = new EmulatedVrController(mVrTestRule.getActivity()); + controller.recenterView(); + controller.moveControllerInstant(0.0f, -0.259f, -0.996f, -0.0f); + // Spam clicks to ensure we're getting one in. + for (int i = 0; i < 5; i++) { + controller.performControllerClick(); + } mVrBrowserTestFramework.assertNoJavaScriptErrors(); } + /** + * Tests that the overflow menu appears when the overflow menu button is clicked. + */ @Test @LargeTest @HeadTrackingMode(HeadTrackingMode.SupportedMode.FROZEN) @@ -307,6 +329,9 @@ mVrBrowserTestFramework.assertNoJavaScriptErrors(); } + /** + * Tests that the page info popup appears when the security token in the URL bar is clicked. + */ @Test @LargeTest @HeadTrackingMode(HeadTrackingMode.SupportedMode.FROZEN)
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/survey/ChromeSurveyControllerTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/survey/ChromeSurveyControllerTest.java index 6a801da..0db9fa0 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/survey/ChromeSurveyControllerTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/survey/ChromeSurveyControllerTest.java
@@ -11,6 +11,7 @@ import static org.mockito.Mockito.verify; import android.content.SharedPreferences; +import android.util.ArrayMap; import org.junit.After; import org.junit.Assert; @@ -24,16 +25,22 @@ import org.chromium.base.ContextUtils; import org.chromium.base.metrics.RecordHistogram; import org.chromium.base.test.BaseRobolectricTestRunner; +import org.chromium.chrome.browser.ChromeFeatureList; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tabmodel.TabModelSelector; import org.chromium.content_public.browser.WebContents; +import java.util.Map; + /** * Unit tests for ChromeSurveyController.java. */ @RunWith(BaseRobolectricTestRunner.class) @Config(manifest = Config.NONE) public class ChromeSurveyControllerTest { + private static final String STUDY_NAME = "HorizontalTabSwitcherStudyName"; + private static final String GROUP_NAME = "HorizontalTabSwitcherGroupName"; + private TestChromeSurveyController mTestController; private RiggedSurveyController mRiggedController; private SharedPreferences mSharedPreferences; @@ -57,6 +64,9 @@ mSharedPreferences = ContextUtils.getAppSharedPreferences(); mSharedPreferences.edit().clear().apply(); Assert.assertNull("Tab should be null", mTestController.getLastTabInfobarShown()); + Map<String, Boolean> featureMap = new ArrayMap<>(); + featureMap.put(ChromeFeatureList.HORIZONTAL_TAB_SWITCHER_ANDROID, true); + ChromeFeatureList.setTestFeatures(featureMap); } @After
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp index ae7b157..63f9555 100644 --- a/chrome/app/chromeos_strings.grdp +++ b/chrome/app/chromeos_strings.grdp
@@ -1772,6 +1772,15 @@ <message name="IDS_SPOKEN_FEEDBACK_OPTION_ON" desc="A value for Spoken Feedback accessibility option when it is on."> On </message> + <message name="IDS_OOBE_SELECT_TO_SPEAK_OPTION" desc="Select to Speak option shown on OOBE screens accessibility menu."> + Select to speak + </message> + <message name="IDS_SELECT_TO_SPEAK_OPTION_OFF" desc="A value for Select to Speak accessibility option when it is off."> + Off + </message> + <message name="IDS_SELECT_TO_SPEAK_OPTION_ON" desc="A value for Select to Speak accessibility option when it is on."> + On + </message> <message name="IDS_OOBE_LARGE_CURSOR_OPTION" desc="Large mouse cursor option shown on OOBE screens accessibility menu."> Large mouse cursor </message>
diff --git a/chrome/app/chromeos_strings_grdp/IDS_OOBE_SELECT_TO_SPEAK_OPTION.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_OOBE_SELECT_TO_SPEAK_OPTION.png.sha1 new file mode 100644 index 0000000..786c7b5 --- /dev/null +++ b/chrome/app/chromeos_strings_grdp/IDS_OOBE_SELECT_TO_SPEAK_OPTION.png.sha1
@@ -0,0 +1 @@ +436d213dcaafc071f6631e6d497dfa37c5ad5bbc \ No newline at end of file
diff --git a/chrome/app/chromeos_strings_grdp/IDS_SELECT_TO_SPEAK_OPTION_OFF.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_SELECT_TO_SPEAK_OPTION_OFF.png.sha1 new file mode 100644 index 0000000..786c7b5 --- /dev/null +++ b/chrome/app/chromeos_strings_grdp/IDS_SELECT_TO_SPEAK_OPTION_OFF.png.sha1
@@ -0,0 +1 @@ +436d213dcaafc071f6631e6d497dfa37c5ad5bbc \ No newline at end of file
diff --git a/chrome/app/chromeos_strings_grdp/IDS_SELECT_TO_SPEAK_OPTION_ON.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_SELECT_TO_SPEAK_OPTION_ON.png.sha1 new file mode 100644 index 0000000..0e0b6a4 --- /dev/null +++ b/chrome/app/chromeos_strings_grdp/IDS_SELECT_TO_SPEAK_OPTION_ON.png.sha1
@@ -0,0 +1 @@ +d04d627bb29da9efd1172f6792ba930f7e7c435a \ No newline at end of file
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index 0f6d70e..772d74df 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -3219,6 +3219,7 @@ } if (is_mac) { + allow_circular_includes_from += [ "//chrome/browser/apps/app_shim" ] deps += [ "//chrome/app_shim", "//chrome/browser/apps/app_shim", @@ -3831,11 +3832,18 @@ allow_circular_includes_from += [ "//chrome/browser/apps/platform_apps", "//chrome/browser/extensions", + "//chrome/browser/web_applications", + "//chrome/browser/web_applications/bookmark_apps", + "//chrome/browser/web_applications/components", + "//chrome/browser/web_applications/extensions", ] deps += [ "//apps", "//chrome/browser/sync_file_system/drive_backend:sync_file_system_drive_proto", "//chrome/browser/web_applications", + "//chrome/browser/web_applications/bookmark_apps", + "//chrome/browser/web_applications/components", + "//chrome/browser/web_applications/extensions", "//chrome/common/extensions/api", "//chrome/common/extensions/api:extensions_features", "//components/drive",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 91b566d..89bc5f6f 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -485,6 +485,14 @@ }; #endif // OS_CHROMEOS +const FeatureEntry::FeatureParam kIdnNavigationSuggestionsMetricsOnly[] = { + {"metrics_only", "true"}, +}; + +const FeatureEntry::FeatureVariation kIdnNavigationSuggestionVariants[] = { + {"With Metrics Only", kIdnNavigationSuggestionsMetricsOnly, + base::size(kIdnNavigationSuggestionsMetricsOnly)}}; + const FeatureEntry::Choice kExtensionContentVerificationChoices[] = { {flags_ui::kGenericExperimentChoiceDefault, "", ""}, {flag_descriptions::kExtensionContentVerificationBootstrap, @@ -4288,7 +4296,9 @@ {"enable-idn-navigation-suggestions", flag_descriptions::kIdnNavigationSuggestionsName, flag_descriptions::kIdnNavigationSuggestionsDescription, kOsDesktop, - FEATURE_VALUE_TYPE(features::kIdnNavigationSuggestions)}, + FEATURE_WITH_PARAMS_VALUE_TYPE(features::kIdnNavigationSuggestions, + kIdnNavigationSuggestionVariants, + "IdnNavigationSuggestions")}, #if defined(OS_ANDROID) {"long-press-back-for-history",
diff --git a/chrome/browser/android/vr/render_loop_factory.cc b/chrome/browser/android/vr/render_loop_factory.cc index 318720ac..5121c95 100644 --- a/chrome/browser/android/vr/render_loop_factory.cc +++ b/chrome/browser/android/vr/render_loop_factory.cc
@@ -10,10 +10,17 @@ #include "chrome/browser/android/vr/gvr_keyboard_delegate.h" #include "chrome/browser/android/vr/vr_gl_thread.h" #include "chrome/browser/android/vr/vr_shell_gl.h" +#include "chrome/browser/vr/render_loop.h" #include "chrome/browser/vr/sounds_manager_audio_delegate.h" #include "chrome/browser/vr/text_input_delegate.h" #include "chrome/browser/vr/ui_factory.h" +namespace { +// Number of frames to use for sliding averages for pose timings, +// as used for estimating prediction times. +constexpr unsigned kSlidingAverageSize = 5; +} // namespace + namespace vr { RenderLoopFactory::Params::Params( @@ -58,10 +65,16 @@ auto controller_delegate = std::make_unique<GvrControllerDelegate>(params->gvr_api, vr_gl_thread); auto vr_shell_gl = std::make_unique<VrShellGl>( - vr_gl_thread, std::move(ui), std::move(controller_delegate), + std::move(ui), std::move(controller_delegate), vr_gl_thread, params->gvr_api, params->reprojected_rendering, params->daydream_support, params->ui_initial_state.in_web_vr, params->pause_content, - params->low_density); + params->low_density, kSlidingAverageSize); + vr_shell_gl->SetDrawWebXrCallback(base::BindRepeating( + &RenderLoop::Draw, base::Unretained(vr_shell_gl.get()), + CompositorDelegate::kWebXrFrame)); + vr_shell_gl->SetDrawBrowserCallback(base::BindRepeating( + &RenderLoop::Draw, base::Unretained(vr_shell_gl.get()), + CompositorDelegate::kUiFrame)); vr_gl_thread->task_runner()->PostTask( FROM_HERE, base::BindOnce(&VrShellGl::Init, vr_shell_gl->GetWeakPtr(),
diff --git a/chrome/browser/android/vr/vr_shell_gl.cc b/chrome/browser/android/vr/vr_shell_gl.cc index b3391ed..210b7e8 100644 --- a/chrome/browser/android/vr/vr_shell_gl.cc +++ b/chrome/browser/android/vr/vr_shell_gl.cc
@@ -4,6 +4,7 @@ #include "chrome/browser/android/vr/vr_shell_gl.h" +#include <algorithm> #include <limits> #include <string> @@ -27,6 +28,7 @@ #include "chrome/browser/android/vr/vr_controller.h" #include "chrome/browser/android/vr/vr_shell.h" #include "chrome/browser/vr/assets_loader.h" +#include "chrome/browser/vr/compositor_ui_interface.h" #include "chrome/browser/vr/controller_delegate.h" #include "chrome/browser/vr/gl_texture_location.h" #include "chrome/browser/vr/metrics/session_metrics_helper.h" @@ -82,10 +84,6 @@ // Use 2 for now, we can probably make the buffer even smaller. constexpr float kWebVrBrowserUiSizeFactor = 2.f; -// Number of frames to use for sliding averages for pose timings, -// as used for estimating prediction times. -constexpr unsigned kWebVRSlidingAverageSize = 5; - // Timeout for checking for the WebVR rendering GL fence. If the timeout is // reached, yield to let other tasks execute before rechecking. constexpr base::TimeDelta kWebVRFenceCheckTimeout = @@ -112,6 +110,8 @@ // Taken from the GVR source code, this is the default vignette border fraction. constexpr float kContentVignetteBorder = 0.04; constexpr float kContentVignetteScale = 1.0 + (kContentVignetteBorder * 2.0); +// Add a 4 pixel border to avoid aliasing issues at the edge of the texture. +constexpr int kContentBorderPixels = 4; constexpr gvr::Rectf kContentUv = {0, 1.0, 0, 1.0}; // If we're not using the SurfaceTexture, use this matrix instead of @@ -172,31 +172,32 @@ return bounds; } -gvr::Rectf ToGvrRectf(const UiInterface::FovRectangle& rect) { +gvr::Rectf ToGvrRectf(const FovRectangle& rect) { return gvr::Rectf{rect.left, rect.right, rect.bottom, rect.top}; } -UiInterface::FovRectangle ToUiFovRect(const gvr::Rectf& rect) { - return UiInterface::FovRectangle{rect.left, rect.right, rect.bottom, - rect.top}; +FovRectangle ToUiFovRect(const gvr::Rectf& rect) { + return FovRectangle{rect.left, rect.right, rect.bottom, rect.top}; } } // namespace -VrShellGl::VrShellGl(GlBrowserInterface* browser, - std::unique_ptr<UiInterface> ui, +VrShellGl::VrShellGl(std::unique_ptr<UiInterface> ui, std::unique_ptr<ControllerDelegate> controller_delegate, + GlBrowserInterface* browser, gvr::GvrApi* gvr_api, bool reprojected_rendering, bool daydream_support, bool start_in_web_vr_mode, bool pause_content, - bool low_density) + bool low_density, + size_t sliding_time_size) : RenderLoop(std::move(ui), this, + this, std::move(controller_delegate), browser, - kWebVRSlidingAverageSize), + sliding_time_size), webvr_vsync_align_( base::FeatureList::IsEnabled(features::kWebVrVsyncAlign)), gvr_api_(gvr_api), @@ -211,11 +212,11 @@ browser_(browser), vr_ui_fps_meter_(), webvr_fps_meter_(), - webvr_js_time_(kWebVRSlidingAverageSize), - webvr_render_time_(kWebVRSlidingAverageSize), - webvr_js_wait_time_(kWebVRSlidingAverageSize), - webvr_acquire_time_(kWebVRSlidingAverageSize), - webvr_submit_time_(kWebVRSlidingAverageSize), + webvr_js_time_(sliding_time_size), + webvr_render_time_(sliding_time_size), + webvr_js_wait_time_(sliding_time_size), + webvr_acquire_time_(sliding_time_size), + webvr_submit_time_(sliding_time_size), weak_ptr_factory_(this) { GvrInit(); } @@ -267,13 +268,13 @@ unsigned int textures[4]; glGenTextures(4, textures); webvr_texture_id_ = textures[0]; - content_texture_id_ = textures[1]; - content_overlay_texture_id_ = textures[2]; + unsigned int content_texture_id = textures[1]; + unsigned int content_overlay_texture_id = textures[2]; unsigned int ui_texture_id = textures[3]; - content_surface_texture_ = gl::SurfaceTexture::Create(content_texture_id_); + content_surface_texture_ = gl::SurfaceTexture::Create(content_texture_id); content_overlay_surface_texture_ = - gl::SurfaceTexture::Create(content_overlay_texture_id_); + gl::SurfaceTexture::Create(content_overlay_texture_id); ui_surface_texture_ = gl::SurfaceTexture::Create(ui_texture_id); content_surface_ = @@ -308,8 +309,8 @@ // responding to RequestPresent. InitializeRenderer(); - ui_->OnGlInitialized(content_texture_id_, kGlTextureLocationExternal, - content_overlay_texture_id_, kGlTextureLocationExternal, + ui_->OnGlInitialized(content_texture_id, kGlTextureLocationExternal, + content_overlay_texture_id, kGlTextureLocationExternal, ui_texture_id); } @@ -610,13 +611,13 @@ DCHECK(webxr_.mailbox_bridge_ready()); // Don't allow any state changes for this processing frame until it - // arrives on the Surface. See OnWebVRFrameAvailable. + // arrives on the Surface. See OnWebXrFrameAvailable. DCHECK(webxr_.HaveProcessingFrame()); webxr_.GetProcessingFrame()->state_locked = true; bool swapped = mailbox_bridge_->CopyMailboxToSurfaceAndSwap(mailbox); DCHECK(swapped); - // Tell OnWebVRFrameAvailable to expect a new frame to arrive on + // Tell OnWebXrFrameAvailable to expect a new frame to arrive on // the SurfaceTexture, and save the associated frame index. pending_frames_.emplace(frame_index); @@ -669,7 +670,7 @@ if (!webvr_surface_texture_) { webvr_surface_texture_ = gl::SurfaceTexture::Create(webvr_texture_id_); webvr_surface_texture_->SetFrameAvailableCallback(base::BindRepeating( - &VrShellGl::OnWebVRFrameAvailable, weak_ptr_factory_.GetWeakPtr())); + &VrShellGl::OnWebXrFrameAvailable, weak_ptr_factory_.GetWeakPtr())); } CreateOrResizeWebVRSurface(webvr_size); } @@ -689,65 +690,13 @@ browser_->SendRequestPresentReply(std::move(session)); } -void VrShellGl::OnSwapContents(int new_content_id) { - ui_->OnSwapContents(new_content_id); -} - -void VrShellGl::EnableAlertDialog(PlatformInputHandler* input_handler, - float width, - float height) { - showing_vr_dialog_ = true; - vr_dialog_input_delegate_.reset(new PlatformUiInputDelegate(input_handler)); - vr_dialog_input_delegate_->SetSize(width, height); - if (web_vr_mode_) { - ui_->SetAlertDialogEnabled(true, vr_dialog_input_delegate_.get(), width, - height); - } else { - ui_->SetContentOverlayAlertDialogEnabled( - true, vr_dialog_input_delegate_.get(), - width / content_tex_buffer_size_.width(), - height / content_tex_buffer_size_.width()); - } +void VrShellGl::SetShowingVrDialog(bool showing) { + showing_vr_dialog_ = showing; ScheduleOrCancelWebVrFrameTimeout(); } -void VrShellGl::DisableAlertDialog() { - showing_vr_dialog_ = false; - ui_->SetAlertDialogEnabled(false, nullptr, 0, 0); - vr_dialog_input_delegate_ = nullptr; - ScheduleOrCancelWebVrFrameTimeout(); -} - -void VrShellGl::SetAlertDialogSize(float width, float height) { - if (vr_dialog_input_delegate_) - vr_dialog_input_delegate_->SetSize(width, height); - // If not floating, dialogs are rendered with a fixed width, so that only the - // ratio matters. But, if they are floating, its size should be relative to - // the contents. During a WebXR presentation, the contents might not have been - // initialized but, in this case, the dialogs are never floating. - if (web_vr_mode_) { - ui_->SetAlertDialogSize(width, height); - } else { - ui_->SetContentOverlayAlertDialogSize( - width / content_tex_buffer_size_.width(), - height / content_tex_buffer_size_.width()); - } -} - -void VrShellGl::SetDialogLocation(float x, float y) { - ui_->SetDialogLocation(x, y); -} - -void VrShellGl::SetDialogFloating(bool floating) { - ui_->SetDialogFloating(floating); -} - -void VrShellGl::ShowToast(const base::string16& text) { - ui_->ShowPlatformToast(text); -} - -void VrShellGl::CancelToast() { - ui_->CancelPlatformToast(); +int VrShellGl::GetContentBufferWidth() { + return web_vr_mode_ ? 0 : content_tex_buffer_size_.width(); } void VrShellGl::ResumeContentRendering() { @@ -774,7 +723,7 @@ ui_surface_texture_->UpdateTexImage(); } -void VrShellGl::OnWebVRFrameAvailable() { +void VrShellGl::OnWebXrFrameAvailable() { // This is called each time a frame that was drawn on the WebVR Surface // arrives on the SurfaceTexture. @@ -788,7 +737,7 @@ webvr_surface_texture_->UpdateTexImage(); int frame_index = pending_frames_.front(); - TRACE_EVENT1("gpu", "VrShellGl::OnWebVRFrameAvailable", "frame", frame_index); + TRACE_EVENT1("gpu", "VrShellGl::OnWebXrFrameAvailable", "frame", frame_index); pending_frames_.pop(); // The usual transform matrix we get for the Surface flips Y, so we need to @@ -824,7 +773,7 @@ } void VrShellGl::OnNewWebVRFrame() { - ui_->OnWebVrFrameAvailable(); + ui_->OnWebXrFrameAvailable(); if (web_vr_mode_) { ++webvr_frames_received_; @@ -836,6 +785,10 @@ ScheduleOrCancelWebVrFrameTimeout(); } +bool VrShellGl::CanSendWebXrVSync() const { + return web_vr_mode_ && !showing_vr_dialog_; +} + void VrShellGl::ScheduleOrCancelWebVrFrameTimeout() { // TODO(mthiesse): We should also timeout after the initial frame to prevent // bad experiences, but we have to be careful to handle things like splash @@ -847,13 +800,13 @@ webvr_spinner_timeout_.Cancel(); return; } - if (ui_->CanSendWebVrVSync() && submit_client_) { + if (CanSendWebXrVSync() && submit_client_) { webvr_spinner_timeout_.Reset(base::BindOnce( - &VrShellGl::OnWebVrTimeoutImminent, base::Unretained(this))); + &VrShellGl::OnWebXrTimeoutImminent, base::Unretained(this))); task_runner_->PostDelayedTask( FROM_HERE, webvr_spinner_timeout_.callback(), base::TimeDelta::FromSeconds(kWebVrSpinnerTimeoutSeconds)); - webvr_frame_timeout_.Reset(base::BindOnce(&VrShellGl::OnWebVrFrameTimedOut, + webvr_frame_timeout_.Reset(base::BindOnce(&VrShellGl::OnWebXrFrameTimedOut, base::Unretained(this))); task_runner_->PostDelayedTask( FROM_HERE, webvr_frame_timeout_.callback(), @@ -861,12 +814,12 @@ } } -void VrShellGl::OnWebVrFrameTimedOut() { - ui_->OnWebVrTimedOut(); +void VrShellGl::OnWebXrFrameTimedOut() { + ui_->OnWebXrTimedOut(); } -void VrShellGl::OnWebVrTimeoutImminent() { - ui_->OnWebVrTimeoutImminent(); +void VrShellGl::OnWebXrTimeoutImminent() { + ui_->OnWebXrTimeoutImminent(); } void VrShellGl::GvrInit() { @@ -1107,20 +1060,19 @@ } void VrShellGl::UpdateContentViewportTransforms( - const gfx::Transform& head_pose) { - gfx::Transform quad_transform = ui_->GetContentWorldSpaceTransform(); + const gfx::Transform& quad_transform) { // The Texture Quad renderer draws quads that extend from -0.5 to 0.5 in X and // Y, while Daydream's quad layers are implicitly -1.0 to 1.0. Thus to ensure // things line up we have to scale by 0.5. - quad_transform.Scale3d(0.5f * kContentVignetteScale, - 0.5f * kContentVignetteScale, 1.0f); + gfx::Transform transform = quad_transform; + transform.Scale3d(0.5f * kContentVignetteScale, 0.5f * kContentVignetteScale, + 1.0f); for (auto eye : {GVR_LEFT_EYE, GVR_RIGHT_EYE}) { CameraModel camera = (eye == GVR_LEFT_EYE) ? render_info_.left_eye_model : render_info_.right_eye_model; - gfx::Transform transform = camera.view_matrix * quad_transform; gvr::Mat4f viewport_transform; - TransformToGvrMat(transform, &viewport_transform); + TransformToGvrMat(camera.view_matrix * transform, &viewport_transform); gvr::BufferViewport& viewport = (eye == GVR_LEFT_EYE) ? content_underlay_viewport_.left : content_underlay_viewport_.right; @@ -1130,18 +1082,16 @@ void VrShellGl::DrawFrame(int16_t frame_index, base::TimeTicks current_time) { TRACE_EVENT1("gpu", "VrShellGl::DrawFrame", "frame", frame_index); - if (!webvr_delayed_gvr_submit_.IsCancelled()) { + DCHECK(browser_draw_callback_); + DCHECK(web_xr_draw_callback_); + if (!webxr_delayed_gvr_submit_.IsCancelled()) { // The last submit to GVR didn't complete, we have an acquired frame. This // is normal when exiting WebVR, in that case we just want to reuse the // frame. It's not supposed to happen during WebVR presentation. - if (frame_index >= 0) { - // This is a WebVR frame from OnWebVRFrameAvailable which isn't supposed - // to be delivered while the previous frame is still processing. Drop the - // previous work to avoid errors and reuse the acquired frame. - DLOG(WARNING) << "Unexpected WebVR DrawFrame during acquired frame"; - } - webvr_delayed_gvr_submit_.Cancel(); - DrawIntoAcquiredFrame(frame_index, current_time); + DCHECK_LT(frame_index, 0) + << "Unexpected WebXR DrawFrame during acquired frame"; + webxr_delayed_gvr_submit_.Cancel(); + browser_draw_callback_.Run(current_time); return; } @@ -1163,7 +1113,7 @@ // frame, it must be the current processing frame. Careful, we may still have // a processing frame in UI mode that couldn't be cancelled yet. For example // when showing a permission prompt, ShouldDrawWebVr() may have become false - // in the time between SubmitFrame and OnWebVRFrameAvailable or + // in the time between SubmitFrame and OnWebXrFrameAvailable or // OnWebVRTokenSignaled. In that case we continue handling the current frame // as a WebVR frame. Also, WebVR frames can still have overlay UI drawn on top // of them. @@ -1221,127 +1171,161 @@ if (!acquired_frame_) return; - DrawIntoAcquiredFrame(frame_index, current_time); + if (is_webxr_frame) + web_xr_draw_callback_.Run(current_time); + else + browser_draw_callback_.Run(current_time); } -void VrShellGl::DrawIntoAcquiredFrame(int16_t frame_index, - base::TimeTicks current_time) { - TRACE_EVENT1("gpu", "VrShellGl::DrawIntoAcquiredFrame", "frame", frame_index); - - bool is_webxr_frame = frame_index >= 0; - DCHECK(!is_webxr_frame || webxr_.HaveProcessingFrame()); - - UpdateUi(render_info_, current_time, is_webxr_frame ? kWebXrFrame : kUiFrame); - +RenderInfo VrShellGl::GetRenderInfo(FrameType frame_type) { gfx::Size render_size = - is_webxr_frame ? render_size_webvr_ui_ : render_size_default_; + frame_type == kWebXrFrame ? render_size_webvr_ui_ : render_size_default_; UpdateEyeInfos(render_info_.head_pose, main_viewport_, render_size, &render_info_); - ui_->OnProjMatrixChanged(render_info_.left_eye_model.proj_matrix); + return render_info_; +} - // Content quad can't have transparency when using the quad layer because we - // can't blend with the quad layer. - bool use_quad_layer = ui_->IsContentVisibleAndOpaque(); - - // We can't use webvr and the quad layer at the same time because they - // currently share the same non-multisampled buffer. - DCHECK(!is_webxr_frame || !use_quad_layer); - +void VrShellGl::InitializeBuffers() { viewport_list_ = gvr_api_->CreateEmptyBufferViewportList(); +} - ui_->SetContentUsesQuadLayer(use_quad_layer); - if (use_quad_layer) { - // This should be the first layer as it needs to be rendered behind the - // rest of the browser UI, which punches a transparent hole through to this - // layer. - DCHECK_EQ(viewport_list_.GetSize(), 0U); - - UpdateContentViewportTransforms(render_info_.head_pose); - - viewport_list_.SetBufferViewport(viewport_list_.GetSize(), - content_underlay_viewport_.left); - viewport_list_.SetBufferViewport(viewport_list_.GetSize(), - content_underlay_viewport_.right); - - // Draw the main browser content to a quad layer. - acquired_frame_.BindBuffer(kNoMultiSampleBuffer); - - glClear(GL_COLOR_BUFFER_BIT); - - DrawContentQuad(); - - acquired_frame_.Unbind(); +void VrShellGl::PrepareBufferForWebXr() { + DCHECK_EQ(viewport_list_.GetSize(), 0U); + viewport_list_.SetBufferViewport(0, webvr_viewport_.left); + viewport_list_.SetBufferViewport(1, webvr_viewport_.right); + acquired_frame_.BindBuffer(kNoMultiSampleBuffer); + if (webxr_use_shared_buffer_draw_) { + WebVrWaitForServerFence(); + CHECK(webxr_.HaveProcessingFrame()); } + // We're redrawing over the entire viewport, but it's generally more + // efficient on mobile tiling GPUs to clear anyway as a hint that + // we're done with the old content. TODO(klausw, https://crbug.com/700389): + // investigate using glDiscardFramebufferEXT here since that's more + // efficient on desktop, but it would need a capability check since + // it's not supported on older devices such as Nexus 5X. + glClear(GL_COLOR_BUFFER_BIT); + // Don't need face culling, depth testing, blending, etc. Turn it all off. + glDisable(GL_CULL_FACE); + glDisable(GL_SCISSOR_TEST); + glDisable(GL_BLEND); + glDisable(GL_POLYGON_OFFSET_FILL); - if (is_webxr_frame) { - DCHECK_EQ(viewport_list_.GetSize(), 0U); - viewport_list_.SetBufferViewport(0, webvr_viewport_.left); - viewport_list_.SetBufferViewport(1, webvr_viewport_.right); - acquired_frame_.BindBuffer(kNoMultiSampleBuffer); - // We're redrawing over the entire viewport, but it's generally more - // efficient on mobile tiling GPUs to clear anyway as a hint that - // we're done with the old content. TODO(klausw, https://crbug.com/700389): - // investigate using glDiscardFramebufferEXT here since that's more - // efficient on desktop, but it would need a capability check since - // it's not supported on older devices such as Nexus 5X. - glClear(GL_COLOR_BUFFER_BIT); - DrawWebVr(); - acquired_frame_.Unbind(); + glViewport(0, 0, webvr_surface_size_.width(), webvr_surface_size_.height()); +} + +void VrShellGl::PrepareBufferForWebXrOverlayElements() { + // WebVR content may use an arbitrary size buffer. We need to draw browser + // UI on a different buffer to make sure that our UI has enough resolution. + acquired_frame_.BindBuffer(kMultiSampleBuffer); + DCHECK_EQ(viewport_list_.GetSize(), 2U); + viewport_list_.SetBufferViewport(2, webvr_overlay_viewport_.left); + viewport_list_.SetBufferViewport(3, webvr_overlay_viewport_.right); + glClear(GL_COLOR_BUFFER_BIT); +} + +void VrShellGl::PrepareBufferForContentQuadLayer( + const gfx::Transform& quad_transform) { + DCHECK_EQ(viewport_list_.GetSize(), 0U); + UpdateContentViewportTransforms(quad_transform); + + viewport_list_.SetBufferViewport(viewport_list_.GetSize(), + content_underlay_viewport_.left); + viewport_list_.SetBufferViewport(viewport_list_.GetSize(), + content_underlay_viewport_.right); + // Draw the main browser content to a quad layer. + acquired_frame_.BindBuffer(kNoMultiSampleBuffer); + // Don't need face culling, depth testing, blending, etc. Turn it all off. + glDisable(GL_CULL_FACE); + glDisable(GL_SCISSOR_TEST); + glDisable(GL_POLYGON_OFFSET_FILL); + glDisable(GL_BLEND); + glClear(GL_COLOR_BUFFER_BIT); + + DCHECK(!content_tex_buffer_size_.IsEmpty()); + glViewport(content_tex_buffer_size_.width() * kContentVignetteBorder - + kContentBorderPixels, + content_tex_buffer_size_.height() * kContentVignetteBorder - + kContentBorderPixels, + content_tex_buffer_size_.width() + 2 * kContentBorderPixels, + content_tex_buffer_size_.height() + 2 * kContentBorderPixels); +} + +void VrShellGl::PrepareBufferForBrowserUi() { + DCHECK_LE(viewport_list_.GetSize(), 2U); + viewport_list_.SetBufferViewport(viewport_list_.GetSize(), + main_viewport_.left); + viewport_list_.SetBufferViewport(viewport_list_.GetSize(), + main_viewport_.right); + acquired_frame_.BindBuffer(kMultiSampleBuffer); + glClear(GL_COLOR_BUFFER_BIT); +} + +FovRectangles VrShellGl::GetRecommendedFovs() { + return {ToUiFovRect(main_viewport_.left.GetSourceFov()), + ToUiFovRect(main_viewport_.right.GetSourceFov())}; +} + +float VrShellGl::GetZNear() { + return kZNear; +} + +RenderInfo VrShellGl::GetOptimizedRenderInfoForFovs(const FovRectangles& fovs) { + webvr_overlay_viewport_.left.SetSourceFov(ToGvrRectf(fovs.first)); + webvr_overlay_viewport_.right.SetSourceFov(ToGvrRectf(fovs.second)); + + // Set render info to recommended setting. It will be used as our base for + // optimization. + RenderInfo render_info_webxr_overlay; + render_info_webxr_overlay.head_pose = render_info_.head_pose; + UpdateEyeInfos(render_info_webxr_overlay.head_pose, webvr_overlay_viewport_, + render_size_webvr_ui_, &render_info_webxr_overlay); + return render_info_webxr_overlay; +} + +void VrShellGl::OnFinishedDrawingBuffer() { + acquired_frame_.Unbind(); +} + +bool VrShellGl::IsContentQuadReady() { + return !content_tex_buffer_size_.IsEmpty(); +} + +void VrShellGl::GetContentQuadDrawParams(Transform* uv_transform, + float* border_x, + float* border_y) { + std::copy(kContentUvTransform, + kContentUvTransform + base::size(kContentUvTransform), + *uv_transform); + DCHECK(!content_tex_buffer_size_.IsEmpty()); + *border_x = kContentBorderPixels / content_tex_buffer_size_.width(); + *border_y = kContentBorderPixels / content_tex_buffer_size_.height(); +} + +void VrShellGl::GetWebXrDrawParams(int* texture_id, Transform* uv_transform) { + if (webxr_use_shared_buffer_draw_) { + WebXrSharedBuffer* buffer = + webxr_.GetProcessingFrame()->shared_buffer.get(); + CHECK(buffer); + *texture_id = buffer->local_texture; + // Use an identity UV transform, the image is already oriented correctly. + std::copy(kWebVrIdentityUvTransform, + kWebVrIdentityUvTransform + base::size(kWebVrIdentityUvTransform), + *uv_transform); } else { - DCHECK_LE(viewport_list_.GetSize(), 2U); - viewport_list_.SetBufferViewport(viewport_list_.GetSize(), - main_viewport_.left); - viewport_list_.SetBufferViewport(viewport_list_.GetSize(), - main_viewport_.right); - acquired_frame_.BindBuffer(kMultiSampleBuffer); - glClear(GL_COLOR_BUFFER_BIT); - // At this point, we draw non-WebVR content that could, potentially, fill - // the viewport. NB: this is not just 2d browsing stuff, we may have a - // splash screen showing in WebVR mode that must also fill the screen. That - // said, while the splash screen is up ShouldDrawWebVr() will return false, - // and we only draw UI frames, not WebVR frames. - ui_->Draw(render_info_); - acquired_frame_.Unbind(); + *texture_id = webvr_texture_id_; + // Apply the UV transform from the SurfaceTexture, that's usually a Y flip. + std::copy(webvr_surface_texture_uv_transform_, + webvr_surface_texture_uv_transform_ + + base::size(webvr_surface_texture_uv_transform_), + *uv_transform); } +} - if (is_webxr_frame && ui_->HasWebXrOverlayElementsToDraw()) { - // WebVR content may use an arbitrary size buffer. We need to draw browser - // UI on a different buffer to make sure that our UI has enough resolution. - acquired_frame_.BindBuffer(kMultiSampleBuffer); - glClear(GL_COLOR_BUFFER_BIT); - // Update recommended fov and uv per frame. - const auto& fov_recommended_left = - ToUiFovRect(main_viewport_.left.GetSourceFov()); - const auto& fov_recommended_right = - ToUiFovRect(main_viewport_.right.GetSourceFov()); - - auto fovs = ui_->GetMinimalFovForWebXrOverlayElements( - render_info_.left_eye_model.view_matrix, fov_recommended_left, - render_info_.right_eye_model.view_matrix, fov_recommended_right, - kZNear); - webvr_overlay_viewport_.left.SetSourceFov(ToGvrRectf(fovs.first)); - webvr_overlay_viewport_.right.SetSourceFov(ToGvrRectf(fovs.second)); - - DCHECK_EQ(viewport_list_.GetSize(), 2U); - viewport_list_.SetBufferViewport(2, webvr_overlay_viewport_.left); - viewport_list_.SetBufferViewport(3, webvr_overlay_viewport_.right); - - // Set render info to recommended setting. It will be used as our base for - // optimization. - RenderInfo render_info_webvr_browser_ui; - render_info_webvr_browser_ui.head_pose = render_info_.head_pose; - UpdateEyeInfos(render_info_webvr_browser_ui.head_pose, - webvr_overlay_viewport_, render_size_webvr_ui_, - &render_info_webvr_browser_ui); - - ui_->DrawWebVrOverlayForeground(render_info_webvr_browser_ui); - - acquired_frame_.Unbind(); - } - +void VrShellGl::SubmitFrame(FrameType frame_type) { // GVR submit needs the exact head pose that was used for rendering. gfx::Transform submit_head_pose; - if (is_webxr_frame) { + if (frame_type == kWebXrFrame) { // Don't use render_info_.head_pose here, that may have been // overwritten by OnVSync's controller handling. We need the pose that was // sent to JS. @@ -1350,7 +1334,7 @@ submit_head_pose = render_info_.head_pose; } std::unique_ptr<gl::GLFenceEGL> fence = nullptr; - if (is_webxr_frame && surfaceless_rendering_) { + if (frame_type == kWebXrFrame && surfaceless_rendering_) { webxr_.GetProcessingFrame()->time_copied = base::TimeTicks::Now(); if (webxr_use_gpu_fence_) { // Continue with submit once the previous frame's GL fence signals that @@ -1361,7 +1345,6 @@ // The fence had already signaled. We can get the signaled time from the // fence and submit immediately. AddWebVrRenderTimeEstimate( - frame_index, webvr_prev_frame_completion_fence_->GetStatusChangeTime()); webvr_prev_frame_completion_fence_.reset(); } else { @@ -1374,15 +1357,15 @@ } } if (fence) { - webvr_delayed_gvr_submit_.Reset(base::BindRepeating( + webxr_delayed_gvr_submit_.Reset(base::BindRepeating( &VrShellGl::DrawFrameSubmitWhenReady, base::Unretained(this))); task_runner_->PostTask( FROM_HERE, - base::BindOnce(webvr_delayed_gvr_submit_.callback(), frame_index, + base::BindOnce(webxr_delayed_gvr_submit_.callback(), frame_type, submit_head_pose, base::Passed(&fence))); } else { // Continue with submit immediately. - DrawFrameSubmitNow(frame_index, submit_head_pose); + DrawFrameSubmitNow(frame_type, submit_head_pose); } } @@ -1404,12 +1387,12 @@ } void VrShellGl::DrawFrameSubmitWhenReady( - int16_t frame_index, + FrameType frame_type, const gfx::Transform& head_pose, std::unique_ptr<gl::GLFenceEGL> fence) { - TRACE_EVENT1("gpu", "VrShellGl::DrawFrameSubmitWhenReady", "frame", - frame_index); - DVLOG(2) << __func__ << ": frame=" << static_cast<int>(frame_index); + TRACE_EVENT1("gpu", "VrShellGl::DrawFrameSubmitWhenReady", "frame_type", + frame_type); + DVLOG(2) << __func__ << ": frame_type=" << static_cast<int>(frame_type); bool use_polling = webxr_.mailbox_bridge_ready() && mailbox_bridge_->IsGpuWorkaroundEnabled( gpu::DONT_USE_EGLCLIENTWAITSYNC_WITH_TIMEOUT); @@ -1421,7 +1404,7 @@ kWebVRFenceCheckTimeout.InMicroseconds() * 1000); } if (!fence->HasCompleted()) { - webvr_delayed_gvr_submit_.Reset(base::BindRepeating( + webxr_delayed_gvr_submit_.Reset(base::BindRepeating( &VrShellGl::DrawFrameSubmitWhenReady, base::Unretained(this))); if (use_polling) { // Poll the fence status at a short interval. This burns some CPU, but @@ -1430,13 +1413,13 @@ // with a delay of up to one polling interval. task_runner_->PostDelayedTask( FROM_HERE, - base::BindOnce(webvr_delayed_gvr_submit_.callback(), frame_index, + base::BindOnce(webxr_delayed_gvr_submit_.callback(), frame_type, head_pose, base::Passed(&fence)), kWebVRFenceCheckPollInterval); } else { task_runner_->PostTask( FROM_HERE, - base::BindOnce(webvr_delayed_gvr_submit_.callback(), frame_index, + base::BindOnce(webxr_delayed_gvr_submit_.callback(), frame_type, head_pose, base::Passed(&fence))); } return; @@ -1446,15 +1429,14 @@ if (fence && webxr_use_gpu_fence_) { // We were waiting for the fence, so the time now is the actual // finish time for the previous frame's rendering. - AddWebVrRenderTimeEstimate(frame_index, base::TimeTicks::Now()); + AddWebVrRenderTimeEstimate(base::TimeTicks::Now()); } - webvr_delayed_gvr_submit_.Cancel(); - DrawFrameSubmitNow(frame_index, head_pose); + webxr_delayed_gvr_submit_.Cancel(); + DrawFrameSubmitNow(frame_type, head_pose); } void VrShellGl::AddWebVrRenderTimeEstimate( - int16_t frame_index, const base::TimeTicks& fence_complete_time) { if (!webxr_.HaveRenderingFrame()) return; @@ -1492,16 +1474,16 @@ } } -void VrShellGl::DrawFrameSubmitNow(int16_t frame_index, +void VrShellGl::DrawFrameSubmitNow(FrameType frame_type, const gfx::Transform& head_pose) { - TRACE_EVENT1("gpu", "VrShellGl::DrawFrameSubmitNow", "frame", frame_index); + TRACE_EVENT1("gpu", "VrShellGl::DrawFrameSubmitNow", "frame_type", + frame_type); gvr::Mat4f mat; TransformToGvrMat(head_pose, &mat); - bool is_webxr_frame = frame_index >= 0; { std::unique_ptr<ScopedGpuTrace> browser_gpu_trace; - if (gl::GLFence::IsGpuFenceSupported() && !is_webxr_frame) { + if (gl::GLFence::IsGpuFenceSupported() && frame_type == kUiFrame) { // This fence instance is created for the tracing side effect. Insert it // before GVR submit. Then replace the previous instance below after GVR // submit completes, at which point the previous fence (if any) should be @@ -1537,7 +1519,7 @@ // false for a WebVR frame. Ignore the ShouldDrawWebVr status to ensure we // send render notifications while paused for exclusive UI mode. Skip the // steps if we lost the processing state, that means presentation has ended. - if (is_webxr_frame && webxr_.HaveProcessingFrame()) { + if (frame_type == kWebXrFrame && webxr_.HaveProcessingFrame()) { // Report rendering completion to the Renderer so that it's permitted to // submit a fresh frame. We could do this earlier, as soon as the frame // got pulled off the transfer surface, but that results in overstuffed @@ -1571,7 +1553,7 @@ "controller", ui_controller_update_time().GetAverage().InMicroseconds()); - if (is_webxr_frame) { + if (frame_type == kWebXrFrame) { // We finished processing a frame, this may make pending WebVR // work eligible to proceed. webxr_.TryDeferredProcessing(); @@ -1586,75 +1568,38 @@ } bool VrShellGl::ShouldDrawWebVr() { - return web_vr_mode_ && ui_->ShouldRenderWebVr() && webvr_frames_received_ > 0; + return web_vr_mode_ && !showing_vr_dialog_ && webvr_frames_received_ > 0; } -void VrShellGl::DrawWebVr() { - TRACE_EVENT0("gpu", "VrShellGl::DrawWebVr"); - // Don't need face culling, depth testing, blending, etc. Turn it all off. - glDisable(GL_CULL_FACE); - glDisable(GL_SCISSOR_TEST); - glDisable(GL_BLEND); - glDisable(GL_POLYGON_OFFSET_FILL); - - glViewport(0, 0, webvr_surface_size_.width(), webvr_surface_size_.height()); - - if (webxr_use_shared_buffer_draw_) { - WebVrWaitForServerFence(); - CHECK(webxr_.HaveProcessingFrame()); - WebXrSharedBuffer* buffer = - webxr_.GetProcessingFrame()->shared_buffer.get(); - CHECK(buffer); - - // Use an identity UV transform, the image is already oriented correctly. - ui_->DrawWebXr(buffer->local_texture, kWebVrIdentityUvTransform); - } else { - // Apply the UV transform from the SurfaceTexture, that's usually a Y flip. - ui_->DrawWebXr(webvr_texture_id_, webvr_surface_texture_uv_transform_); - } -} - -void VrShellGl::DrawContentQuad() { - // Add a 2 pixel border to avoid aliasing issues at the edge of the texture. - constexpr float kBorder = 2; - TRACE_EVENT0("gpu", __func__); - // Don't need face culling, depth testing, blending, etc. Turn it all off. - glDisable(GL_CULL_FACE); - glDisable(GL_SCISSOR_TEST); - glDisable(GL_POLYGON_OFFSET_FILL); - glDisable(GL_BLEND); - glClear(GL_COLOR_BUFFER_BIT); - - glViewport( - content_tex_buffer_size_.width() * kContentVignetteBorder - kBorder, - content_tex_buffer_size_.height() * kContentVignetteBorder - kBorder, - content_tex_buffer_size_.width() + 2 * kBorder, - content_tex_buffer_size_.height() + 2 * kBorder); - - ui_->DrawContent(kContentUvTransform, - kBorder / content_tex_buffer_size_.width(), - kBorder / content_tex_buffer_size_.height()); -} - -void VrShellGl::OnPause() { +void VrShellGl::OnSchedulerPause() { vsync_helper_.CancelVSyncRequest(); - RenderLoop::OnPause(); gvr_api_->PauseTracking(); webvr_frame_timeout_.Cancel(); webvr_spinner_timeout_.Cancel(); } -void VrShellGl::OnResume() { +void VrShellGl::OnSchedulerResume() { gvr_api_->RefreshViewerProfile(); viewports_need_updating_ = true; gvr_api_->ResumeTracking(); - RenderLoop::OnResume(); vsync_helper_.CancelVSyncRequest(); OnVSync(base::TimeTicks::Now()); if (web_vr_mode_) ScheduleOrCancelWebVrFrameTimeout(); } +void VrShellGl::SetUiInterface(CompositorUiInterface* ui) { + ui_ = ui; +} + +void VrShellGl::SetDrawWebXrCallback(DrawCallback callback) { + web_xr_draw_callback_ = std::move(callback); +} + +void VrShellGl::SetDrawBrowserCallback(DrawCallback callback) { + browser_draw_callback_ = std::move(callback); +} + void VrShellGl::OnExitPresent() { webvr_frame_timeout_.Cancel(); webvr_spinner_timeout_.Cancel(); @@ -1697,11 +1642,6 @@ } } -void VrShellGl::ContentBoundsChanged(int width, int height) { - TRACE_EVENT0("gpu", "VrShellGl::ContentBoundsChanged"); - ui_->OnContentBoundsChanged(width, height); -} - void VrShellGl::BufferBoundsChanged(const gfx::Size& content_buffer_size, const gfx::Size& overlay_buffer_size) { content_tex_buffer_size_ = content_buffer_size; @@ -1711,14 +1651,10 @@ return weak_ptr_factory_.GetWeakPtr(); } -base::WeakPtr<BrowserUiInterface> VrShellGl::GetBrowserUiWeakPtr() { - return ui_->GetBrowserUiWeakPtr(); -} - bool VrShellGl::WebVrCanAnimateFrame(bool is_from_onvsync) { // This check needs to be first to ensure that we start the WebVR // first-frame timeout on presentation start. - bool can_send_webvr_vsync = ui_->CanSendWebVrVSync(); + bool can_send_webvr_vsync = CanSendWebXrVSync(); if (!webxr_.last_ui_allows_sending_vsync && can_send_webvr_vsync) { // We will start sending vsync to the WebVR page, so schedule the incoming // frame timeout. @@ -2115,8 +2051,4 @@ } } -void VrShellGl::AcceptDoffPromptForTesting() { - ui_->AcceptDoffPromptForTesting(); -} - } // namespace vr
diff --git a/chrome/browser/android/vr/vr_shell_gl.h b/chrome/browser/android/vr/vr_shell_gl.h index fbf79d7..afba116 100644 --- a/chrome/browser/android/vr/vr_shell_gl.h +++ b/chrome/browser/android/vr/vr_shell_gl.h
@@ -23,6 +23,7 @@ #include "chrome/browser/vr/model/controller_model.h" #include "chrome/browser/vr/render_info.h" #include "chrome/browser/vr/render_loop.h" +#include "chrome/browser/vr/scheduler_delegate.h" #include "chrome/browser/vr/sliding_average.h" #include "chrome/browser/vr/ui_test_input.h" #include "device/vr/public/mojom/vr_service.mojom.h" @@ -58,13 +59,11 @@ namespace vr { -class BrowserUiInterface; +class CompositorUiInterface; class ControllerDelegate; class FPSMeter; class GlBrowserInterface; class MailboxToSurfaceBridge; -class PlatformInputHandler; -class PlatformUiInputDelegate; class ScopedGpuTrace; class SlidingTimeDeltaAverage; class UiInterface; @@ -99,18 +98,20 @@ // It is not threadsafe and must only be used on the GL thread. class VrShellGl : public RenderLoop, public BaseCompositorDelegate, + public SchedulerDelegate, public device::mojom::XRPresentationProvider, public device::mojom::XRFrameDataProvider { public: - VrShellGl(GlBrowserInterface* browser, - std::unique_ptr<UiInterface> ui, + VrShellGl(std::unique_ptr<UiInterface> ui, std::unique_ptr<ControllerDelegate> controller_delegate, + GlBrowserInterface* browser, gvr::GvrApi* gvr_api, bool reprojected_rendering, bool daydream_support, bool start_in_web_vr_mode, bool pause_content, - bool low_density); + bool low_density, + size_t sliding_time_size); ~VrShellGl() override; void Init(base::WaitableEvent* gl_surface_created_event, @@ -119,11 +120,35 @@ void OnTriggerEvent(bool pressed); void OnExitPresent(); - // RenderLoop overrides. - void OnPause() override; - void OnResume() override; + // CompositorDelegate overrides. + FovRectangles GetRecommendedFovs() override; + float GetZNear() override; + RenderInfo GetRenderInfo(FrameType frame_type) override; + RenderInfo GetOptimizedRenderInfoForFovs(const FovRectangles& fovs) override; + void InitializeBuffers() override; + void PrepareBufferForWebXr() override; + void PrepareBufferForWebXrOverlayElements() override; + bool IsContentQuadReady() override; + void PrepareBufferForContentQuadLayer( + const gfx::Transform& quad_transform) override; + void PrepareBufferForBrowserUi() override; + void OnFinishedDrawingBuffer() override; + void GetWebXrDrawParams(int* texture_id, Transform* uv_transform) override; + void GetContentQuadDrawParams(Transform* uv_transform, + float* border_x, + float* border_y) override; + void SubmitFrame(FrameType frame_type) override; + void SetUiInterface(CompositorUiInterface* ui) override; + void SetShowingVrDialog(bool showing) override; + int GetContentBufferWidth() override; - base::WeakPtr<BrowserUiInterface> GetBrowserUiWeakPtr(); + // SchedulerDelegate overrides. + void SetDrawWebXrCallback(DrawCallback callback) override; + void SetDrawBrowserCallback(DrawCallback callback) override; + // TODO(acondor): Drop "Scheduler" from these names once RenderLoop owns + // VrShellGl. + void OnSchedulerPause() override; + void OnSchedulerResume() override; scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner() { return task_runner_; @@ -135,7 +160,6 @@ void WebVrCreateOrResizeSharedBufferImage(WebXrSharedBuffer* buffer, const gfx::Size& size); void WebVrPrepareSharedBuffer(const gfx::Size& size); - void ContentBoundsChanged(int width, int height); void BufferBoundsChanged(const gfx::Size& content_buffer_size, const gfx::Size& overlay_buffer_size); void UIBoundsChanged(int width, int height); @@ -147,22 +171,6 @@ device::mojom::VRDisplayInfoPtr display_info, device::mojom::XRRuntimeSessionOptionsPtr options); - void OnSwapContents(int new_content_id); - - void EnableAlertDialog(PlatformInputHandler* input_handler, - float width, - float height); - void DisableAlertDialog(); - - void SetAlertDialogSize(float width, float height); - void SetDialogLocation(float x, float y); - void SetDialogFloating(bool floating); - - void ShowToast(const base::string16& text); - void CancelToast(); - - void AcceptDoffPromptForTesting(); - private: void InitializeGl(gfx::AcceleratedWidget surface); void GvrInit(); @@ -183,28 +191,25 @@ RenderInfo* out_render_info); void UpdateContentViewportTransforms(const gfx::Transform& head_pose); void DrawFrame(int16_t frame_index, base::TimeTicks current_time); - void DrawIntoAcquiredFrame(int16_t frame_index, base::TimeTicks current_time); - void DrawFrameSubmitWhenReady(int16_t frame_index, + void DrawFrameSubmitWhenReady(FrameType frame_type, const gfx::Transform& head_pose, std::unique_ptr<gl::GLFenceEGL> fence); - void DrawFrameSubmitNow(int16_t frame_index, const gfx::Transform& head_pose); + void DrawFrameSubmitNow(FrameType frame_type, + const gfx::Transform& head_pose); bool ShouldDrawWebVr(); - void DrawWebVr(); - void DrawContentQuad(); bool WebVrPoseByteIsValid(int pose_index_byte); void OnContentFrameAvailable(); void OnContentOverlayFrameAvailable(); void OnUiFrameAvailable(); - void OnWebVRFrameAvailable(); + void OnWebXrFrameAvailable(); void OnNewWebVRFrame(); void ScheduleOrCancelWebVrFrameTimeout(); - void OnWebVrTimeoutImminent(); - void OnWebVrFrameTimedOut(); + void OnWebXrTimeoutImminent(); + void OnWebXrFrameTimedOut(); base::TimeDelta GetPredictedFrameTime(); - void AddWebVrRenderTimeEstimate(int16_t frame_index, - const base::TimeTicks& fence_complete_time); + void AddWebVrRenderTimeEstimate(const base::TimeTicks& fence_complete_time); void OnVSync(base::TimeTicks frame_time); @@ -255,9 +260,10 @@ void ProcessWebVrFrameFromMailbox(int16_t frame_index, const gpu::MailboxHolder& mailbox); + bool CanSendWebXrVSync() const; // Used for discarding unwanted WebVR frames while UI is showing. We can't // safely cancel frames from processing start until they show up in - // OnWebVRFrameAvailable, so only support cancelling them before or after + // OnWebXrFrameAvailable, so only support cancelling them before or after // that lifecycle segment. void WebVrCancelAnimatingFrame(); void WebVrCancelProcessingFrameAfterTransfer(); @@ -270,8 +276,6 @@ // samplerExternalOES texture data for WebVR content image. int webvr_texture_id_ = 0; - int content_texture_id_ = 0; - int content_overlay_texture_id_ = 0; // Set from feature flags. bool webvr_vsync_align_; @@ -362,6 +366,7 @@ device::mojom::XRPresentationClientPtr submit_client_; GlBrowserInterface* browser_; + CompositorUiInterface* ui_; uint64_t webvr_frames_received_ = 0; @@ -398,14 +403,16 @@ // for later. If we exit WebVR before it is executed, we need to // cancel it to avoid inconsistent state. base::CancelableOnceCallback< - void(int16_t, const gfx::Transform&, std::unique_ptr<gl::GLFenceEGL>)> - webvr_delayed_gvr_submit_; + void(FrameType, const gfx::Transform&, std::unique_ptr<gl::GLFenceEGL>)> + webxr_delayed_gvr_submit_; + + DrawCallback web_xr_draw_callback_; + DrawCallback browser_draw_callback_; std::vector<gvr::BufferSpec> specs_; ControllerModel controller_model_; - std::unique_ptr<PlatformUiInputDelegate> vr_dialog_input_delegate_; bool showing_vr_dialog_ = false; base::WeakPtrFactory<VrShellGl> weak_ptr_factory_;
diff --git a/chrome/browser/apps/app_shim/BUILD.gn b/chrome/browser/apps/app_shim/BUILD.gn index f8a6d186..82b974de 100644 --- a/chrome/browser/apps/app_shim/BUILD.gn +++ b/chrome/browser/apps/app_shim/BUILD.gn
@@ -21,7 +21,18 @@ ] deps = [ + "//apps", + "//chrome/browser/apps/platform_apps", + "//chrome/browser/extensions", + "//chrome/browser/web_applications/components", + "//chrome/browser/web_applications/extensions", + "//chrome/common", + "//chrome/common:app_mode_app_support", + "//chrome/common:constants", "//chrome/common:mojo_bindings", + "//chrome/common:non_code_constants", + "//components/crx_file", + "//components/version_info", "//content/public/browser", "//content/public/common", "//extensions/browser",
diff --git a/chrome/browser/apps/foundation/app_service/BUILD.gn b/chrome/browser/apps/foundation/app_service/BUILD.gn index 5b26c5b..e3a3254d 100644 --- a/chrome/browser/apps/foundation/app_service/BUILD.gn +++ b/chrome/browser/apps/foundation/app_service/BUILD.gn
@@ -16,6 +16,7 @@ deps = [ "//base", + "//components/pref_registry", "//components/prefs", "//mojo/public/cpp/bindings", "//services/preferences/public/cpp",
diff --git a/chrome/browser/apps/platform_apps/BUILD.gn b/chrome/browser/apps/platform_apps/BUILD.gn index 05382206a..bc3c6e6 100644 --- a/chrome/browser/apps/platform_apps/BUILD.gn +++ b/chrome/browser/apps/platform_apps/BUILD.gn
@@ -42,6 +42,7 @@ "//chrome/app:command_ids", "//chrome/browser/extensions", "//chrome/browser/media/router/discovery", + "//chrome/browser/web_applications/extensions", "//chrome/common", "//components/crx_file", "//components/keyed_service/content",
diff --git a/chrome/browser/chrome_browser_main_browsertest.cc b/chrome/browser/chrome_browser_main_browsertest.cc index e717c04..fe2676a 100644 --- a/chrome/browser/chrome_browser_main_browsertest.cc +++ b/chrome/browser/chrome_browser_main_browsertest.cc
@@ -78,10 +78,15 @@ DISALLOW_COPY_AND_ASSIGN(ChromeBrowserMainExtraPartsNetFactoryInstaller); }; -class ChromeBrowserMainBrowserTest : public InProcessBrowserTest { +class ChromeBrowserMainBrowserTest + : public InProcessBrowserTest, + network::NetworkConnectionTracker::NetworkConnectionObserver { public: ChromeBrowserMainBrowserTest() = default; - ~ChromeBrowserMainBrowserTest() override = default; + ~ChromeBrowserMainBrowserTest() override { + content::GetNetworkConnectionTracker()->RemoveNetworkConnectionObserver( + this); + } protected: // InProcessBrowserTest: @@ -103,8 +108,33 @@ chrome_browser_main_parts->AddParts(extra_parts_); } + void SetUpOnMainThread() override { + content::GetNetworkConnectionTracker()->AddNetworkConnectionObserver(this); + } + + void WaitForConnectionType(network::mojom::ConnectionType type) { + if (connection_type_ == type) + return; + + expected_connection_type_ = type; + run_loop_ = std::make_unique<base::RunLoop>(); + run_loop_->Run(); + } + ChromeBrowserMainExtraPartsNetFactoryInstaller* extra_parts_ = nullptr; + private: + // network::NetworkConnectionTracker::NetworkConnectionObserver: + void OnConnectionChanged(network::mojom::ConnectionType type) override { + connection_type_ = type; + if (expected_connection_type_ == connection_type_ && run_loop_) + run_loop_->Quit(); + } + + network::mojom::ConnectionType expected_connection_type_; + network::mojom::ConnectionType connection_type_; + std::unique_ptr<base::RunLoop> run_loop_; + DISALLOW_COPY_AND_ASSIGN(ChromeBrowserMainBrowserTest); }; @@ -116,6 +146,7 @@ g_browser_process->variations_service()->request_count(); ASSERT_TRUE(extra_parts_); SimulateNetworkChange(network::mojom::ConnectionType::CONNECTION_WIFI); + WaitForConnectionType(network::mojom::ConnectionType::CONNECTION_WIFI); // NotifyObserversOfNetworkChangeForTests uses PostTask, so run the loop until // idle to ensure VariationsService processes the network change. base::RunLoop().RunUntilIdle();
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn index 5a3100a..ea1d515a 100644 --- a/chrome/browser/chromeos/BUILD.gn +++ b/chrome/browser/chromeos/BUILD.gn
@@ -58,6 +58,7 @@ "//chrome/app:command_ids", "//chrome/app/vector_icons", "//chrome/browser/apps/foundation/app_service:lib", + "//chrome/browser/apps/platform_apps", "//chrome/browser/chromeos/android_sms:android_sms_urls", "//chrome/browser/chromeos/power/ml:user_activity_ukm_logger_helpers", "//chrome/browser/chromeos/power/ml/smart_dim", @@ -66,6 +67,7 @@ "//chrome/browser/resource_coordinator:tab_metrics_event_proto", "//chrome/browser/ssl:proto", "//chrome/browser/web_applications", + "//chrome/browser/web_applications/bookmark_apps", "//chrome/browser/web_applications/components", "//chrome/common", "//chrome/common/extensions/api", @@ -243,7 +245,10 @@ ":dbus_service_files", ] - allow_circular_includes_from = [ "//chrome/browser/extensions" ] + allow_circular_includes_from = [ + "//chrome/browser/extensions", + "//chrome/browser/web_applications/bookmark_apps", + ] sources = [ "accessibility/accessibility_extension_loader.cc",
diff --git a/chrome/browser/chromeos/arc/auth/arc_auth_service.cc b/chrome/browser/chromeos/arc/auth/arc_auth_service.cc index 9ce4d8b..7c6f7c9 100644 --- a/chrome/browser/chromeos/arc/auth/arc_auth_service.cc +++ b/chrome/browser/chromeos/arc/auth/arc_auth_service.cc
@@ -365,6 +365,16 @@ ArcSessionManager::Get()->auth_context()->full_account_id(), GetAccountType(profile_), policy_util::IsAccountManaged(profile_)), mojom::ArcSignInStatus::SUCCESS); + } else if (chromeos::DemoSession::Get() && + chromeos::DemoSession::Get()->started()) { + // For demo sessions, if auth code fetch failed (e.g. because the device is + // offline), fall back to accountless offline demo mode provisioning. + OnAccountInfoReady( + CreateAccountInfo(true /* is_enforced */, std::string() /* auth_info */, + std::string() /* auth_name */, + mojom::ChromeAccountType::OFFLINE_DEMO_ACCOUNT, + true /* is_managed */), + mojom::ArcSignInStatus::SUCCESS); } else { // Send error to ARC. OnAccountInfoReady(
diff --git a/chrome/browser/chromeos/arc/auth/arc_auth_service_browsertest.cc b/chrome/browser/chromeos/arc/auth/arc_auth_service_browsertest.cc index 83c0b45..96c5c2dc 100644 --- a/chrome/browser/chromeos/arc/auth/arc_auth_service_browsertest.cc +++ b/chrome/browser/chromeos/arc/auth/arc_auth_service_browsertest.cc
@@ -393,6 +393,30 @@ EXPECT_TRUE(auth_instance().account_info()->is_managed); } +IN_PROC_BROWSER_TEST_F(ArcRobotAccountAuthServiceTest, + GetDemoAccountOnAuthTokenFetchFailure) { + chromeos::DemoSession::SetDemoModeEnrollmentTypeForTesting( + chromeos::DemoSession::EnrollmentType::kOnline); + chromeos::DemoSession::StartIfInDemoMode(); + + SetAccountAndProfile(user_manager::USER_TYPE_PUBLIC_ACCOUNT); + + interceptor()->PushJobCallback( + policy::TestRequestInterceptor::HttpErrorJob("404 Not Found")); + + base::RunLoop run_loop; + auth_instance().RequestAccountInfo(run_loop.QuitClosure()); + run_loop.Run(); + + ASSERT_TRUE(auth_instance().account_info()); + EXPECT_TRUE(auth_instance().account_info()->account_name.value().empty()); + EXPECT_TRUE(auth_instance().account_info()->auth_code.value().empty()); + EXPECT_EQ(mojom::ChromeAccountType::OFFLINE_DEMO_ACCOUNT, + auth_instance().account_info()->account_type); + EXPECT_FALSE(auth_instance().account_info()->enrollment_token); + EXPECT_TRUE(auth_instance().account_info()->is_managed); +} + class ArcAuthServiceChildAccountTest : public ArcAuthServiceTest { protected: ArcAuthServiceChildAccountTest() = default;
diff --git a/chrome/browser/chromeos/login/demo_mode/demo_extensions_external_loader_unittest.cc b/chrome/browser/chromeos/login/demo_mode/demo_extensions_external_loader_unittest.cc index 39fc144..88998bb 100644 --- a/chrome/browser/chromeos/login/demo_mode/demo_extensions_external_loader_unittest.cc +++ b/chrome/browser/chromeos/login/demo_mode/demo_extensions_external_loader_unittest.cc
@@ -27,6 +27,7 @@ #include "chrome/test/base/testing_profile.h" #include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/fake_image_loader_client.h" +#include "components/session_manager/core/session_manager.h" #include "components/user_manager/scoped_user_manager.h" #include "content/public/test/test_browser_thread_bundle.h" #include "extensions/browser/external_install_info.h" @@ -122,6 +123,7 @@ image_loader_client_ = image_loader_client.get(); DBusThreadManager::GetSetterForTesting()->SetImageLoaderClient( std::move(image_loader_client)); + session_manager_ = std::make_unique<session_manager::SessionManager>(); } void TearDown() override { @@ -213,6 +215,8 @@ base::ScopedTempDir offline_demo_resources_; + std::unique_ptr<session_manager::SessionManager> session_manager_; + DISALLOW_COPY_AND_ASSIGN(DemoExtensionsExternalLoaderTest); }; @@ -444,6 +448,7 @@ user_manager_ = fake_user_manager.get(); scoped_user_manager_ = std::make_unique<user_manager::ScopedUserManager>( std::move(fake_user_manager)); + session_manager_ = std::make_unique<session_manager::SessionManager>(); } ~ShouldCreateDemoExtensionsExternalLoaderTest() override = default; @@ -483,6 +488,7 @@ private: content::TestBrowserThreadBundle thread_bundle_; std::unique_ptr<user_manager::ScopedUserManager> scoped_user_manager_; + std::unique_ptr<session_manager::SessionManager> session_manager_; DISALLOW_COPY_AND_ASSIGN(ShouldCreateDemoExtensionsExternalLoaderTest); };
diff --git a/chrome/browser/chromeos/login/demo_mode/demo_mode_resources_remover_unittest.cc b/chrome/browser/chromeos/login/demo_mode/demo_mode_resources_remover_unittest.cc index 9a036df..32cd6c6 100644 --- a/chrome/browser/chromeos/login/demo_mode/demo_mode_resources_remover_unittest.cc +++ b/chrome/browser/chromeos/login/demo_mode/demo_mode_resources_remover_unittest.cc
@@ -13,15 +13,14 @@ #include "base/files/scoped_temp_dir.h" #include "base/macros.h" #include "base/optional.h" -#include "base/test/scoped_task_environment.h" +#include "base/test/scoped_path_override.h" #include "base/test/simple_test_tick_clock.h" #include "base/values.h" #include "chrome/browser/chromeos/login/demo_mode/demo_session.h" #include "chrome/browser/chromeos/login/users/fake_chrome_user_manager.h" #include "chrome/browser/chromeos/profiles/profile_helper.h" #include "chrome/browser/chromeos/settings/stub_install_attributes.h" -#include "chrome/browser/extensions/external_policy_loader.h" -#include "chrome/test/base/testing_profile.h" +#include "chromeos/chromeos_paths.h" #include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/fake_cryptohome_client.h" #include "components/prefs/testing_pref_service.h" @@ -67,10 +66,11 @@ std::move(cryptohome_client)); ASSERT_TRUE(scoped_temp_dir_.CreateUniqueTempDir()); - demo_resources_path_ = - scoped_temp_dir_.GetPath().AppendASCII("demo-mode-resources"); - DemoSession::OverridePreInstalledDemoResourcesPathForTesting( - &demo_resources_path_); + components_path_override_ = std::make_unique<base::ScopedPathOverride>( + chromeos::DIR_PREINSTALLED_COMPONENTS, scoped_temp_dir_.GetPath()); + demo_resources_path_ = scoped_temp_dir_.GetPath() + .AppendASCII("cros-components") + .AppendASCII("demo-mode-resources"); scoped_user_manager_ = std::make_unique<user_manager::ScopedUserManager>( std::make_unique<FakeChromeUserManager>()); @@ -83,7 +83,6 @@ void TearDown() override { DemoSession::ShutDownIfInitialized(); - DemoSession::OverridePreInstalledDemoResourcesPathForTesting(nullptr); DemoSession::SetDemoModeEnrollmentTypeForTesting( DemoSession::EnrollmentType::kNone); chromeos::DBusThreadManager::Shutdown(); @@ -190,6 +189,7 @@ std::unique_ptr<ScopedStubInstallAttributes> install_attributes_; base::ScopedTempDir scoped_temp_dir_; + std::unique_ptr<base::ScopedPathOverride> components_path_override_; base::FilePath demo_resources_path_; std::unique_ptr<user_manager::ScopedUserManager> scoped_user_manager_;
diff --git a/chrome/browser/chromeos/login/demo_mode/demo_session.cc b/chrome/browser/chromeos/login/demo_mode/demo_session.cc index 1b42996f..068553de 100644 --- a/chrome/browser/chromeos/login/demo_mode/demo_session.cc +++ b/chrome/browser/chromeos/login/demo_mode/demo_session.cc
@@ -8,13 +8,20 @@ #include "base/bind.h" #include "base/callback.h" +#include "base/command_line.h" +#include "base/path_service.h" +#include "base/sys_info.h" +#include "chrome/browser/apps/platform_apps/app_load_service.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/browser_process_platform_part.h" #include "chrome/browser/chromeos/login/demo_mode/demo_setup_controller.h" #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h" #include "chrome/browser/chromeos/settings/install_attributes.h" +#include "chrome/browser/profiles/profile_manager.h" +#include "chromeos/chromeos_paths.h" #include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/image_loader_client.h" +#include "components/session_manager/core/session_manager.h" namespace chromeos { @@ -30,16 +37,6 @@ // The name of the offline demo resource image loader component. constexpr char kDemoResourcesComponentName[] = "demo-mode-resources"; -// The path from which the offline demo mode resources component should be -// loaded by the image loader service. -constexpr base::FilePath::CharType kPreInstalledDemoResourcesComponentPath[] = - FILE_PATH_LITERAL( - "/mnt/stateful_partition/unencrypted/demo_mode_resources"); - -// Can be set in test to override location of preinstalled offline resources -// component path. -const base::FilePath* g_pre_installed_demo_resources_path_override = nullptr; - // Path relative to the path at which offline demo resources are loaded that // contains image with demo Android apps. constexpr base::FilePath::CharType kDemoAppsPath[] = @@ -48,6 +45,14 @@ constexpr base::FilePath::CharType kExternalExtensionsPrefsPath[] = FILE_PATH_LITERAL("demo_extensions.json"); +// Path relative to the path at which offline demo resources are loaded that +// contains the highlights app. +constexpr char kHighlightsAppPath[] = "chrome_apps/highlights/dist"; + +// The name of the subdirectory that contains the resources for the default +// highlights app, used when a board-specific version is not available. +constexpr char kDefaultHighlightsAppResourcesPath[] = "default"; + bool IsDemoModeOfflineEnrolled() { DCHECK(DemoSession::IsDeviceInDemoMode()); return DemoSession::GetEnrollmentType() == @@ -58,15 +63,11 @@ // static base::FilePath DemoSession::GetPreInstalledDemoResourcesPath() { - if (g_pre_installed_demo_resources_path_override) - return *g_pre_installed_demo_resources_path_override; - return base::FilePath(kPreInstalledDemoResourcesComponentPath); -} - -// static -void DemoSession::OverridePreInstalledDemoResourcesPathForTesting( - base::FilePath* overriden_path) { - g_pre_installed_demo_resources_path_override = overriden_path; + base::FilePath preinstalled_components_root; + base::PathService::Get(DIR_PREINSTALLED_COMPONENTS, + &preinstalled_components_root); + return preinstalled_components_root.AppendASCII("cros-components") + .AppendASCII(kDemoResourcesComponentName); } // static @@ -207,7 +208,12 @@ } DemoSession::DemoSession() - : offline_enrolled_(IsDemoModeOfflineEnrolled()), weak_ptr_factory_(this) {} + : offline_enrolled_(IsDemoModeOfflineEnrolled()), + session_manager_observer_(this), + weak_ptr_factory_(this) { + session_manager_observer_.Add(session_manager::SessionManager::Get()); + OnSessionStateChanged(); +} DemoSession::~DemoSession() = default; @@ -224,4 +230,42 @@ std::move(callback).Run(); } +void DemoSession::LoadAndLaunchHighlightsApp() { + DCHECK(offline_resources_loaded_); + if (offline_resources_path_.empty()) { + LOG(ERROR) << "Offline resources not loaded - no highlights app available."; + return; + } + Profile* profile = ProfileManager::GetPrimaryUserProfile(); + DCHECK(profile); + const std::vector<std::string> board = + base::SplitString(base::SysInfo::GetLsbReleaseBoard(), "-", + base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY); + const std::string board_name = board[0]; + base::FilePath resources_path = + offline_resources_path_.Append(kHighlightsAppPath) + .Append(kDefaultHighlightsAppResourcesPath); + base::FilePath board_specific_resources_path = + offline_resources_path_.Append(kHighlightsAppPath).Append(board_name); + if (base::PathExists(board_specific_resources_path)) + resources_path = board_specific_resources_path; + + if (!apps::AppLoadService::Get(profile)->LoadAndLaunch( + resources_path, base::CommandLine(base::CommandLine::NO_PROGRAM), + base::FilePath() /* cur_dir */)) { + LOG(WARNING) << "Failed to launch highlights app!"; + } +} + +void DemoSession::OnSessionStateChanged() { + if (session_manager::SessionManager::Get()->session_state() != + session_manager::SessionState::ACTIVE || + !IsDeviceInDemoMode()) { + return; + } + EnsureOfflineResourcesLoaded( + base::BindOnce(&DemoSession::LoadAndLaunchHighlightsApp, + weak_ptr_factory_.GetWeakPtr())); +} + } // namespace chromeos
diff --git a/chrome/browser/chromeos/login/demo_mode/demo_session.h b/chrome/browser/chromeos/login/demo_mode/demo_session.h index 3c27633..5ff549b 100644 --- a/chrome/browser/chromeos/login/demo_mode/demo_session.h +++ b/chrome/browser/chromeos/login/demo_mode/demo_session.h
@@ -12,13 +12,19 @@ #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "base/optional.h" +#include "base/scoped_observer.h" #include "chrome/browser/component_updater/cros_component_installer_chromeos.h" +#include "components/session_manager/core/session_manager_observer.h" + +namespace session_manager { +class SessionManager; +} namespace chromeos { // Tracks global demo session state. For example, whether the demo session has // started, and whether the demo session offline resources have been loaded. -class DemoSession { +class DemoSession : public session_manager::SessionManagerObserver { public: enum class EnrollmentType { // Demo mode enrollment unset/unknown. @@ -38,8 +44,6 @@ // Location on disk where pre-installed demo mode resources are expected to be // found. static base::FilePath GetPreInstalledDemoResourcesPath(); - static void OverridePreInstalledDemoResourcesPathForTesting( - base::FilePath* overriden_path); // Whether the device is set up to run demo sessions. static bool IsDeviceInDemoMode(); @@ -95,7 +99,7 @@ private: DemoSession(); - ~DemoSession(); + ~DemoSession() override; // Called after load of a currently installed (if any) demo mode resources // component has finished. @@ -109,6 +113,12 @@ // |mount_path| is the path at which the resources were loaded. void OnOfflineResourcesLoaded(base::Optional<base::FilePath> mounted_path); + // Loads and launches the highlights app. + void LoadAndLaunchHighlightsApp(); + + // session_manager::SessionManagerObserver: + void OnSessionStateChanged() override; + // Whether the device was offline-enrolled into demo mode, i.e. enrolled using // pre-built policies. Offline enrolled demo sessions do not have working // robot account associated with them. @@ -126,6 +136,10 @@ // List of pending callbacks passed to EnsureOfflineResourcesLoaded(). std::list<base::OnceClosure> offline_resources_load_callbacks_; + ScopedObserver<session_manager::SessionManager, + session_manager::SessionManagerObserver> + session_manager_observer_; + base::WeakPtrFactory<DemoSession> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(DemoSession);
diff --git a/chrome/browser/chromeos/login/demo_mode/demo_session_unittest.cc b/chrome/browser/chromeos/login/demo_mode/demo_session_unittest.cc index a2a01dd..e1816f8 100644 --- a/chrome/browser/chromeos/login/demo_mode/demo_session_unittest.cc +++ b/chrome/browser/chromeos/login/demo_mode/demo_session_unittest.cc
@@ -15,6 +15,7 @@ #include "base/macros.h" #include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/fake_image_loader_client.h" +#include "components/session_manager/core/session_manager.h" #include "content/public/test/test_browser_thread_bundle.h" #include "testing/gtest/include/gtest/gtest.h" @@ -120,6 +121,7 @@ image_loader_client_ = image_loader_client.get(); chromeos::DBusThreadManager::GetSetterForTesting()->SetImageLoaderClient( std::move(image_loader_client)); + session_manager_ = std::make_unique<session_manager::SessionManager>(); } void TearDown() override { @@ -134,6 +136,7 @@ // Points to the image loader client passed to the test DBusTestManager. TestImageLoaderClient* image_loader_client_ = nullptr; content::TestBrowserThreadBundle thread_bundle_; + std::unique_ptr<session_manager::SessionManager> session_manager_; private: DISALLOW_COPY_AND_ASSIGN(DemoSessionTest);
diff --git a/chrome/browser/chromeos/smb_client/smb_service.cc b/chrome/browser/chromeos/smb_client/smb_service.cc index 1b56df5..d5f209b 100644 --- a/chrome/browser/chromeos/smb_client/smb_service.cc +++ b/chrome/browser/chromeos/smb_client/smb_service.cc
@@ -96,6 +96,7 @@ void SmbService::RegisterProfilePrefs( user_prefs::PrefRegistrySyncable* registry) { registry->RegisterBooleanPref(prefs::kNetworkFileSharesAllowed, true); + registry->RegisterBooleanPref(prefs::kNetBiosShareDiscoveryEnabled, true); } void SmbService::Mount(const file_system_provider::MountOptions& options,
diff --git a/chrome/browser/extensions/BUILD.gn b/chrome/browser/extensions/BUILD.gn index fd72268..a0c053e 100644 --- a/chrome/browser/extensions/BUILD.gn +++ b/chrome/browser/extensions/BUILD.gn
@@ -481,6 +481,8 @@ "chrome_extension_host_delegate.h", "chrome_extension_web_contents_observer.cc", "chrome_extension_web_contents_observer.h", + "chrome_extensions_browser_api_provider.cc", + "chrome_extensions_browser_api_provider.h", "chrome_extensions_browser_client.cc", "chrome_extensions_browser_client.h", "chrome_extensions_interface_registration.cc", @@ -771,6 +773,10 @@ ] defines = [] + # TODO(loyso): Remove this circular dependency. http://crbug.com/876576. + allow_circular_includes_from = + [ "//chrome/browser/web_applications/extensions" ] + # Since browser and browser_extensions actually depend on each other, # we must omit the dependency from browser_extensions to browser. # However, this means browser_extensions and browser should more or less @@ -873,7 +879,7 @@ "//device/bluetooth", "//extensions:extensions_resources", "//extensions/browser", - "//extensions/browser/api:api_registration", + "//extensions/browser:core_api_provider", "//extensions/buildflags", "//extensions/common", "//extensions/common/api",
diff --git a/chrome/browser/extensions/api/content_settings/content_settings_service.cc b/chrome/browser/extensions/api/content_settings/content_settings_service.cc index 83169fc..272f5ee 100644 --- a/chrome/browser/extensions/api/content_settings/content_settings_service.cc +++ b/chrome/browser/extensions/api/content_settings/content_settings_service.cc
@@ -5,7 +5,6 @@ #include "chrome/browser/extensions/api/content_settings/content_settings_service.h" #include "base/lazy_instance.h" -#include "chrome/browser/extensions/api/content_settings/content_settings_store.h" #include "extensions/browser/extension_prefs.h" #include "extensions/browser/extension_prefs_scope.h" #include "extensions/browser/pref_names.h"
diff --git a/chrome/browser/extensions/api/content_settings/content_settings_service.h b/chrome/browser/extensions/api/content_settings/content_settings_service.h index 96fa0e8d..0b4d70ca2 100644 --- a/chrome/browser/extensions/api/content_settings/content_settings_service.h +++ b/chrome/browser/extensions/api/content_settings/content_settings_service.h
@@ -7,6 +7,7 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" +#include "chrome/browser/extensions/api/content_settings/content_settings_store.h" #include "extensions/browser/browser_context_keyed_api_factory.h" #include "extensions/browser/extension_prefs_observer.h"
diff --git a/chrome/browser/extensions/api/developer_private/developer_private_api.cc b/chrome/browser/extensions/api/developer_private/developer_private_api.cc index 2e7539d..f748cf4 100644 --- a/chrome/browser/extensions/api/developer_private/developer_private_api.cc +++ b/chrome/browser/extensions/api/developer_private/developer_private_api.cc
@@ -34,6 +34,7 @@ #include "chrome/browser/extensions/extension_ui_util.h" #include "chrome/browser/extensions/extension_util.h" #include "chrome/browser/extensions/install_verifier.h" +#include "chrome/browser/extensions/permissions_updater.h" #include "chrome/browser/extensions/scripting_permissions_modifier.h" #include "chrome/browser/extensions/shared_module_service.h" #include "chrome/browser/extensions/unpacked_installer.h" @@ -267,6 +268,25 @@ return response; } +base::Optional<URLPattern> ParseRuntimePermissionsPattern( + const std::string& pattern_str) { + constexpr int kValidRuntimePermissionSchemes = URLPattern::SCHEME_HTTP | + URLPattern::SCHEME_HTTPS | + URLPattern::SCHEME_FILE; + + URLPattern pattern(kValidRuntimePermissionSchemes); + if (pattern.Parse(pattern_str) != URLPattern::PARSE_SUCCESS) + return base::nullopt; + + // We don't allow adding paths for permissions, because they aren't meaningful + // in terms of origin access. The frontend should validate this, but there's + // a chance something can slip through, so we should fail gracefully. + if (pattern.path() != "/*") + return base::nullopt; + + return pattern; +} + } // namespace namespace ChoosePath = api::developer_private::ChoosePath; @@ -1969,30 +1989,27 @@ developer::AddHostPermission::Params::Create(*args_)); EXTENSION_FUNCTION_VALIDATE(params); - GURL host(params->host); - if (!host.is_valid() || host.path_piece().length() > 1 || host.has_query() || - host.has_ref()) { + base::Optional<URLPattern> pattern = + ParseRuntimePermissionsPattern(params->host); + if (!pattern) return RespondNow(Error(kInvalidHost)); - } const Extension* extension = GetExtensionById(params->extension_id); if (!extension) return RespondNow(Error(kNoSuchExtensionError)); - ScriptingPermissionsModifier scripting_modifier(browser_context(), extension); - if (!scripting_modifier.CanAffectExtension()) + if (!ScriptingPermissionsModifier(browser_context(), extension) + .CanAffectExtension()) { return RespondNow(Error(kCannotChangeHostPermissions)); - - // Only grant withheld permissions. This also ensures that we won't grant - // any permission for a host that shouldn't be accessible to the extension, - // like chrome:-scheme urls. - if (!extension->permissions_data() - ->withheld_permissions() - .HasEffectiveAccessToURL(host)) { - return RespondNow(Error("Cannot grant a permission that wasn't withheld.")); } - scripting_modifier.GrantHostPermission(host); + URLPatternSet new_host_permissions({*pattern}); + PermissionsUpdater(browser_context()) + .GrantRuntimePermissions( + *extension, + PermissionSet(APIPermissionSet(), ManifestPermissionSet(), + new_host_permissions, new_host_permissions)); + return RespondNow(NoArguments()); } @@ -2007,11 +2024,10 @@ developer::RemoveHostPermission::Params::Create(*args_)); EXTENSION_FUNCTION_VALIDATE(params); - GURL host(params->host); - if (!host.is_valid() || host.path_piece().length() > 1 || host.has_query() || - host.has_ref()) { + base::Optional<URLPattern> pattern = + ParseRuntimePermissionsPattern(params->host); + if (!pattern) return RespondNow(Error(kInvalidHost)); - } const Extension* extension = GetExtensionById(params->extension_id); if (!extension) @@ -2021,10 +2037,18 @@ if (!scripting_modifier.CanAffectExtension()) return RespondNow(Error(kCannotChangeHostPermissions)); - if (!scripting_modifier.HasGrantedHostPermission(host)) + URLPatternSet host_permissions_to_remove({*pattern}); + std::unique_ptr<const PermissionSet> permissions_to_remove = + PermissionSet::CreateIntersection( + PermissionSet(APIPermissionSet(), ManifestPermissionSet(), + host_permissions_to_remove, host_permissions_to_remove), + *scripting_modifier.GetRevokablePermissions(), + URLPatternSet::IntersectionBehavior::kDetailed); + if (permissions_to_remove->IsEmpty()) return RespondNow(Error("Cannot remove a host that hasn't been granted.")); - scripting_modifier.RemoveGrantedHostPermission(host); + PermissionsUpdater(browser_context()) + .RevokeRuntimePermissions(*extension, *permissions_to_remove); return RespondNow(NoArguments()); }
diff --git a/chrome/browser/extensions/api/developer_private/developer_private_api_unittest.cc b/chrome/browser/extensions/api/developer_private/developer_private_api_unittest.cc index dc072d6..f5af643 100644 --- a/chrome/browser/extensions/api/developer_private/developer_private_api_unittest.cc +++ b/chrome/browser/extensions/api/developer_private/developer_private_api_unittest.cc
@@ -62,6 +62,7 @@ #include "extensions/common/extension_set.h" #include "extensions/common/manifest_constants.h" #include "extensions/common/permissions/permission_set.h" +#include "extensions/common/permissions/permissions_data.h" #include "extensions/common/value_builder.h" #include "extensions/test/test_extension_dir.h" #include "services/data_decoder/data_decoder_service.h" @@ -1346,19 +1347,33 @@ } }; - GURL host("https://example.com"); - EXPECT_FALSE(modifier.HasGrantedHostPermission(host)); - run_add_host_permission(host.spec(), true, nullptr); + const GURL kExampleCom("https://example.com/"); + EXPECT_FALSE(modifier.HasGrantedHostPermission(kExampleCom)); + run_add_host_permission("https://example.com/*", true, nullptr); + EXPECT_TRUE(modifier.HasGrantedHostPermission(kExampleCom)); + + const GURL kGoogleCom("https://google.com"); + const GURL kMapsGoogleCom("https://maps.google.com/"); + EXPECT_FALSE(modifier.HasGrantedHostPermission(kGoogleCom)); + EXPECT_FALSE(modifier.HasGrantedHostPermission(kMapsGoogleCom)); + run_add_host_permission("https://*.google.com/*", true, nullptr); + EXPECT_TRUE(modifier.HasGrantedHostPermission(kGoogleCom)); + EXPECT_TRUE(modifier.HasGrantedHostPermission(kMapsGoogleCom)); run_add_host_permission(kInvalidHost, false, kInvalidHostError); + // Path of the pattern must exactly match "/*". + run_add_host_permission("https://example.com/", false, kInvalidHostError); run_add_host_permission("https://example.com/foobar", false, kInvalidHostError); run_add_host_permission("https://example.com/#foobar", false, kInvalidHostError); + run_add_host_permission("https://example.com/*foobar", false, + kInvalidHostError); - GURL chrome_host("chrome://settings"); - run_add_host_permission(chrome_host.spec(), false, - "Cannot grant a permission that wasn't withheld."); + // Cannot grant chrome:-scheme URLs. + GURL chrome_host("chrome://settings/*"); + run_add_host_permission(chrome_host.spec(), false, kInvalidHostError); + EXPECT_FALSE(modifier.HasGrantedHostPermission(chrome_host)); } @@ -1391,22 +1406,41 @@ } }; - GURL host("https://example.com"); - run_remove_host_permission(host.spec(), false, + run_remove_host_permission("https://example.com/*", false, "Cannot remove a host that hasn't been granted."); - modifier.GrantHostPermission(host); - EXPECT_TRUE(modifier.HasGrantedHostPermission(host)); + const GURL kExampleCom("https://example.com"); + modifier.GrantHostPermission(kExampleCom); + EXPECT_TRUE(modifier.HasGrantedHostPermission(kExampleCom)); + // Path of the pattern must exactly match "/*". + run_remove_host_permission("https://example.com/", false, kInvalidHostError); run_remove_host_permission("https://example.com/foobar", false, kInvalidHostError); run_remove_host_permission("https://example.com/#foobar", false, kInvalidHostError); + run_remove_host_permission("https://example.com/*foobar", false, + kInvalidHostError); run_remove_host_permission(kInvalidHost, false, kInvalidHostError); - EXPECT_TRUE(modifier.HasGrantedHostPermission(host)); + EXPECT_TRUE(modifier.HasGrantedHostPermission(kExampleCom)); - run_remove_host_permission(host.spec(), true, nullptr); - EXPECT_FALSE(modifier.HasGrantedHostPermission(host)); + run_remove_host_permission("https://example.com/*", true, nullptr); + EXPECT_FALSE(modifier.HasGrantedHostPermission(kExampleCom)); + + URLPattern new_pattern(Extension::kValidHostPermissionSchemes, + "https://*.google.com/*"); + PermissionsUpdater(profile()).GrantRuntimePermissions( + *extension, PermissionSet(APIPermissionSet(), ManifestPermissionSet(), + URLPatternSet({new_pattern}), URLPatternSet())); + + const GURL kGoogleCom("https://google.com/"); + const GURL kMapsGoogleCom("https://maps.google.com/"); + EXPECT_TRUE(modifier.HasGrantedHostPermission(kGoogleCom)); + EXPECT_TRUE(modifier.HasGrantedHostPermission(kMapsGoogleCom)); + + run_remove_host_permission("https://*.google.com/*", true, nullptr); + EXPECT_FALSE(modifier.HasGrantedHostPermission(kGoogleCom)); + EXPECT_FALSE(modifier.HasGrantedHostPermission(kMapsGoogleCom)); } TEST_F(DeveloperPrivateApiUnitTest, UpdateHostAccess) { @@ -1499,6 +1533,71 @@ EXPECT_FALSE(modifier.HasGrantedHostPermission(example_com)); } +TEST_F(DeveloperPrivateApiUnitTest, + UpdateHostAccess_GrantScopeGreaterThanRequestedScope) { + base::test::ScopedFeatureList feature_list; + feature_list.InitAndEnableFeature(features::kRuntimeHostPermissions); + + scoped_refptr<const Extension> extension = + ExtensionBuilder("test").AddPermission("http://*/*").Build(); + service()->AddExtension(extension.get()); + ScriptingPermissionsModifier modifier(profile(), extension.get()); + modifier.SetWithholdHostPermissions(true); + + ExtensionPrefs* extension_prefs = ExtensionPrefs::Get(profile()); + EXPECT_EQ(PermissionSet(), + extension->permissions_data()->active_permissions()); + EXPECT_EQ(PermissionSet(), + *extension_prefs->GetRuntimeGrantedPermissions(extension->id())); + + { + scoped_refptr<UIThreadExtensionFunction> function = + base::MakeRefCounted<api::DeveloperPrivateAddHostPermissionFunction>(); + std::string args = base::StringPrintf( + R"(["%s", "%s"])", extension->id().c_str(), "*://chromium.org/*"); + EXPECT_TRUE(api_test_utils::RunFunction(function.get(), args, profile())) + << function->GetError(); + } + + // The active permissions (which are given to the extension process) should + // only include the intersection of what was requested by the extension and + // the runtime granted permissions - which is http://chromium.org/*. + URLPattern http_chromium(Extension::kValidHostPermissionSchemes, + "http://chromium.org/*"); + const PermissionSet http_chromium_set( + APIPermissionSet(), ManifestPermissionSet(), + URLPatternSet({http_chromium}), URLPatternSet()); + EXPECT_EQ(http_chromium_set, + extension->permissions_data()->active_permissions()); + + // The runtime granted permissions should include all of what was approved by + // the user, which is *://chromium.org/*, and should be present in both the + // scriptable and explicit hosts. + URLPattern all_chromium(Extension::kValidHostPermissionSchemes, + "*://chromium.org/*"); + const PermissionSet all_chromium_set( + APIPermissionSet(), ManifestPermissionSet(), + URLPatternSet({all_chromium}), URLPatternSet({all_chromium})); + EXPECT_EQ(all_chromium_set, + *extension_prefs->GetRuntimeGrantedPermissions(extension->id())); + + { + scoped_refptr<UIThreadExtensionFunction> function = base::MakeRefCounted< + api::DeveloperPrivateRemoveHostPermissionFunction>(); + std::string args = base::StringPrintf( + R"(["%s", "%s"])", extension->id().c_str(), "*://chromium.org/*"); + EXPECT_TRUE(api_test_utils::RunFunction(function.get(), args, profile())) + << function->GetError(); + } + + // Removing the granted permission should remove it entirely from both + // the active and the stored permissions. + EXPECT_EQ(PermissionSet(), + extension->permissions_data()->active_permissions()); + EXPECT_EQ(PermissionSet(), + *extension_prefs->GetRuntimeGrantedPermissions(extension->id())); +} + TEST_F(DeveloperPrivateApiUnitTest, ExtensionUpdatedEventOnPermissionsChange) { DeveloperPrivateAPI::Get(profile()); const ExtensionId listener_id = crx_file::id_util::GenerateId("listener");
diff --git a/chrome/browser/extensions/api/developer_private/extension_info_generator.cc b/chrome/browser/extensions/api/developer_private/extension_info_generator.cc index 98edfbd..d1753118 100644 --- a/chrome/browser/extensions/api/developer_private/extension_info_generator.cc +++ b/chrome/browser/extensions/api/developer_private/extension_info_generator.cc
@@ -273,24 +273,33 @@ if (!permissions_modifier.HasWithheldHostPermissions()) { permissions->host_access = developer::HOST_ACCESS_ON_ALL_SITES; } else { - constexpr bool include_rcd = true; - constexpr bool exclude_file_scheme = true; - std::set<std::string> distinct_hosts = - permission_message_util::GetDistinctHosts( - active_permissions.effective_hosts(), include_rcd, - exclude_file_scheme); - // TODO(devlin): This isn't quite right - it's possible the user just - // selected "on specific sites" from the dropdown, and hasn't yet added - // any sites. We'll need to handle this. - // https://crbug.com/844128. - if (!distinct_hosts.empty()) { + ExtensionPrefs* extension_prefs = ExtensionPrefs::Get(browser_context); + std::unique_ptr<const PermissionSet> runtime_granted_permissions = + extension_prefs->GetRuntimeGrantedPermissions(extension.id()); + if (runtime_granted_permissions->effective_hosts().is_empty()) { + // TODO(devlin): This isn't quite right - it's possible the user just + // selected "on specific sites" from the dropdown, and hasn't yet added + // any sites. We'll need to handle this. + // https://crbug.com/844128. + permissions->host_access = developer::HOST_ACCESS_ON_CLICK; + } else { permissions->host_access = developer::HOST_ACCESS_ON_SPECIFIC_SITES; + std::set<std::string> distinct_hosts; + for (auto pattern : runtime_granted_permissions->effective_hosts()) { + // We only allow addition/removal of full hosts (since from a + // permissions point of view, path is irrelevant). We always make the + // path wildcard when adding through this UI, but the optional + // permissions API may allow adding permissions with paths. + // TODO(devlin): Investigate, and possibly change the optional + // permissions API. + pattern.SetPath("/*"); + distinct_hosts.insert(pattern.GetAsString()); + } + permissions->runtime_host_permissions = std::make_unique<std::vector<std::string>>( std::make_move_iterator(distinct_hosts.begin()), std::make_move_iterator(distinct_hosts.end())); - } else { - permissions->host_access = developer::HOST_ACCESS_ON_CLICK; } } }
diff --git a/chrome/browser/extensions/api/developer_private/extension_info_generator_unittest.cc b/chrome/browser/extensions/api/developer_private/extension_info_generator_unittest.cc index a8184d3e9..9d8496f 100644 --- a/chrome/browser/extensions/api/developer_private/extension_info_generator_unittest.cc +++ b/chrome/browser/extensions/api/developer_private/extension_info_generator_unittest.cc
@@ -36,7 +36,10 @@ #include "extensions/common/extension_features.h" #include "extensions/common/feature_switch.h" #include "extensions/common/permissions/permission_message.h" +#include "extensions/common/permissions/permission_set.h" #include "extensions/common/permissions/permissions_data.h" +#include "extensions/common/url_pattern.h" +#include "extensions/common/url_pattern_set.h" #include "extensions/common/value_builder.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -430,7 +433,7 @@ info->permissions.host_access); ASSERT_TRUE(info->permissions.runtime_host_permissions); EXPECT_THAT(*info->permissions.runtime_host_permissions, - testing::UnorderedElementsAre("example.com")); + testing::UnorderedElementsAre("https://example.com/*")); EXPECT_THAT(info->permissions.simple_permissions, testing::IsEmpty()); // An extension that doesn't request any host permissions should not have @@ -457,6 +460,50 @@ info->permissions.simple_permissions[0].message); } +// Tests that runtime_host_permissions is correctly populated when permissions +// are granted by the user beyond what the extension originally requested in the +// manifest. +TEST_F(ExtensionInfoGeneratorUnitTest, + RuntimeHostPermissionsBeyondRequestedScope) { + base::test::ScopedFeatureList feature_list; + feature_list.InitAndEnableFeature(features::kRuntimeHostPermissions); + + scoped_refptr<const Extension> extension = + CreateExtension("extension", ListBuilder().Append("http://*/*").Build(), + Manifest::INTERNAL); + + std::unique_ptr<developer::ExtensionInfo> info = + GenerateExtensionInfo(extension->id()); + + // Withhold permissions, and grant *://chromium.org/*. + ScriptingPermissionsModifier permissions_modifier(profile(), extension); + permissions_modifier.SetWithholdHostPermissions(true); + URLPattern all_chromium(Extension::kValidHostPermissionSchemes, + "*://chromium.org/*"); + PermissionSet all_chromium_set(APIPermissionSet(), ManifestPermissionSet(), + URLPatternSet({all_chromium}), + URLPatternSet({all_chromium})); + PermissionsUpdater(profile()).GrantRuntimePermissions(*extension, + all_chromium_set); + + // The extension should only be granted http://chromium.org/* (since that's + // the intersection with what it requested). + URLPattern http_chromium(Extension::kValidHostPermissionSchemes, + "http://chromium.org/*"); + EXPECT_EQ(PermissionSet(APIPermissionSet(), ManifestPermissionSet(), + URLPatternSet({http_chromium}), URLPatternSet()), + extension->permissions_data()->active_permissions()); + + // The generated info should use the entirety of the granted permission, + // which is *://chromium.org/*. + info = GenerateExtensionInfo(extension->id()); + EXPECT_EQ(developer::HOST_ACCESS_ON_SPECIFIC_SITES, + info->permissions.host_access); + ASSERT_TRUE(info->permissions.runtime_host_permissions); + EXPECT_THAT(*info->permissions.runtime_host_permissions, + testing::UnorderedElementsAre("*://chromium.org/*")); +} + // Test that file:// access checkbox does not show up when the user can't // modify an extension's settings. https://crbug.com/173640. TEST_F(ExtensionInfoGeneratorUnitTest, ExtensionInfoLockedAllUrls) {
diff --git a/chrome/browser/extensions/chrome_extensions_browser_api_provider.cc b/chrome/browser/extensions/chrome_extensions_browser_api_provider.cc new file mode 100644 index 0000000..133585d --- /dev/null +++ b/chrome/browser/extensions/chrome_extensions_browser_api_provider.cc
@@ -0,0 +1,29 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/extensions/chrome_extensions_browser_api_provider.h" + +#include "chrome/browser/extensions/api/generated_api_registration.h" +#include "chrome/browser/extensions/api/preference/preference_api.h" +#include "extensions/browser/extension_function_registry.h" + +namespace extensions { + +ChromeExtensionsBrowserAPIProvider::ChromeExtensionsBrowserAPIProvider() = + default; +ChromeExtensionsBrowserAPIProvider::~ChromeExtensionsBrowserAPIProvider() = + default; + +void ChromeExtensionsBrowserAPIProvider::RegisterExtensionFunctions( + ExtensionFunctionRegistry* registry) { + // Preferences. + registry->RegisterFunction<GetPreferenceFunction>(); + registry->RegisterFunction<SetPreferenceFunction>(); + registry->RegisterFunction<ClearPreferenceFunction>(); + + // Generated APIs from Chrome. + api::ChromeGeneratedFunctionRegistry::RegisterAll(registry); +} + +} // namespace extensions
diff --git a/chrome/browser/extensions/chrome_extensions_browser_api_provider.h b/chrome/browser/extensions/chrome_extensions_browser_api_provider.h new file mode 100644 index 0000000..42a5fa5a --- /dev/null +++ b/chrome/browser/extensions/chrome_extensions_browser_api_provider.h
@@ -0,0 +1,26 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_EXTENSIONS_CHROME_EXTENSIONS_BROWSER_API_PROVIDER_H_ +#define CHROME_BROWSER_EXTENSIONS_CHROME_EXTENSIONS_BROWSER_API_PROVIDER_H_ + +#include "base/macros.h" +#include "extensions/browser/extensions_browser_api_provider.h" + +namespace extensions { + +class ChromeExtensionsBrowserAPIProvider : public ExtensionsBrowserAPIProvider { + public: + ChromeExtensionsBrowserAPIProvider(); + ~ChromeExtensionsBrowserAPIProvider() override; + + void RegisterExtensionFunctions(ExtensionFunctionRegistry* registry) override; + + private: + DISALLOW_COPY_AND_ASSIGN(ChromeExtensionsBrowserAPIProvider); +}; + +} // namespace extensions + +#endif // CHROME_BROWSER_EXTENSIONS_CHROME_EXTENSIONS_BROWSER_API_PROVIDER_H_
diff --git a/chrome/browser/extensions/chrome_extensions_browser_client.cc b/chrome/browser/extensions/chrome_extensions_browser_client.cc index ec40a5a..d225d09 100644 --- a/chrome/browser/extensions/chrome_extensions_browser_client.cc +++ b/chrome/browser/extensions/chrome_extensions_browser_client.cc
@@ -15,13 +15,12 @@ #include "chrome/browser/extensions/activity_log/activity_log.h" #include "chrome/browser/extensions/api/chrome_extensions_api_client.h" #include "chrome/browser/extensions/api/content_settings/content_settings_service.h" -#include "chrome/browser/extensions/api/generated_api_registration.h" -#include "chrome/browser/extensions/api/preference/preference_api.h" #include "chrome/browser/extensions/api/runtime/chrome_runtime_api_delegate.h" #include "chrome/browser/extensions/chrome_component_extension_resource_manager.h" #include "chrome/browser/extensions/chrome_extension_api_frame_id_map_helper.h" #include "chrome/browser/extensions/chrome_extension_host_delegate.h" #include "chrome/browser/extensions/chrome_extension_web_contents_observer.h" +#include "chrome/browser/extensions/chrome_extensions_browser_api_provider.h" #include "chrome/browser/extensions/chrome_extensions_interface_registration.h" #include "chrome/browser/extensions/chrome_kiosk_delegate.h" #include "chrome/browser/extensions/chrome_process_manager_delegate.h" @@ -51,8 +50,7 @@ #include "content/public/browser/render_process_host.h" #include "content/public/browser/resource_request_info.h" #include "content/public/common/content_switches.h" -#include "extensions/browser/api/generated_api_registration.h" -#include "extensions/browser/extension_function_registry.h" +#include "extensions/browser/core_extensions_browser_api_provider.h" #include "extensions/browser/extension_prefs.h" #include "extensions/browser/extension_system.h" #include "extensions/browser/extension_util.h" @@ -88,6 +86,9 @@ } // namespace ChromeExtensionsBrowserClient::ChromeExtensionsBrowserClient() { + AddAPIProvider(std::make_unique<CoreExtensionsBrowserAPIProvider>()); + AddAPIProvider(std::make_unique<ChromeExtensionsBrowserAPIProvider>()); + process_manager_delegate_.reset(new ChromeProcessManagerDelegate); api_client_.reset(new ChromeExtensionsAPIClient); SetCurrentChannel(chrome::GetChannel()); @@ -324,20 +325,6 @@ return ExtensionSystemFactory::GetInstance(); } -void ChromeExtensionsBrowserClient::RegisterExtensionFunctions( - ExtensionFunctionRegistry* registry) const { - // Preferences. - registry->RegisterFunction<GetPreferenceFunction>(); - registry->RegisterFunction<SetPreferenceFunction>(); - registry->RegisterFunction<ClearPreferenceFunction>(); - - // Generated APIs from lower-level modules. - api::GeneratedFunctionRegistry::RegisterAll(registry); - - // Generated APIs from Chrome. - api::ChromeGeneratedFunctionRegistry::RegisterAll(registry); -} - void ChromeExtensionsBrowserClient::RegisterExtensionInterfaces( service_manager::BinderRegistryWithArgs<content::RenderFrameHost*>* registry,
diff --git a/chrome/browser/extensions/chrome_extensions_browser_client.h b/chrome/browser/extensions/chrome_extensions_browser_client.h index 87658e0a..0c13d34 100644 --- a/chrome/browser/extensions/chrome_extensions_browser_client.h +++ b/chrome/browser/extensions/chrome_extensions_browser_client.h
@@ -105,8 +105,6 @@ bool IsAppModeForcedForApp(const ExtensionId& extension_id) override; bool IsLoggedInAsPublicAccount() override; ExtensionSystemProvider* GetExtensionSystemFactory() override; - void RegisterExtensionFunctions( - ExtensionFunctionRegistry* registry) const override; void RegisterExtensionInterfaces(service_manager::BinderRegistryWithArgs< content::RenderFrameHost*>* registry, content::RenderFrameHost* render_frame_host,
diff --git a/chrome/browser/extensions/crx_installer.cc b/chrome/browser/extensions/crx_installer.cc index af204648..62316c3 100644 --- a/chrome/browser/extensions/crx_installer.cc +++ b/chrome/browser/extensions/crx_installer.cc
@@ -143,8 +143,9 @@ approved_ = true; expected_manifest_check_level_ = approval->manifest_check_level; if (expected_manifest_check_level_ != - WebstoreInstaller::MANIFEST_CHECK_LEVEL_NONE) - expected_manifest_.reset(approval->manifest->DeepCopy()); + WebstoreInstaller::MANIFEST_CHECK_LEVEL_NONE) { + expected_manifest_ = approval->manifest->CreateDeepCopy(); + } expected_id_ = approval->extension_id; } if (approval->minimum_version.get())
diff --git a/chrome/browser/geolocation/geolocation_permission_context_extensions.cc b/chrome/browser/geolocation/geolocation_permission_context_extensions.cc index cecf90c..8ec22415 100644 --- a/chrome/browser/geolocation/geolocation_permission_context_extensions.cc +++ b/chrome/browser/geolocation/geolocation_permission_context_extensions.cc
@@ -86,8 +86,9 @@ } } - if (extensions::GetViewType(web_contents) != - extensions::VIEW_TYPE_TAB_CONTENTS) { + extensions::ViewType view_type = extensions::GetViewType(web_contents); + if (view_type != extensions::VIEW_TYPE_TAB_CONTENTS && + view_type != extensions::VIEW_TYPE_INVALID) { // The tab may have gone away, or the request may not be from a tab at all. // TODO(mpcomplete): the request could be from a background page or // extension popup (web_contents will have a different ViewType). But why do
diff --git a/chrome/browser/google/google_search_domain_mixing_metrics_emitter.cc b/chrome/browser/google/google_search_domain_mixing_metrics_emitter.cc index 5df162b..1b27a7f 100644 --- a/chrome/browser/google/google_search_domain_mixing_metrics_emitter.cc +++ b/chrome/browser/google/google_search_domain_mixing_metrics_emitter.cc
@@ -4,6 +4,7 @@ #include "chrome/browser/google/google_search_domain_mixing_metrics_emitter.h" +#include "base/logging.h" #include "base/threading/thread_task_runner_handle.h" #include "components/history/core/browser/domain_mixing_metrics.h" #include "components/history/core/browser/history_backend.h" @@ -52,7 +53,9 @@ : prefs_(prefs), history_service_(history_service), ui_thread_task_runner_(content::BrowserThread::GetTaskRunnerForThread( - content::BrowserThread::UI)) {} + content::BrowserThread::UI)) { + DCHECK(history_service_); +} GoogleSearchDomainMixingMetricsEmitter:: ~GoogleSearchDomainMixingMetricsEmitter() {}
diff --git a/chrome/browser/google/google_search_domain_mixing_metrics_emitter_factory.cc b/chrome/browser/google/google_search_domain_mixing_metrics_emitter_factory.cc index 7d6c8c3..a53f698 100644 --- a/chrome/browser/google/google_search_domain_mixing_metrics_emitter_factory.cc +++ b/chrome/browser/google/google_search_domain_mixing_metrics_emitter_factory.cc
@@ -43,9 +43,12 @@ GoogleSearchDomainMixingMetricsEmitterFactory::BuildServiceInstanceFor( content::BrowserContext* context) const { Profile* profile = Profile::FromBrowserContext(context); + auto* history_service = HistoryServiceFactory::GetInstance()->GetForProfile( + profile, ServiceAccessType::IMPLICIT_ACCESS); + if (history_service == nullptr) + return nullptr; auto emitter = std::make_unique<GoogleSearchDomainMixingMetricsEmitter>( - profile->GetPrefs(), HistoryServiceFactory::GetInstance()->GetForProfile( - profile, ServiceAccessType::IMPLICIT_ACCESS)); + profile->GetPrefs(), history_service); emitter->Start(); return emitter.release(); }
diff --git a/chrome/browser/page_load_metrics/observers/core_page_load_metrics_observer.cc b/chrome/browser/page_load_metrics/observers/core_page_load_metrics_observer.cc index dce4c94..b310a40 100644 --- a/chrome/browser/page_load_metrics/observers/core_page_load_metrics_observer.cc +++ b/chrome/browser/page_load_metrics/observers/core_page_load_metrics_observer.cc
@@ -233,6 +233,10 @@ "PageLoad.Experimental.InputTiming.InputToNavigationStart"; const char kBackgroundHistogramInputToNavigation[] = "PageLoad.Experimental.InputTiming.InputToNavigationStart.Background"; +const char kHistogramInputToNavigationLinkClick[] = + "PageLoad.Experimental.InputTiming.InputToNavigationStart.FromLinkClick"; +const char kHistogramInputToNavigationOmnibox[] = + "PageLoad.Experimental.InputTiming.InputToNavigationStart.FromOmnibox"; const char kHistogramInputToFirstPaint[] = "PageLoad.Experimental.PaintTiming.InputToFirstPaint"; const char kBackgroundHistogramInputToFirstPaint[] = @@ -408,6 +412,17 @@ internal::kHistogramInputToFirstContentfulPaint, timing.input_to_navigation_start.value() + timing.paint_timing->first_contentful_paint.value()); + + if (ui::PageTransitionCoreTypeIs(transition_, ui::PAGE_TRANSITION_LINK)) { + PAGE_LOAD_HISTOGRAM(internal::kHistogramInputToNavigationLinkClick, + timing.input_to_navigation_start.value()); + } else if (ui::PageTransitionCoreTypeIs(transition_, + ui::PAGE_TRANSITION_GENERATED) || + ui::PageTransitionCoreTypeIs(transition_, + ui::PAGE_TRANSITION_TYPED)) { + PAGE_LOAD_HISTOGRAM(internal::kHistogramInputToNavigationOmnibox, + timing.input_to_navigation_start.value()); + } } switch (GetPageLoadType(transition_)) {
diff --git a/chrome/browser/page_load_metrics/observers/core_page_load_metrics_observer.h b/chrome/browser/page_load_metrics/observers/core_page_load_metrics_observer.h index 4c30692..c9bd586 100644 --- a/chrome/browser/page_load_metrics/observers/core_page_load_metrics_observer.h +++ b/chrome/browser/page_load_metrics/observers/core_page_load_metrics_observer.h
@@ -82,6 +82,8 @@ extern const char kHistogramInputToNavigation[]; extern const char kBackgroundHistogramInputToNavigation[]; +extern const char kHistogramInputToNavigationLinkClick[]; +extern const char kHistogramInputToNavigationOmnibox[]; extern const char kHistogramInputToFirstPaint[]; extern const char kBackgroundHistogramInputToFirstPaint[]; extern const char kHistogramInputToFirstContentfulPaint[];
diff --git a/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc b/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc index e314777..1e6ab3f 100644 --- a/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc +++ b/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc
@@ -1959,6 +1959,8 @@ waiter->Wait(); histogram_tester_.ExpectTotalCount(internal::kHistogramInputToNavigation, 1); + histogram_tester_.ExpectTotalCount( + internal::kHistogramInputToNavigationLinkClick, 1); histogram_tester_.ExpectTotalCount(internal::kHistogramInputToFirstPaint, 1); histogram_tester_.ExpectTotalCount( internal::kHistogramInputToFirstContentfulPaint, 1);
diff --git a/chrome/browser/permissions/permission_manager_unittest.cc b/chrome/browser/permissions/permission_manager_unittest.cc index 8832ac6..e1b9195 100644 --- a/chrome/browser/permissions/permission_manager_unittest.cc +++ b/chrome/browser/permissions/permission_manager_unittest.cc
@@ -22,9 +22,12 @@ #include "chrome/test/base/testing_profile.h" #include "components/content_settings/core/browser/host_content_settings_map.h" #include "content/public/browser/permission_type.h" +#include "content/public/test/navigation_simulator.h" #include "content/public/test/test_browser_thread_bundle.h" +#include "content/public/test/test_renderer_host.h" #include "device/vr/buildflags/buildflags.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom.h" #if defined(OS_ANDROID) #include "chrome/browser/android/chrome_feature_list.h" @@ -58,6 +61,8 @@ class PermissionManagerTest : public ChromeRenderViewHostTestHarness { public: void OnPermissionChange(PermissionStatus permission) { + if (!quit_closure_.is_null()) + quit_closure_.Run(); callback_called_ = true; callback_result_ = permission; } @@ -98,6 +103,19 @@ ->SetContentSettingDefaultScope(url_, url_, type, std::string(), value); } + int RequestPermission(PermissionType type, + content::RenderFrameHost* rfh, + const GURL& origin) { + base::RunLoop loop; + quit_closure_ = loop.QuitClosure(); + int result = GetPermissionControllerDelegate()->RequestPermission( + type, rfh, origin, true, + base::Bind(&PermissionManagerTest::OnPermissionChange, + base::Unretained(this))); + loop.Run(); + return result; + } + const GURL& url() const { return url_; } @@ -125,6 +143,31 @@ return GetPermissionControllerDelegate()->pending_requests_.IsEmpty(); } + // The header policy should only be set once on page load, so we refresh the + // page to simulate that. + void RefreshPageAndSetHeaderPolicy(content::RenderFrameHost** rfh, + blink::mojom::FeaturePolicyFeature feature, + const std::vector<std::string>& origins) { + content::RenderFrameHost* current = *rfh; + SimulateNavigation(¤t, current->GetLastCommittedURL()); + std::vector<url::Origin> parsed_origins; + for (const std::string& origin : origins) + parsed_origins.push_back(url::Origin::Create(GURL(origin))); + content::RenderFrameHostTester::For(current)->SimulateFeaturePolicyHeader( + feature, parsed_origins); + *rfh = current; + } + + content::RenderFrameHost* AddChildRFH(content::RenderFrameHost* parent, + const char* origin) { + content::RenderFrameHost* result = + content::RenderFrameHostTester::For(parent)->AppendChild(""); + content::RenderFrameHostTester::For(result) + ->InitializeRenderFrameIfNeeded(); + SimulateNavigation(&result, GURL(origin)); + return result; + } + private: void SetUp() override { ChromeRenderViewHostTestHarness::SetUp(); @@ -148,10 +191,18 @@ ChromeRenderViewHostTestHarness::TearDown(); } + void SimulateNavigation(content::RenderFrameHost** rfh, const GURL& url) { + auto navigation_simulator = + content::NavigationSimulator::CreateRendererInitiated(url, *rfh); + navigation_simulator->Commit(); + *rfh = navigation_simulator->GetFinalRenderFrameHost(); + } + const GURL url_; const GURL other_url_; bool callback_called_; PermissionStatus callback_result_; + base::Closure quit_closure_; std::unique_ptr<PermissionManagerTestingProfile> profile_; }; @@ -487,29 +538,20 @@ NavigateAndCommit(url()); SetPermission(CONTENT_SETTINGS_TYPE_NOTIFICATIONS, CONTENT_SETTING_ALLOW); - GetPermissionControllerDelegate()->RequestPermission( - PermissionType::NOTIFICATIONS, main_rfh(), url(), true, - base::Bind(&PermissionManagerTest::OnPermissionChange, - base::Unretained(this))); + RequestPermission(PermissionType::NOTIFICATIONS, main_rfh(), url()); EXPECT_TRUE(callback_called()); EXPECT_EQ(PermissionStatus::GRANTED, callback_result()); vr::VrTabHelper* vr_tab_helper = vr::VrTabHelper::FromWebContents(contents); vr_tab_helper->SetIsInVr(true); - EXPECT_EQ( - kNoPendingOperation, - GetPermissionControllerDelegate()->RequestPermission( - PermissionType::NOTIFICATIONS, contents->GetMainFrame(), url(), false, - base::Bind(&PermissionManagerTest::OnPermissionChange, - base::Unretained(this)))); + EXPECT_EQ(kNoPendingOperation, + RequestPermission(PermissionType::NOTIFICATIONS, + contents->GetMainFrame(), url())); EXPECT_TRUE(callback_called()); EXPECT_EQ(PermissionStatus::DENIED, callback_result()); vr_tab_helper->SetIsInVr(false); - GetPermissionControllerDelegate()->RequestPermission( - PermissionType::NOTIFICATIONS, main_rfh(), url(), false, - base::Bind(&PermissionManagerTest::OnPermissionChange, - base::Unretained(this))); + RequestPermission(PermissionType::NOTIFICATIONS, main_rfh(), url()); EXPECT_TRUE(callback_called()); EXPECT_EQ(PermissionStatus::GRANTED, callback_result()); #endif @@ -625,3 +667,98 @@ extensions_requesting_origin, embedding_origin)); } } + +TEST_F(PermissionManagerTest, GetPermissionStatusDelegation) { + const char* kOrigin1 = "https://example.com"; + const char* kOrigin2 = "https://google.com"; + + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitAndEnableFeature(features::kPermissionDelegation); + + NavigateAndCommit(GURL(kOrigin1)); + content::RenderFrameHost* parent = main_rfh(); + + content::RenderFrameHost* child = AddChildRFH(parent, kOrigin2); + + // By default the parent should be able to request access, but not the child. + EXPECT_EQ(CONTENT_SETTING_ASK, + GetPermissionControllerDelegate() + ->GetPermissionStatusForFrame(CONTENT_SETTINGS_TYPE_GEOLOCATION, + parent, GURL(kOrigin1)) + .content_setting); + EXPECT_EQ(CONTENT_SETTING_BLOCK, + GetPermissionControllerDelegate() + ->GetPermissionStatusForFrame(CONTENT_SETTINGS_TYPE_GEOLOCATION, + child, GURL(kOrigin2)) + .content_setting); + + // Enabling geolocation by FP should allow the child to request access also. + RefreshPageAndSetHeaderPolicy( + &parent, blink::mojom::FeaturePolicyFeature::kGeolocation, + {kOrigin1, kOrigin2}); + child = AddChildRFH(parent, kOrigin2); + + EXPECT_EQ(CONTENT_SETTING_ASK, + GetPermissionControllerDelegate() + ->GetPermissionStatusForFrame(CONTENT_SETTINGS_TYPE_GEOLOCATION, + child, GURL(kOrigin2)) + .content_setting); + + // When the child requests location a prompt should be displayed for the + // parent. + PermissionRequestManager::CreateForWebContents(web_contents()); + PermissionRequestManager* manager = + PermissionRequestManager::FromWebContents(web_contents()); + auto prompt_factory = std::make_unique<MockPermissionPromptFactory>(manager); + prompt_factory->set_response_type(PermissionRequestManager::ACCEPT_ALL); + prompt_factory->DocumentOnLoadCompletedInMainFrame(); + + RequestPermission(PermissionType::GEOLOCATION, child, GURL(kOrigin2)); + + EXPECT_TRUE(prompt_factory->RequestOriginSeen(GURL(kOrigin1))); + + // Now the child frame should have location, as well as the parent frame. + EXPECT_EQ(CONTENT_SETTING_ALLOW, + GetPermissionControllerDelegate() + ->GetPermissionStatusForFrame(CONTENT_SETTINGS_TYPE_GEOLOCATION, + parent, GURL(kOrigin1)) + .content_setting); + EXPECT_EQ(CONTENT_SETTING_ALLOW, + GetPermissionControllerDelegate() + ->GetPermissionStatusForFrame(CONTENT_SETTINGS_TYPE_GEOLOCATION, + child, GURL(kOrigin2)) + .content_setting); + + // Revoking access from the parent should cause the child not to have access + // either. + GetPermissionControllerDelegate()->ResetPermission( + PermissionType::GEOLOCATION, GURL(kOrigin1), GURL(kOrigin1)); + EXPECT_EQ(CONTENT_SETTING_ASK, + GetPermissionControllerDelegate() + ->GetPermissionStatusForFrame(CONTENT_SETTINGS_TYPE_GEOLOCATION, + parent, GURL(kOrigin1)) + .content_setting); + EXPECT_EQ(CONTENT_SETTING_ASK, + GetPermissionControllerDelegate() + ->GetPermissionStatusForFrame(CONTENT_SETTINGS_TYPE_GEOLOCATION, + child, GURL(kOrigin2)) + .content_setting); + + // If the parent changes its policy, the child should be blocked. + RefreshPageAndSetHeaderPolicy( + &parent, blink::mojom::FeaturePolicyFeature::kGeolocation, {kOrigin1}); + child = AddChildRFH(parent, kOrigin2); + + EXPECT_EQ(CONTENT_SETTING_ASK, + GetPermissionControllerDelegate() + ->GetPermissionStatusForFrame(CONTENT_SETTINGS_TYPE_GEOLOCATION, + parent, GURL(kOrigin1)) + .content_setting); + EXPECT_EQ(CONTENT_SETTING_BLOCK, + GetPermissionControllerDelegate() + ->GetPermissionStatusForFrame(CONTENT_SETTINGS_TYPE_GEOLOCATION, + child, GURL(kOrigin2)) + .content_setting); + + prompt_factory.reset(); +}
diff --git a/chrome/browser/policy/configuration_policy_handler_list_factory.cc b/chrome/browser/policy/configuration_policy_handler_list_factory.cc index 3594ee5e..e87e5e8 100644 --- a/chrome/browser/policy/configuration_policy_handler_list_factory.cc +++ b/chrome/browser/policy/configuration_policy_handler_list_factory.cc
@@ -662,6 +662,9 @@ { key::kPowerSmartDimEnabled, ash::prefs::kPowerSmartDimEnabled, base::Value::Type::BOOLEAN }, + { key::kNetBiosShareDiscoveryEnabled, + prefs::kNetBiosShareDiscoveryEnabled, + base::Value::Type::BOOLEAN }, #endif // defined(OS_CHROMEOS) // Metrics reporting is controlled by a platform specific policy for ChromeOS
diff --git a/chrome/browser/previews/previews_ui_tab_helper.cc b/chrome/browser/previews/previews_ui_tab_helper.cc index 62c6405..e060e08b 100644 --- a/chrome/browser/previews/previews_ui_tab_helper.cc +++ b/chrome/browser/previews/previews_ui_tab_helper.cc
@@ -59,6 +59,9 @@ bool is_data_saver_user, bool is_reload, OnDismissPreviewsUICallback on_dismiss_callback) { + if (!web_contents()) + return; + // Retrieve PreviewsUIService* from |web_contents| if available. PreviewsService* previews_service = PreviewsServiceFactory::GetForProfile( Profile::FromBrowserContext(web_contents()->GetBrowserContext()));
diff --git a/chrome/browser/printing/print_preview_message_handler.cc b/chrome/browser/printing/print_preview_message_handler.cc index 607dea8..7f4f4dad7 100644 --- a/chrome/browser/printing/print_preview_message_handler.cc +++ b/chrome/browser/printing/print_preview_message_handler.cc
@@ -106,8 +106,8 @@ PrintPreviewUI::SetInitialParams(GetPrintPreviewDialog(), params); } -void PrintPreviewMessageHandler::OnDidGetPreviewPageCount( - const PrintHostMsg_DidGetPreviewPageCount_Params& params, +void PrintPreviewMessageHandler::OnDidStartPreview( + const PrintHostMsg_DidStartPreview_Params& params, const PrintHostMsg_PreviewIds& ids) { if (params.page_count <= 0) { NOTREACHED(); @@ -119,7 +119,7 @@ return; print_preview_ui->ClearAllPreviewData(); - print_preview_ui->OnDidGetPreviewPageCount(params, ids.request_id); + print_preview_ui->OnDidStartPreview(params, ids.request_id); } void PrintPreviewMessageHandler::OnDidPreviewPage( @@ -324,8 +324,7 @@ handled = true; IPC_BEGIN_MESSAGE_MAP(PrintPreviewMessageHandler, message) - IPC_MESSAGE_HANDLER(PrintHostMsg_DidGetPreviewPageCount, - OnDidGetPreviewPageCount) + IPC_MESSAGE_HANDLER(PrintHostMsg_DidStartPreview, OnDidStartPreview) IPC_MESSAGE_HANDLER(PrintHostMsg_PrintPreviewFailed, OnPrintPreviewFailed) IPC_MESSAGE_HANDLER(PrintHostMsg_DidGetDefaultPageLayout,
diff --git a/chrome/browser/printing/print_preview_message_handler.h b/chrome/browser/printing/print_preview_message_handler.h index ab4a96190..534f7e6 100644 --- a/chrome/browser/printing/print_preview_message_handler.h +++ b/chrome/browser/printing/print_preview_message_handler.h
@@ -13,9 +13,9 @@ #include "content/public/browser/web_contents_user_data.h" class PrintPreviewUI; -struct PrintHostMsg_DidGetPreviewPageCount_Params; struct PrintHostMsg_DidPreviewDocument_Params; struct PrintHostMsg_DidPreviewPage_Params; +struct PrintHostMsg_DidStartPreview_Params; struct PrintHostMsg_PreviewIds; struct PrintHostMsg_RequestPrintPreview_Params; struct PrintHostMsg_SetOptionsFromDocument_Params; @@ -69,9 +69,8 @@ const gfx::Rect& printable_area_in_points, bool has_custom_page_size_style, const PrintHostMsg_PreviewIds& ids); - void OnDidGetPreviewPageCount( - const PrintHostMsg_DidGetPreviewPageCount_Params& params, - const PrintHostMsg_PreviewIds& ids); + void OnDidStartPreview(const PrintHostMsg_DidStartPreview_Params& params, + const PrintHostMsg_PreviewIds& ids); void OnDidPreviewPage(content::RenderFrameHost* render_frame_host, const PrintHostMsg_DidPreviewPage_Params& params, const PrintHostMsg_PreviewIds& ids);
diff --git a/chrome/browser/printing/print_preview_pdf_generated_browsertest.cc b/chrome/browser/printing/print_preview_pdf_generated_browsertest.cc index 26f45ee..9e86ff0 100644 --- a/chrome/browser/printing/print_preview_pdf_generated_browsertest.cc +++ b/chrome/browser/printing/print_preview_pdf_generated_browsertest.cc
@@ -141,8 +141,7 @@ bool OnMessageReceived(const IPC::Message& message) override { IPC_BEGIN_MESSAGE_MAP(PrintPreviewObserver, message) - IPC_MESSAGE_HANDLER(PrintHostMsg_DidGetPreviewPageCount, - OnDidGetPreviewPageCount) + IPC_MESSAGE_HANDLER(PrintHostMsg_DidStartPreview, OnDidStartPreview) IPC_END_MESSAGE_MAP() return false; } @@ -268,11 +267,10 @@ DISALLOW_COPY_AND_ASSIGN(UIDoneLoadingMessageHandler); }; - // Called when the observer gets the IPC message stating that the page count - // is ready. - void OnDidGetPreviewPageCount( - const PrintHostMsg_DidGetPreviewPageCount_Params& params, - const PrintHostMsg_PreviewIds& ids) { + // Called when the observer gets the IPC message with the preview document's + // properties. + void OnDidStartPreview(const PrintHostMsg_DidStartPreview_Params& params, + const PrintHostMsg_PreviewIds& ids) { WebContents* web_contents = GetDialog(); ASSERT_TRUE(web_contents); Observe(web_contents);
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/automation_predicate.js b/chrome/browser/resources/chromeos/chromevox/cvox2/background/automation_predicate.js index a9c840bf..2b71035a 100644 --- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/automation_predicate.js +++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/automation_predicate.js
@@ -457,7 +457,7 @@ */ AutomationPredicate.checkable = AutomationPredicate.roles([ Role.CHECK_BOX, Role.RADIO_BUTTON, Role.MENU_ITEM_CHECK_BOX, - Role.MENU_ITEM_RADIO, Role.TOGGLE_BUTTON, Role.TREE_ITEM + Role.MENU_ITEM_RADIO, Role.SWITCH, Role.TOGGLE_BUTTON, Role.TREE_ITEM ]); /**
diff --git a/chrome/browser/resources/chromeos/login/accessibility_menu.html b/chrome/browser/resources/chromeos/login/accessibility_menu.html index 1a40792..2f45e681 100644 --- a/chrome/browser/resources/chromeos/login/accessibility_menu.html +++ b/chrome/browser/resources/chromeos/login/accessibility_menu.html
@@ -23,6 +23,12 @@ i18n-content="screenMagnifierOption"> </label> </div> + <div class="checkboxrow" id="select-to-speak-row"> + <input id="select-to-speak" type="checkbox"> + <label for="select-to-speak" class="checkboxlabel" + i18n-content="selectToSpeakOption"> + </label> + </div> <div class="checkboxrow"> <input id="virtual-keyboard" type="checkbox"> <label for="virtual-keyboard" class="checkboxlabel"
diff --git a/chrome/browser/resources/chromeos/login/oobe.js b/chrome/browser/resources/chromeos/login/oobe.js index acdc8b6..525bf02f 100644 --- a/chrome/browser/resources/chromeos/login/oobe.js +++ b/chrome/browser/resources/chromeos/login/oobe.js
@@ -97,6 +97,8 @@ $('large-cursor').addEventListener('click', Oobe.handleLargeCursorClick); $('spoken-feedback') .addEventListener('click', Oobe.handleSpokenFeedbackClick); + $('select-to-speak') + .addEventListener('click', Oobe.handleSelectToSpeakClick); $('screen-magnifier') .addEventListener('click', Oobe.handleScreenMagnifierClick); $('virtual-keyboard') @@ -106,6 +108,8 @@ $('large-cursor').addEventListener('keypress', Oobe.handleA11yKeyPress); $('spoken-feedback') .addEventListener('keypress', Oobe.handleA11yKeyPress); + $('select-to-speak') + .addEventListener('keypress', Oobe.handleA11yKeyPress); $('screen-magnifier') .addEventListener('keypress', Oobe.handleA11yKeyPress); $('virtual-keyboard') @@ -178,6 +182,14 @@ }, /** + * Select to speak checkbox handler. + */ + handleSelectToSpeakClick: function(e) { + chrome.send('enableSelectToSpeak', [$('select-to-speak').checked]); + e.stopPropagation(); + }, + + /** * Large cursor checkbox handler. */ handleLargeCursorClick: function(e) { @@ -232,10 +244,15 @@ refreshA11yInfo: function(data) { $('high-contrast').checked = data.highContrastEnabled; $('spoken-feedback').checked = data.spokenFeedbackEnabled; + $('select-to-speak').checked = data.selectToSpeakEnabled; $('screen-magnifier').checked = data.screenMagnifierEnabled; $('large-cursor').checked = data.largeCursorEnabled; $('virtual-keyboard').checked = data.virtualKeyboardEnabled; + // TODO(katie): Remove this when launching STS in OOBE screen. + if (!data.enableExperimentalA11yFeatures) + $('select-to-speak-row').setAttribute('hidden', true); + $('oobe-welcome-md').a11yStatus = data; },
diff --git a/chrome/browser/resources/chromeos/login/oobe_welcome.html b/chrome/browser/resources/chromeos/login/oobe_welcome.html index a16207d..932bf36 100644 --- a/chrome/browser/resources/chromeos/login/oobe_welcome.html +++ b/chrome/browser/resources/chromeos/login/oobe_welcome.html
@@ -176,6 +176,21 @@ [[i18nDynamic(locale, 'screenMagnifierOptionOff')]] </span> </oobe-a11y-option> + <oobe-a11y-option checked="[[a11yStatus.selectToSpeakEnabled]]" + on-change="onA11yOptionChanged_" + chrome-message="enableSelectToSpeak" + label-for-aria="[[i18nDynamic(locale, 'selectToSpeakOption')]]" + id="selectToSpeakOobeOption"> + <span slot="title"> + [[i18nDynamic(locale, 'selectToSpeakOption')]] + </span> + <span slot="checked-value"> + [[i18nDynamic(locale, 'selectToSpeakOptionOn')]] + </span> + <span slot="unchecked-value"> + [[i18nDynamic(locale, 'selectToSpeakOptionOff')]] + </span> + </oobe-a11y-option> <oobe-a11y-option checked="[[a11yStatus.virtualKeyboardEnabled]]" on-change="onA11yOptionChanged_" chrome-message="enableVirtualKeyboard"
diff --git a/chrome/browser/resources/chromeos/login/oobe_welcome.js b/chrome/browser/resources/chromeos/login/oobe_welcome.js index 3d75839e..c4089469 100644 --- a/chrome/browser/resources/chromeos/login/oobe_welcome.js +++ b/chrome/browser/resources/chromeos/login/oobe_welcome.js
@@ -83,6 +83,10 @@ }, onBeforeShow: function() { + // TODO(katie): Remove this when launching STS in OOBE screen. + if (!this.a11yStatus.enableExperimentalA11yFeatures) + this.$.selectToSpeakOobeOption.setAttribute('hidden', true); + this.behaviors.forEach((behavior) => { if (behavior.onBeforeShow) behavior.onBeforeShow.call(this);
diff --git a/chrome/browser/resources/chromeos/switch_access/automation_manager.js b/chrome/browser/resources/chromeos/switch_access/automation_manager.js index b7fe09a..ef135d7 100644 --- a/chrome/browser/resources/chromeos/switch_access/automation_manager.js +++ b/chrome/browser/resources/chromeos/switch_access/automation_manager.js
@@ -180,7 +180,9 @@ SwitchAccessPredicate.restrictions(this.scope_)); // Special case: Scope is actionable. - if (this.node_ === this.scope_ && !this.visitingScopeAsActionable_) { + if (this.node_ === this.scope_ && + SwitchAccessPredicate.isActionable(this.node_) && + !this.visitingScopeAsActionable_) { this.showScopeAsActionable_(); return; } @@ -218,7 +220,7 @@ let node = treeWalker.next().node; // Special case: Scope is actionable - if (node === this.scope_) { + if (node === this.scope_ && SwitchAccessPredicate.isActionable(node)) { this.showScopeAsActionable_(); return; }
diff --git a/chrome/browser/resources/chromeos/switch_access/switch_access_predicate.js b/chrome/browser/resources/chromeos/switch_access/switch_access_predicate.js index 0eacd4d..df8647d 100644 --- a/chrome/browser/resources/chromeos/switch_access/switch_access_predicate.js +++ b/chrome/browser/resources/chromeos/switch_access/switch_access_predicate.js
@@ -4,6 +4,7 @@ let StateType = chrome.automation.StateType; let RoleType = chrome.automation.RoleType; +let DefaultActionVerb = chrome.automation.DefaultActionVerb; /** * Class containing predicates for the chrome automation API. Each predicate @@ -105,13 +106,15 @@ node !== scope) return false; - let interestingBranches = 0; - let children = node.children || []; - for (let child of children) { + let interestingBranchesCount = + SwitchAccessPredicate.isActionable(node) ? 1 : 0; + let child = node.firstChild; + while (child) { if (SwitchAccessPredicate.isInterestingSubtree(child)) - interestingBranches += 1; - if (interestingBranches > 1) + interestingBranchesCount += 1; + if (interestingBranchesCount > 1) return true; + child = child.nextSibling; } return false; }; @@ -138,7 +141,7 @@ * @return {boolean} */ SwitchAccessPredicate.isInterestingSubtree = function(node) { - let children = node.children || []; + let children = node.children; return SwitchAccessPredicate.isActionable(node) || children.some(SwitchAccessPredicate.isInterestingSubtree); }; @@ -151,28 +154,41 @@ * @return {boolean} */ SwitchAccessPredicate.isActionable = function(node) { + let defaultActionVerb = node.defaultActionVerb; let loc = node.location; let parent = node.parent; let root = node.root; let role = node.role; let state = node.state; - // Skip things that are offscreen + // Skip things that are offscreen. if (state[StateType.OFFSCREEN] || loc.top < 0 || loc.left < 0) return false; - // Should just leave these as groups + // These web containers are not directly actionable. if (role === RoleType.WEB_VIEW || role === RoleType.ROOT_WEB_AREA) return false; if (parent) { // crbug.com/710559 - // Work around for browser tabs + // Work around for browser tabs. if (role === RoleType.TAB && parent.role === RoleType.TAB_LIST && root.role === RoleType.DESKTOP) return true; } - // The general rule that applies to everything. - return state[StateType.FOCUSABLE]; + // Check various indicators that the node is actionable. + // TODO(zhelfins): Update tests to reflect this updated behavior. + + if (defaultActionVerb && defaultActionVerb !== 'none' && + defaultActionVerb !== DefaultActionVerb.CLICK_ANCESTOR) + return true; + + if (node.inputType) + return true; + + if (role === RoleType.BUTTON) + return true; + + return false; };
diff --git a/chrome/browser/resources/local_ntp/custom_backgrounds.js b/chrome/browser/resources/local_ntp/custom_backgrounds.js index daa0764..e81ba16 100644 --- a/chrome/browser/resources/local_ntp/custom_backgrounds.js +++ b/chrome/browser/resources/local_ntp/custom_backgrounds.js
@@ -839,7 +839,7 @@ if (event.target == editDialog) editDialogInteraction(); }; - editDialog.onkeyup = function(event) { + editDialog.onkeydown = function(event) { if (event.keyCode === customBackgrounds.KEYCODES.ESC) { editDialogInteraction(); } @@ -853,12 +853,15 @@ editDialog.classList.remove(customBackgrounds.CLASSES.MOUSE_NAV); } // If keyboard navigation is attempted, remove mouse-only mode. - else if ( - event.keyCode === customBackgrounds.KEYCODES.TAB || + else if (event.keyCode === customBackgrounds.KEYCODES.TAB) { + editDialog.classList.remove(customBackgrounds.CLASSES.MOUSE_NAV); + } + else if( event.keyCode === customBackgrounds.KEYCODES.LEFT || event.keyCode === customBackgrounds.KEYCODES.UP || event.keyCode === customBackgrounds.KEYCODES.RIGHT || event.keyCode === customBackgrounds.KEYCODES.DOWN) { + event.preventDefault(); editDialog.classList.remove(customBackgrounds.CLASSES.MOUSE_NAV); } }; @@ -889,18 +892,20 @@ }; $(customBackgrounds.IDS.CUSTOM_LINKS_RESTORE_DEFAULT).onclick = customLinksRestoreDefaultInteraction; - $(customBackgrounds.IDS.CUSTOM_LINKS_RESTORE_DEFAULT).onkeyup = function( + $(customBackgrounds.IDS.CUSTOM_LINKS_RESTORE_DEFAULT).onkeydown = function( event) { if (event.keyCode === customBackgrounds.KEYCODES.ENTER) { customLinksRestoreDefaultInteraction(event); } // Handle arrow key navigation. else if (event.keyCode === customBackgrounds.KEYCODES.UP) { + event.preventDefault(); customBackgrounds .getNextOption( customBackgrounds.MENU_ENTRIES.CUSTOM_LINKS_RESTORE_DEFAULT, -1) .focus(); } else if (event.keyCode === customBackgrounds.KEYCODES.DOWN) { + event.preventDefault(); customBackgrounds .getNextOption( customBackgrounds.MENU_ENTRIES.CUSTOM_LINKS_RESTORE_DEFAULT, 1) @@ -957,18 +962,20 @@ }; $(customBackgrounds.IDS.UPLOAD_IMAGE).onclick = uploadImageInteraction; - $(customBackgrounds.IDS.UPLOAD_IMAGE).onkeyup = function(event) { + $(customBackgrounds.IDS.UPLOAD_IMAGE).onkeydown = function(event) { if (event.keyCode === customBackgrounds.KEYCODES.ENTER) { uploadImageInteraction(event); } // Handle arrow key navigation. if (event.keyCode === customBackgrounds.KEYCODES.UP) { + event.preventDefault(); customBackgrounds .getNextOption(customBackgrounds.MENU_ENTRIES.UPLOAD_IMAGE, -1) .focus(); } if (event.keyCode === customBackgrounds.KEYCODES.DOWN) { + event.preventDefault(); customBackgrounds .getNextOption(customBackgrounds.MENU_ENTRIES.UPLOAD_IMAGE, 1) .focus(); @@ -984,18 +991,20 @@ .NTP_CUSTOMIZE_RESTORE_BACKGROUND_CLICKED); }; $(customBackgrounds.IDS.RESTORE_DEFAULT).onclick = restoreDefaultInteraction; - $(customBackgrounds.IDS.RESTORE_DEFAULT).onkeyup = function(event) { + $(customBackgrounds.IDS.RESTORE_DEFAULT).onkeydown = function(event) { if (event.keyCode === customBackgrounds.KEYCODES.ENTER) { restoreDefaultInteraction(event); } // Handle arrow key navigation. if (event.keyCode === customBackgrounds.KEYCODES.UP) { + event.preventDefault(); customBackgrounds .getNextOption(customBackgrounds.MENU_ENTRIES.RESTORE_DEFAULT, -1) .focus(); } if (event.keyCode === customBackgrounds.KEYCODES.DOWN) { + event.preventDefault(); customBackgrounds .getNextOption(customBackgrounds.MENU_ENTRIES.RESTORE_DEFAULT, 1) .focus(); @@ -1022,7 +1031,7 @@ .classList.add(customBackgrounds.CLASSES.MOUSE_NAV); defaultWallpapersInteraction(event); }; - $(customBackgrounds.IDS.DEFAULT_WALLPAPERS).onkeyup = function(event) { + $(customBackgrounds.IDS.DEFAULT_WALLPAPERS).onkeydown = function(event) { if (event.keyCode === customBackgrounds.KEYCODES.ENTER) { $(customBackgrounds.IDS.MENU) .classList.remove(customBackgrounds.CLASSES.MOUSE_NAV); @@ -1031,11 +1040,13 @@ // Handle arrow key navigation. if (event.keyCode === customBackgrounds.KEYCODES.UP) { + event.preventDefault(); customBackgrounds .getNextOption(customBackgrounds.MENU_ENTRIES.CHROME_BACKGROUNDS, -1) .focus(); } if (event.keyCode === customBackgrounds.KEYCODES.DOWN) { + event.preventDefault(); customBackgrounds .getNextOption(customBackgrounds.MENU_ENTRIES.CHROME_BACKGROUNDS, 1) .focus(); @@ -1069,13 +1080,6 @@ } }; - // Clicks that happen outside of the dialog. - menu.onclick = function(event) { - if (event.target == menu) { - customBackgrounds.closeCollectionDialog(menu); - } - }; - // Interactions with the back arrow on the image selection dialog. var backInteraction = function(event) { customBackgrounds.resetSelectionDialog();
diff --git a/chrome/browser/resources/md_extensions/runtime_hosts_dialog.js b/chrome/browser/resources/md_extensions/runtime_hosts_dialog.js index 2b1cbac2..5a316f9 100644 --- a/chrome/browser/resources/md_extensions/runtime_hosts_dialog.js +++ b/chrome/browser/resources/md_extensions/runtime_hosts_dialog.js
@@ -5,6 +5,39 @@ cr.define('extensions', function() { 'use strict'; + // A RegExp to roughly match acceptable patterns entered by the user. + // exec'ing() this RegExp will match the following groups: + // 0: Full matched string. + // 1: Scheme + scheme separator (e.g., 'https://'). + // 2: Scheme only (e.g., 'https'). + // 3: Match subdomains ('*.'). + // 4: Hostname (e.g., 'example.com'). + // 5: Port, including ':' separator (e.g., ':80'). + // 6: Path, include '/' separator (e.g., '/*'). + const patternRegExp = new RegExp( + '^' + + // Scheme; optional. + '((http|https|\\*)://)?' + + // Include subdomains specifier; optional. + '(\\*\\.)?' + + // Hostname, required. + '([a-z0-9\\.-]+\\.[a-z0-9]+)' + + // Port, optional. + '(:[0-9]+)?' + + // Path, optional but if present must be '/' or '/*'. + '(\\/\\*|\\/)?' + + '$'); + + function getPatternFromSite(site) { + let res = patternRegExp.exec(site); + assert(res); + let scheme = res[1] || '*://'; + let host = (res[3] || '') + res[4]; + let port = res[5] || ''; + let path = '/*'; + return scheme + host + port + path; + } + const RuntimeHostsDialog = Polymer({ is: 'extensions-runtime-hosts-dialog', @@ -62,17 +95,7 @@ return; } - let valid = true; - try { - // Check if the input parses as a valid URL. JS URL parsing isn't - // great, but it's quick and easy and better than nothing. If it's still - // not valid, the API will throw an error and the embedding element will - // call setInputInvalid(). - let testUrl = new URL(this.site_); - } catch (e) { - valid = false; - } - + let valid = patternRegExp.test(this.site_); this.inputInvalid_ = !valid; }, @@ -138,7 +161,8 @@ * @private */ addPermission_: function() { - this.delegate.addRuntimeHostPermission(this.itemId, this.site_) + let pattern = getPatternFromSite(this.site_); + this.delegate.addRuntimeHostPermission(this.itemId, pattern) .then( () => { this.$.dialog.close(); @@ -149,5 +173,8 @@ }, }); - return {RuntimeHostsDialog: RuntimeHostsDialog}; + return { + RuntimeHostsDialog: RuntimeHostsDialog, + getPatternFromSite: getPatternFromSite + }; });
diff --git a/chrome/browser/resources/print_preview/new/more_settings.html b/chrome/browser/resources/print_preview/new/more_settings.html index ba0fbf1..d41ba3c 100644 --- a/chrome/browser/resources/print_preview/new/more_settings.html +++ b/chrome/browser/resources/print_preview/new/more_settings.html
@@ -12,6 +12,10 @@ margin: 10px auto 0; } + :host([disabled]) { + pointer-events: none; + } + :host button { align-items: center; background-color: #f6f6f6;
diff --git a/chrome/browser/resources/settings/site_settings/BUILD.gn b/chrome/browser/resources/settings/site_settings/BUILD.gn index d1d7f626..6fe64dd 100644 --- a/chrome/browser/resources/settings/site_settings/BUILD.gn +++ b/chrome/browser/resources/settings/site_settings/BUILD.gn
@@ -224,6 +224,7 @@ ":site_settings_behavior", "..:focus_row_behavior", "..:route", + "//ui/webui/resources/cr_elements/policy:cr_policy_pref_indicator", "//ui/webui/resources/js:cr", ] }
diff --git a/chrome/browser/resources/settings/site_settings/site_list.html b/chrome/browser/resources/settings/site_settings/site_list.html index efbfbede..1ba4ce4a 100644 --- a/chrome/browser/resources/settings/site_settings/site_list.html +++ b/chrome/browser/resources/settings/site_settings/site_list.html
@@ -4,9 +4,11 @@ <link rel="import" href="chrome://resources/html/cr/ui/focus_without_ink.html"> <link rel="import" href="chrome://resources/cr_elements/cr_action_menu/cr_action_menu.html"> <link rel="import" href="chrome://resources/cr_elements/policy/cr_policy_pref_indicator.html"> +<link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html"> <link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html"> <link rel="import" href="chrome://resources/html/list_property_update_behavior.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-list/iron-list.html"> +<link rel="import" href="chrome://resources/polymer/v1_0/paper-tooltip/paper-tooltip.html"> <link rel="import" href="../i18n_setup.html"> <link rel="import" href="../settings_shared_css.html"> <link rel="import" href="add_site_dialog.html"> @@ -18,7 +20,11 @@ <dom-module id="site-list"> <template> - <style include="settings-shared"></style> + <style include="settings-shared"> + paper-tooltip { + --paper-tooltip: var(--cr-tooltip); + } + </style> <div id="category"> <div class="settings-box first"> <h2 class="start">[[categoryHeader]]</h2> @@ -57,17 +63,21 @@ <div class="list-item secondary">$i18n{noSitesAdded}</div> </div> <div class="list-frame menu-content vertical-list" id="listContainer"> - <iron-list id="list" items="[[sites]]" preserve-focus risk-selection> + <iron-list items="[[sites]]" preserve-focus risk-selection> <template> <site-list-entry model="[[item]]" read-only-list="[[readOnlyList]]" on-show-action-menu="onShowActionMenu_" tabindex$="[[tabIndex]]" first$="[[!index]]" iron-list-tab-index="[[tabIndex]]" - last-focused="{{lastFocused_}}"> + last-focused="{{lastFocused_}}" + on-show-tooltip="onShowTooltip_"> </site-list-entry> </template> </iron-list> </div> </div> + <paper-tooltip id="tooltip" manual-mode position="top"> + [[tooltipText_]] + </paper-tooltip> <template is="dom-if" if="[[showEditExceptionDialog_]]" restamp> <settings-edit-exception-dialog model="[[actionMenuSite_]]" on-close="onEditExceptionDialogClosed_">
diff --git a/chrome/browser/resources/settings/site_settings/site_list.js b/chrome/browser/resources/settings/site_settings/site_list.js index dc04411..578fb2b 100644 --- a/chrome/browser/resources/settings/site_settings/site_list.js +++ b/chrome/browser/resources/settings/site_settings/site_list.js
@@ -102,6 +102,9 @@ /** @private */ lastFocused_: Object, + + /** @private */ + tooltipText_: String, }, /** @@ -202,6 +205,36 @@ }, /** + * Need to use common tooltip since the tooltip in the entry is cut off from + * the iron-list. + * @param {!{detail: {target: HTMLElement, text: string}}} e + * @private + */ + onShowTooltip_: function(e) { + this.tooltipText_ = e.detail.text; + const target = e.detail.target; + // paper-tooltip normally determines the target from the |for| property, + // which is a selector. Here paper-tooltip is being reused by multiple + // potential targets. Since paper-tooltip does not expose a public property + // or method to update the target, the private property |_target| is + // updated directly. + this.$.tooltip._target = target; + /** @type {{updatePosition: Function}} */ (this.$.tooltip).updatePosition(); + const hide = () => { + this.$.tooltip.hide(); + target.removeEventListener('mouseleave', hide); + target.removeEventListener('blur', hide); + target.removeEventListener('tap', hide); + this.$.tooltip.removeEventListener('mouseenter', hide); + }; + target.addEventListener('mouseleave', hide); + target.addEventListener('blur', hide); + target.addEventListener('tap', hide); + this.$.tooltip.addEventListener('mouseenter', hide); + this.$.tooltip.show(); + }, + + /** * Populate the sites list for display. * @private */ @@ -224,14 +257,7 @@ site => site.setting != settings.ContentSetting.DEFAULT && site.setting == this.categorySubtype) .map(site => this.expandSiteException(site)); - // iron-list needs to have display set to 'block' in order to render - // correctly. However, display also needs to be set to 'contents' so that - // the paper-tooltip in cr-policy-pref-indicator is not cutoff. - this.$.list.style.display = 'block'; this.updateList('sites', x => x.origin, sites); - this.async(() => { - this.$.list.style.display = 'contents'; - }); }, /**
diff --git a/chrome/browser/resources/settings/site_settings/site_list_entry.html b/chrome/browser/resources/settings/site_settings/site_list_entry.html index 7367d92..fbbf0fb 100644 --- a/chrome/browser/resources/settings/site_settings/site_list_entry.html +++ b/chrome/browser/resources/settings/site_settings/site_list_entry.html
@@ -4,6 +4,7 @@ <link rel="import" href="chrome://resources/cr_elements/policy/cr_policy_pref_indicator.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html"> +<link rel="import" href="chrome://resources/polymer/v1_0/neon-animation/web-animations.html"> <link rel="import" href="../focus_row_behavior.html"> <link rel="import" href="../i18n_setup.html"> <link rel="import" href="../icons.html"> @@ -19,6 +20,13 @@ .settings-row { flex: 1 } + + /* Tooltip is hidden since site-list will display a common tooltip. */ + cr-policy-pref-indicator { + --cr-tooltip: { + display: none; + }; + } </style> <div class="list-item" focus-row-container> <div class="settings-row" @@ -48,7 +56,8 @@ </div> <template is="dom-if" if="[[model.controlledBy]]"> <cr-policy-pref-indicator pref="[[model]]" - icon-aria-label="[[label]]"> + icon-aria-label="[[label]]" on-mouseenter="onShowTooltip_" + on-focus="onShowTooltip_" focus-row-control focus-type="policy"> </cr-policy-pref-indicator> </template> <paper-icon-button-light id="resetSiteContainer"
diff --git a/chrome/browser/resources/settings/site_settings/site_list_entry.js b/chrome/browser/resources/settings/site_settings/site_list_entry.js index 4ef7aa4..cd7803d 100644 --- a/chrome/browser/resources/settings/site_settings/site_list_entry.js +++ b/chrome/browser/resources/settings/site_settings/site_list_entry.js
@@ -46,6 +46,17 @@ }, }, + /** @private */ + onShowTooltip_: function() { + const indicator = assert(this.$$('cr-policy-pref-indicator')); + // The tooltip text is used by an paper-tooltip contained inside the + // cr-policy-pref-indicator. The text is currently held in a private + // property. This text is needed here to send up to the common tooltip + // component. + const text = indicator.indicatorTooltip_; + this.fire('show-tooltip', {target: indicator, text}); + }, + /** * @return {boolean} * @private
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index 0214d4b2..a1a942b 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -2488,6 +2488,8 @@ sources += cocoa_browser_sources + allow_circular_includes_from += [ "//chrome/browser/apps/app_shim" ] + deps += [ "//chrome/app/nibs:localizer_table", "//chrome/browser/apps/app_shim", @@ -3897,7 +3899,7 @@ } if (is_win && is_chrome_branded) { - deps += [ "//components/nux_google_apps:nux_google_apps_feature" ] + deps += [ "//components/nux:google_apps_feature" ] } if (enable_plugins) {
diff --git a/chrome/browser/ui/omnibox/idn_navigation_observer.cc b/chrome/browser/ui/omnibox/idn_navigation_observer.cc index 4db973c..57f16503d 100644 --- a/chrome/browser/ui/omnibox/idn_navigation_observer.cc +++ b/chrome/browser/ui/omnibox/idn_navigation_observer.cc
@@ -5,12 +5,14 @@ #include "chrome/browser/ui/omnibox/idn_navigation_observer.h" #include "base/bind.h" +#include "base/metrics/field_trial_params.h" #include "base/metrics/histogram_macros.h" #include "base/stl_util.h" #include "base/strings/utf_string_conversions.h" #include "chrome/browser/engagement/site_engagement_service.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/omnibox/alternate_nav_infobar_delegate.h" +#include "chrome/common/chrome_features.h" #include "components/omnibox/browser/autocomplete_match.h" #include "components/url_formatter/idn_spoof_checker.h" #include "components/url_formatter/url_formatter.h" @@ -20,6 +22,9 @@ namespace { +const base::FeatureParam<std::string> kMetricsOnly{ + &features::kIdnNavigationSuggestions, "metrics_only", ""}; + void RecordEvent(IdnNavigationObserver::NavigationSuggestionEvent event) { UMA_HISTOGRAM_ENUMERATION(IdnNavigationObserver::kHistogramName, event); } @@ -80,12 +85,13 @@ replace_host.SetHostStr(matched_domain); const GURL suggested_url = url.ReplaceComponents(replace_host); - RecordEvent(NavigationSuggestionEvent::kInfobarShown); - - AlternateNavInfoBarDelegate::CreateForIDNNavigation( - web_contents(), base::UTF8ToUTF16(matched_domain), suggested_url, - load_details.entry->GetVirtualURL(), - base::BindOnce(RecordEvent, NavigationSuggestionEvent::kLinkClicked)); + if (kMetricsOnly.Get().empty()) { + RecordEvent(NavigationSuggestionEvent::kInfobarShown); + AlternateNavInfoBarDelegate::CreateForIDNNavigation( + web_contents(), base::UTF8ToUTF16(matched_domain), suggested_url, + load_details.entry->GetVirtualURL(), + base::BindOnce(RecordEvent, NavigationSuggestionEvent::kLinkClicked)); + } } // static
diff --git a/chrome/browser/ui/omnibox/idn_navigation_observer_browsertest.cc b/chrome/browser/ui/omnibox/idn_navigation_observer_browsertest.cc index 0a67cf5..a37a50b 100644 --- a/chrome/browser/ui/omnibox/idn_navigation_observer_browsertest.cc +++ b/chrome/browser/ui/omnibox/idn_navigation_observer_browsertest.cc
@@ -24,13 +24,41 @@ #include "net/dns/mock_host_resolver.h" #include "ui/base/window_open_disposition.h" +namespace { + +enum class FeatureTestState { kDisabled, kEnabledWithoutUI, kEnabledWithUI }; + +struct SiteEngagementTestCase { + const char* const navigated; + const char* const suggested; +} kSiteEngagementTestCases[] = { + {"sité1.test", "site1.test"}, + {"mail.www.sité1.test", "site1.test"}, + + // These should match since the comparison uses eTLD+1s. + {"sité2.test", "www.site2.test"}, + {"mail.sité2.test", "www.site2.test"}, + + {"síté3.test", "sité3.test"}, + {"mail.síté3.test", "sité3.test"}, + + {"síté4.test", "www.sité4.test"}, + {"mail.síté4.test", "www.sité4.test"}, +}; + +} // namespace + class IdnNavigationObserverBrowserTest : public InProcessBrowserTest, - public testing::WithParamInterface<bool> { + public testing::WithParamInterface<FeatureTestState> { protected: void SetUp() override { - if (IsFeatureEnabled()) + if (GetParam() == FeatureTestState::kEnabledWithoutUI) { + feature_list_.InitAndEnableFeatureWithParameters( + features::kIdnNavigationSuggestions, {{"metrics_only", "true"}}); + } else if (GetParam() == FeatureTestState::kEnabledWithUI) { feature_list_.InitAndEnableFeature(features::kIdnNavigationSuggestions); + } InProcessBrowserTest::SetUp(); } @@ -100,15 +128,15 @@ EXPECT_FALSE(base::ContainsValue(enumerator.urls(), navigated_url)); } - bool IsFeatureEnabled() const { return GetParam(); } - private: base::test::ScopedFeatureList feature_list_; }; INSTANTIATE_TEST_CASE_P(, IdnNavigationObserverBrowserTest, - ::testing::Values(false, true)); + ::testing::Values(FeatureTestState::kDisabled, + FeatureTestState::kEnabledWithoutUI, + FeatureTestState::kEnabledWithUI)); // Navigating to a non-IDN shouldn't show an infobar. IN_PROC_BROWSER_TEST_P(IdnNavigationObserverBrowserTest, NonIdn_NoInfobar) { @@ -125,9 +153,9 @@ } // Navigating to a domain whose visual representation looks like a top domain -// should show a "Did you mean to go to ..." infobar. +// should show a "Did you mean to go to ..." infobar and record metrics. IN_PROC_BROWSER_TEST_P(IdnNavigationObserverBrowserTest, TopDomainIdn_Infobar) { - if (!IsFeatureEnabled()) + if (GetParam() != FeatureTestState::kEnabledWithUI) return; base::HistogramTester histograms; @@ -149,13 +177,28 @@ IdnNavigationObserver::NavigationSuggestionEvent::kMatchTopSite, 1); } +// Same as TopDomainIdn_Infobar but the UI is disabled, so only checks for +// metrics. +IN_PROC_BROWSER_TEST_P(IdnNavigationObserverBrowserTest, + TopDomainIdn_Metrics_NoInfobar) { + if (GetParam() != FeatureTestState::kEnabledWithoutUI) + return; + + base::HistogramTester histograms; + + TestInfobarNotShown( + embedded_test_server()->GetURL("googlé.com", "/title1.html")); + + histograms.ExpectTotalCount(IdnNavigationObserver::kHistogramName, 1); + histograms.ExpectBucketCount( + IdnNavigationObserver::kHistogramName, + IdnNavigationObserver::NavigationSuggestionEvent::kMatchTopSite, 1); +} + // Same as TopDomainIdn_Infobar but the user has engaged with the domain before. // Shouldn't show an infobar. IN_PROC_BROWSER_TEST_P(IdnNavigationObserverBrowserTest, TopDomainIdn_EngagedSite_NoInfobar) { - if (!IsFeatureEnabled()) - return; - // If the user already engaged with the site, the infobar shouldn't be shown. const GURL url = embedded_test_server()->GetURL("googlé.com", "/title1.html"); SetSiteEngagementScore(url, 20); @@ -167,7 +210,7 @@ // to go to ..." infobar. IN_PROC_BROWSER_TEST_P(IdnNavigationObserverBrowserTest, SiteEngagement_Infobar) { - if (!IsFeatureEnabled()) + if (GetParam() != FeatureTestState::kEnabledWithUI) return; SetSiteEngagementScore(GURL("http://site1.test"), 20); @@ -175,25 +218,7 @@ SetSiteEngagementScore(GURL("http://sité3.test"), 20); SetSiteEngagementScore(GURL("http://www.sité4.test"), 20); - struct TestCase { - const char* const navigated; - const char* const suggested; - } kTestCases[] = { - {"sité1.test", "site1.test"}, - {"mail.www.sité1.test", "site1.test"}, - - // These should match since the comparison uses eTLD+1s. - {"sité2.test", "www.site2.test"}, - {"mail.sité2.test", "www.site2.test"}, - - {"síté3.test", "sité3.test"}, - {"mail.síté3.test", "sité3.test"}, - - {"síté4.test", "www.sité4.test"}, - {"mail.síté4.test", "www.sité4.test"}, - }; - - for (const auto& test_case : kTestCases) { + for (const auto& test_case : kSiteEngagementTestCases) { base::HistogramTester histograms; TestInfobarShown( embedded_test_server()->GetURL(test_case.navigated, "/title1.html"), @@ -212,10 +237,34 @@ } } +// Same as SiteEngagement_Infobar but the UI is disabled, so only checks for +// metrics. +IN_PROC_BROWSER_TEST_P(IdnNavigationObserverBrowserTest, + SiteEngagement_Metrics_NoInfobar) { + if (GetParam() != FeatureTestState::kEnabledWithoutUI) + return; + + SetSiteEngagementScore(GURL("http://site1.test"), 20); + SetSiteEngagementScore(GURL("http://www.site2.test"), 20); + SetSiteEngagementScore(GURL("http://sité3.test"), 20); + SetSiteEngagementScore(GURL("http://www.sité4.test"), 20); + + for (const auto& test_case : kSiteEngagementTestCases) { + base::HistogramTester histograms; + TestInfobarNotShown( + embedded_test_server()->GetURL(test_case.navigated, "/title1.html")); + histograms.ExpectTotalCount(IdnNavigationObserver::kHistogramName, 1); + histograms.ExpectBucketCount( + IdnNavigationObserver::kHistogramName, + IdnNavigationObserver::NavigationSuggestionEvent::kMatchSiteEngagement, + 1); + } +} + // The infobar shouldn't be shown when the feature is disabled. IN_PROC_BROWSER_TEST_P(IdnNavigationObserverBrowserTest, TopDomainIdn_FeatureDisabled) { - if (IsFeatureEnabled()) + if (GetParam() != FeatureTestState::kDisabled) return; TestInfobarNotShown(
diff --git a/chrome/browser/ui/startup/startup_tab_provider.cc b/chrome/browser/ui/startup/startup_tab_provider.cc index 8db8a7e..ef6ac0e0 100644 --- a/chrome/browser/ui/startup/startup_tab_provider.cc +++ b/chrome/browser/ui/startup/startup_tab_provider.cc
@@ -28,8 +28,8 @@ #endif // defined(OS_WIN) #if defined(OS_WIN) && defined(GOOGLE_CHROME_BUILD) -#include "components/nux_google_apps/constants.h" -#include "components/nux_google_apps/google_apps_handler.h" +#include "components/nux/google_apps/constants.h" +#include "components/nux/google_apps/google_apps_handler.h" #endif // defined(OS_WIN) && defined(GOOGLE_CHROME_BUILD) namespace { @@ -84,7 +84,7 @@ #if defined(OS_WIN) #if defined(GOOGLE_CHROME_BUILD) - if (base::FeatureList::IsEnabled(nux_google_apps::kNuxGoogleAppsFeature)) { + if (base::FeatureList::IsEnabled(nux::kNuxGoogleAppsFeature)) { standard_params.is_apps_promo_allowed = true; standard_params.has_seen_apps_promo = prefs && prefs->GetBoolean(prefs::kHasSeenGoogleAppsPromoPage); @@ -214,8 +214,7 @@ // Should be shown before any other new user experience. if (ShouldShowNewUserExperience(params.is_apps_promo_allowed, params.has_seen_apps_promo)) { - return StartupTabs( - {StartupTab(GURL(nux_google_apps::kNuxGoogleAppsUrl), false)}); + return StartupTabs({StartupTab(GURL(nux::kNuxGoogleAppsUrl), false)}); } #endif // defined(OS_WIN) && defined(GOOGLE_CHROME_BUILD) @@ -253,8 +252,7 @@ // Should be shown before any other new user experience. if (ShouldShowNewUserExperience(standard_params.is_apps_promo_allowed, standard_params.has_seen_apps_promo)) { - return StartupTabs( - {StartupTab(GURL(nux_google_apps::kNuxGoogleAppsUrl), false)}); + return StartupTabs({StartupTab(GURL(nux::kNuxGoogleAppsUrl), false)}); } #endif // defined(GOOGLE_CHROME_BUILD)
diff --git a/chrome/browser/ui/startup/startup_tab_provider_unittest.cc b/chrome/browser/ui/startup/startup_tab_provider_unittest.cc index 35e86217..f80f75d6 100644 --- a/chrome/browser/ui/startup/startup_tab_provider_unittest.cc +++ b/chrome/browser/ui/startup/startup_tab_provider_unittest.cc
@@ -15,7 +15,7 @@ #if defined(OS_WIN) #include "base/win/windows_version.h" #if defined(GOOGLE_CHROME_BUILD) -#include "components/nux_google_apps/constants.h" +#include "components/nux/google_apps/constants.h" #endif // defined(GOOGLE_CHROME_BUILD) #endif // defined(OS_WIN) @@ -334,7 +334,7 @@ StartupTabProviderImpl::GetStandardOnboardingTabsForState(params); ASSERT_EQ(1U, output.size()); - EXPECT_EQ(nux_google_apps::kNuxGoogleAppsUrl, output[0].url); + EXPECT_EQ(nux::kNuxGoogleAppsUrl, output[0].url); EXPECT_FALSE(output[0].is_pinned); } { @@ -351,7 +351,7 @@ standard_params, win10_params); ASSERT_EQ(1U, output.size()); - EXPECT_EQ(nux_google_apps::kNuxGoogleAppsUrl, output[0].url); + EXPECT_EQ(nux::kNuxGoogleAppsUrl, output[0].url); EXPECT_FALSE(output[0].is_pinned); } }
diff --git a/chrome/browser/ui/views/apps/glass_app_window_frame_view_win.cc b/chrome/browser/ui/views/apps/glass_app_window_frame_view_win.cc index 4e9fff1..75ec5aa 100644 --- a/chrome/browser/ui/views/apps/glass_app_window_frame_view_win.cc +++ b/chrome/browser/ui/views/apps/glass_app_window_frame_view_win.cc
@@ -9,6 +9,7 @@ #include "base/win/windows_version.h" #include "extensions/browser/app_window/native_app_window.h" #include "ui/base/hit_test.h" +#include "ui/base/win/hwnd_metrics.h" #include "ui/display/win/screen_win.h" #include "ui/views/widget/widget.h" #include "ui/views/widget/widget_delegate.h" @@ -56,11 +57,8 @@ int border_thickness = 1; insets.Set(0, 0, border_thickness, border_thickness); } else { - // On Windows 10 we use a 1 pixel non client border which is too thin as a - // resize target. This inset extends the resize region. - int resize_border = display::win::ScreenWin::GetSystemMetricsForMonitor( - monitor, SM_CXSIZEFRAME); - insets.Set(0, resize_border, resize_border, resize_border); + const int frame_thickness = ui::GetFrameThickness(monitor); + insets.Set(0, frame_thickness, frame_thickness, frame_thickness); } return insets; }
diff --git a/chrome/browser/ui/views/frame/browser_desktop_window_tree_host_win.cc b/chrome/browser/ui/views/frame/browser_desktop_window_tree_host_win.cc index 278c54e..5d146dd5 100644 --- a/chrome/browser/ui/views/frame/browser_desktop_window_tree_host_win.cc +++ b/chrome/browser/ui/views/frame/browser_desktop_window_tree_host_win.cc
@@ -22,6 +22,7 @@ #include "chrome/common/chrome_constants.h" #include "ui/base/material_design/material_design_controller.h" #include "ui/base/theme_provider.h" +#include "ui/base/win/hwnd_metrics.h" #include "ui/display/win/screen_win.h" #include "ui/gfx/geometry/point.h" #include "ui/views/controls/menu/native_menu_win.h" @@ -100,9 +101,7 @@ // In fullscreen mode there is no frame. *insets = gfx::Insets(); } else { - const int frame_thickness = - display::win::ScreenWin::GetSystemMetricsForMonitor(monitor, - SM_CXSIZEFRAME); + const int frame_thickness = ui::GetFrameThickness(monitor); // Reduce the Windows non-client border size because we extend the border // into our client area in UpdateDWMFrame(). The top inset must be 0 or // else Windows will draw a full native titlebar outside the client area.
diff --git a/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.cc b/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.cc index 9bad097..6cb3be0 100644 --- a/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.cc +++ b/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.cc
@@ -10,6 +10,7 @@ #include "ash/public/interfaces/event_rewriter_controller.mojom.h" #include "ash/shell.h" #include "base/bind.h" +#include "base/command_line.h" #include "base/strings/utf_string_conversions.h" #include "base/values.h" #include "chrome/browser/browser_process.h" @@ -38,6 +39,7 @@ #include "chrome/grit/chromium_strings.h" #include "chrome/grit/generated_resources.h" #include "chromeos/chromeos_constants.h" +#include "chromeos/chromeos_switches.h" #include "components/login/base_screen_handler_utils.h" #include "components/login/localized_values_builder.h" #include "components/prefs/pref_service.h" @@ -125,6 +127,7 @@ // OOBE accessibility options menu strings shown on each screen. builder->Add("accessibilityLink", IDS_OOBE_ACCESSIBILITY_LINK); builder->Add("spokenFeedbackOption", IDS_OOBE_SPOKEN_FEEDBACK_OPTION); + builder->Add("selectToSpeakOption", IDS_OOBE_SELECT_TO_SPEAK_OPTION); builder->Add("largeCursorOption", IDS_OOBE_LARGE_CURSOR_OPTION); builder->Add("highContrastOption", IDS_OOBE_HIGH_CONTRAST_MODE_OPTION); builder->Add("screenMagnifierOption", IDS_OOBE_SCREEN_MAGNIFIER_OPTION); @@ -197,6 +200,8 @@ &CoreOobeHandler::HandleEnableScreenMagnifier); AddCallback("enableSpokenFeedback", &CoreOobeHandler::HandleEnableSpokenFeedback); + AddCallback("enableSelectToSpeak", + &CoreOobeHandler::HandleEnableSelectToSpeak); AddCallback("setDeviceRequisition", &CoreOobeHandler::HandleSetDeviceRequisition); AddCallback("screenAssetsLoaded", &CoreOobeHandler::HandleScreenAssetsLoaded); @@ -354,8 +359,15 @@ void CoreOobeHandler::HandleEnableSpokenFeedback(bool /* enabled */) { // Checkbox is initialized on page init and updates when spoken feedback // setting is changed so just toggle spoken feedback here. - AccessibilityManager* manager = AccessibilityManager::Get(); - manager->EnableSpokenFeedback(!manager->IsSpokenFeedbackEnabled()); + AccessibilityManager::Get()->EnableSpokenFeedback( + !AccessibilityManager::Get()->IsSpokenFeedbackEnabled()); +} + +void CoreOobeHandler::HandleEnableSelectToSpeak(bool /* enabled */) { + // Checkbox is initialized on page init and updates when Select to Speak + // setting is changed so just toggle Select to Speak here. + AccessibilityManager::Get()->SetSelectToSpeakEnabled( + !AccessibilityManager::Get()->IsSelectToSpeakEnabled()); } void CoreOobeHandler::HandleSetDeviceRequisition( @@ -479,6 +491,12 @@ AccessibilityManager::Get()->IsLargeCursorEnabled()); a11y_info.SetBoolean("spokenFeedbackEnabled", AccessibilityManager::Get()->IsSpokenFeedbackEnabled()); + a11y_info.SetBoolean("selectToSpeakEnabled", + AccessibilityManager::Get()->IsSelectToSpeakEnabled()); + a11y_info.SetBoolean( + "enableExperimentalA11yFeatures", + base::CommandLine::ForCurrentProcess()->HasSwitch( + chromeos::switches::kEnableExperimentalAccessibilityFeatures)); if (!features::IsMultiProcessMash()) { DCHECK(MagnificationManager::Get()); a11y_info.SetBoolean("screenMagnifierEnabled",
diff --git a/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.h b/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.h index 95ff2885..ccf9b41 100644 --- a/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.h +++ b/chrome/browser/ui/webui/chromeos/login/core_oobe_handler.h
@@ -130,6 +130,7 @@ void HandleEnableVirtualKeyboard(bool enabled); void HandleEnableScreenMagnifier(bool enabled); void HandleEnableSpokenFeedback(bool /* enabled */); + void HandleEnableSelectToSpeak(bool /* enabled */); void HandleInitialized(); void HandleSkipUpdateEnrollAfterEula(); void HandleUpdateCurrentScreen(const std::string& screen);
diff --git a/chrome/browser/ui/webui/chromeos/login/welcome_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/welcome_screen_handler.cc index f181f03..b5b0c3f 100644 --- a/chrome/browser/ui/webui/chromeos/login/welcome_screen_handler.cc +++ b/chrome/browser/ui/webui/chromeos/login/welcome_screen_handler.cc
@@ -155,6 +155,8 @@ builder->Add("screenMagnifierOptionOn", IDS_SCREEN_MAGNIFIER_OPTION_ON); builder->Add("spokenFeedbackOptionOff", IDS_SPOKEN_FEEDBACK_OPTION_OFF); builder->Add("spokenFeedbackOptionOn", IDS_SPOKEN_FEEDBACK_OPTION_ON); + builder->Add("selectToSpeakOptionOff", IDS_SELECT_TO_SPEAK_OPTION_OFF); + builder->Add("selectToSpeakOptionOn", IDS_SELECT_TO_SPEAK_OPTION_ON); builder->Add("virtualKeyboardOptionOff", IDS_VIRTUAL_KEYBOARD_OPTION_OFF); builder->Add("virtualKeyboardOptionOn", IDS_VIRTUAL_KEYBOARD_OPTION_ON);
diff --git a/chrome/browser/ui/webui/print_preview/print_preview_handler.cc b/chrome/browser/ui/webui/print_preview/print_preview_handler.cc index 317e7c5f..9386182 100644 --- a/chrome/browser/ui/webui/print_preview/print_preview_handler.cc +++ b/chrome/browser/ui/webui/print_preview/print_preview_handler.cc
@@ -1241,8 +1241,8 @@ } void PrintPreviewHandler::SendPageCountReady(int page_count, - int request_id, - int fit_to_page_scaling) { + int fit_to_page_scaling, + int request_id) { if (!ShouldReceiveRendererMessage(request_id)) return;
diff --git a/chrome/browser/ui/webui/print_preview/print_preview_handler.h b/chrome/browser/ui/webui/print_preview/print_preview_handler.h index dbca9ab..2a5806b8 100644 --- a/chrome/browser/ui/webui/print_preview/print_preview_handler.h +++ b/chrome/browser/ui/webui/print_preview/print_preview_handler.h
@@ -93,8 +93,8 @@ // Send the print preview page count and fit to page scaling void SendPageCountReady(int page_count, - int request_id, - int fit_to_page_scaling); + int fit_to_page_scaling, + int request_id); // Send the default page layout void SendPageLayoutReady(const base::DictionaryValue& layout,
diff --git a/chrome/browser/ui/webui/print_preview/print_preview_handler_unittest.cc b/chrome/browser/ui/webui/print_preview/print_preview_handler_unittest.cc index e1b41665..0660ac0 100644 --- a/chrome/browser/ui/webui/print_preview/print_preview_handler_unittest.cc +++ b/chrome/browser/ui/webui/print_preview/print_preview_handler_unittest.cc
@@ -694,7 +694,7 @@ AssertWebUIEventFired(*web_ui()->call_data().back(), "page-layout-ready"); // 1 page document. Modifiable so send default 100 scaling. - handler()->SendPageCountReady(1, preview_request_id, 100); + handler()->SendPageCountReady(1, 100, preview_request_id); AssertWebUIEventFired(*web_ui()->call_data().back(), "page-count-ready"); // Page at index 0 is ready. @@ -714,7 +714,7 @@ handler()->SendPageLayoutReady(base::DictionaryValue(), false, preview_request_id); EXPECT_EQ(message_count, web_ui()->call_data().size()); - handler()->SendPageCountReady(1, 0, -1); + handler()->SendPageCountReady(1, -1, 0); EXPECT_EQ(message_count, web_ui()->call_data().size()); handler()->OnPrintPreviewReady(0, 0); EXPECT_EQ(message_count, web_ui()->call_data().size());
diff --git a/chrome/browser/ui/webui/print_preview/print_preview_ui.cc b/chrome/browser/ui/webui/print_preview/print_preview_ui.cc index 8c1daf0a..3ab0afd 100644 --- a/chrome/browser/ui/webui/print_preview/print_preview_ui.cc +++ b/chrome/browser/ui/webui/print_preview/print_preview_ui.cc
@@ -693,14 +693,14 @@ g_print_preview_request_id_map.Get().Set(id_, request_id); } -void PrintPreviewUI::OnDidGetPreviewPageCount( - const PrintHostMsg_DidGetPreviewPageCount_Params& params, +void PrintPreviewUI::OnDidStartPreview( + const PrintHostMsg_DidStartPreview_Params& params, int request_id) { DCHECK_GT(params.page_count, 0); if (g_testing_delegate) g_testing_delegate->DidGetPreviewPageCount(params.page_count); - handler_->SendPageCountReady(params.page_count, request_id, - params.fit_to_page_scaling); + handler_->SendPageCountReady(params.page_count, params.fit_to_page_scaling, + request_id); } void PrintPreviewUI::OnDidGetDefaultPageLayout(
diff --git a/chrome/browser/ui/webui/print_preview/print_preview_ui.h b/chrome/browser/ui/webui/print_preview/print_preview_ui.h index d8f4e65..6fc3581f8 100644 --- a/chrome/browser/ui/webui/print_preview/print_preview_ui.h +++ b/chrome/browser/ui/webui/print_preview/print_preview_ui.h
@@ -17,7 +17,7 @@ #include "chrome/browser/ui/webui/constrained_web_dialog_ui.h" class PrintPreviewHandler; -struct PrintHostMsg_DidGetPreviewPageCount_Params; +struct PrintHostMsg_DidStartPreview_Params; struct PrintHostMsg_PreviewIds; struct PrintHostMsg_RequestPrintPreview_Params; struct PrintHostMsg_SetOptionsFromDocument_Params; @@ -85,10 +85,9 @@ // Notifies the Web UI of a print preview request with |request_id|. virtual void OnPrintPreviewRequest(int request_id); - // Notifies the Web UI about the page count of the request preview. - void OnDidGetPreviewPageCount( - const PrintHostMsg_DidGetPreviewPageCount_Params& params, - int request_id); + // Notifies the Web UI about the properties of the request preview. + void OnDidStartPreview(const PrintHostMsg_DidStartPreview_Params& params, + int request_id); // Notifies the Web UI of the default page layout according to the currently // selected printer and page size.
diff --git a/chrome/browser/ui/webui/welcome_ui.cc b/chrome/browser/ui/webui/welcome_ui.cc index 4bcca49..c037af96 100644 --- a/chrome/browser/ui/webui/welcome_ui.cc +++ b/chrome/browser/ui/webui/welcome_ui.cc
@@ -25,9 +25,9 @@ #if defined(OS_WIN) && defined(GOOGLE_CHROME_BUILD) #include "base/metrics/histogram_macros.h" #include "chrome/browser/bookmarks/bookmark_model_factory.h" +#include "components/nux/google_apps/constants.h" +#include "components/nux/google_apps/google_apps_handler.h" #include "components/nux/show_promo_delegate.h" -#include "components/nux_google_apps/constants.h" -#include "components/nux_google_apps/google_apps_handler.h" #include "content/public/browser/web_contents.h" #endif // defined(OS_WIN) && defined(GOOGLE_CHROME_BUILD) @@ -111,17 +111,16 @@ } #if defined(OS_WIN) && defined(GOOGLE_CHROME_BUILD) - if (base::FeatureList::IsEnabled(nux_google_apps::kNuxGoogleAppsFeature)) { + if (base::FeatureList::IsEnabled(nux::kNuxGoogleAppsFeature)) { content::BrowserContext* browser_context = web_ui->GetWebContents()->GetBrowserContext(); - web_ui->AddMessageHandler( - std::make_unique<nux_google_apps::GoogleAppsHandler>( - profile->GetPrefs(), - FaviconServiceFactory::GetForProfile( - profile, ServiceAccessType::EXPLICIT_ACCESS), - BookmarkModelFactory::GetForBrowserContext(browser_context))); + web_ui->AddMessageHandler(std::make_unique<nux::GoogleAppsHandler>( + profile->GetPrefs(), + FaviconServiceFactory::GetForProfile( + profile, ServiceAccessType::EXPLICIT_ACCESS), + BookmarkModelFactory::GetForBrowserContext(browser_context))); - nux_google_apps::GoogleAppsHandler::AddSources(html_source); + nux::GoogleAppsHandler::AddSources(html_source); } #endif // defined(OS_WIN) && defined(GOOGLE_CHROME_BUILD @@ -132,15 +131,14 @@ void WelcomeUI::StorePageSeen(Profile* profile, const GURL& url) { #if defined(OS_WIN) && defined(GOOGLE_CHROME_BUILD) - if (url.EqualsIgnoringRef(GURL(nux_google_apps::kNuxGoogleAppsUrl))) { + if (url.EqualsIgnoringRef(GURL(nux::kNuxGoogleAppsUrl))) { // Record that the new user experience page was visited. profile->GetPrefs()->SetBoolean(prefs::kHasSeenGoogleAppsPromoPage, true); // Record UMA. - UMA_HISTOGRAM_ENUMERATION( - nux_google_apps::kGoogleAppsInteractionHistogram, - nux_google_apps::GoogleAppsInteraction::kPromptShown, - nux_google_apps::GoogleAppsInteraction::kCount); + UMA_HISTOGRAM_ENUMERATION(nux::kGoogleAppsInteractionHistogram, + nux::GoogleAppsInteraction::kPromptShown, + nux::GoogleAppsInteraction::kCount); return; } #endif // defined(OS_WIN) && defined(GOOGLE_CHROME_BUILD)
diff --git a/chrome/browser/vr/BUILD.gn b/chrome/browser/vr/BUILD.gn index d9f12b5c..edcf5ac 100644 --- a/chrome/browser/vr/BUILD.gn +++ b/chrome/browser/vr/BUILD.gn
@@ -212,6 +212,7 @@ "render_loop_browser_interface.h", "sample_queue.cc", "sample_queue.h", + "scheduler_delegate.h", "service/browser_xr_runtime.cc", "service/browser_xr_runtime.h", "service/isolated_device_provider.cc", @@ -277,6 +278,7 @@ "assets_loader.cc", "assets_loader.h", "browser_ui_interface.h", + "compositor_ui_interface.h", "exit_vr_prompt_choice.h", "gl_texture_location.h", "input_event.cc",
diff --git a/chrome/browser/vr/compositor_delegate.h b/chrome/browser/vr/compositor_delegate.h index c10a8ee..e5254d7 100644 --- a/chrome/browser/vr/compositor_delegate.h +++ b/chrome/browser/vr/compositor_delegate.h
@@ -5,20 +5,53 @@ #ifndef CHROME_BROWSER_VR_COMPOSITOR_DELEGATE_H_ #define CHROME_BROWSER_VR_COMPOSITOR_DELEGATE_H_ +#include "base/callback.h" +#include "chrome/browser/vr/compositor_ui_interface.h" +#include "chrome/browser/vr/gl_texture_location.h" #include "chrome/browser/vr/vr_export.h" +namespace gfx { +class Transform; +} + namespace gl { class GLSurface; } // namespace gl namespace vr { +struct RenderInfo; + class VR_EXPORT CompositorDelegate { public: - typedef base::OnceCallback<void()> SkiaContextCallback; - + using Transform = float[16]; + enum FrameType { kUiFrame, kWebXrFrame }; + using SkiaContextCallback = base::OnceCallback<void()>; virtual ~CompositorDelegate() {} + virtual FovRectangles GetRecommendedFovs() = 0; + virtual float GetZNear() = 0; + virtual RenderInfo GetRenderInfo(FrameType frame_type) = 0; + virtual RenderInfo GetOptimizedRenderInfoForFovs( + const FovRectangles& fovs) = 0; + virtual void InitializeBuffers() = 0; + virtual void PrepareBufferForWebXr() = 0; + virtual void PrepareBufferForWebXrOverlayElements() = 0; + virtual void PrepareBufferForContentQuadLayer( + const gfx::Transform& quad_transform) = 0; + virtual void PrepareBufferForBrowserUi() = 0; + virtual void OnFinishedDrawingBuffer() = 0; + virtual void GetWebXrDrawParams(int* texture_id, Transform* uv_transform) = 0; + virtual bool IsContentQuadReady() = 0; + virtual void GetContentQuadDrawParams(Transform* uv_transform, + float* border_x, + float* border_y) = 0; + virtual void SubmitFrame(FrameType frame_type) = 0; + + virtual void SetUiInterface(CompositorUiInterface* ui) = 0; + virtual void SetShowingVrDialog(bool showing) = 0; + virtual int GetContentBufferWidth() = 0; + // These methods return true when succeeded. virtual bool Initialize(const scoped_refptr<gl::GLSurface>& surface) = 0; virtual bool RunInSkiaContext(SkiaContextCallback callback) = 0;
diff --git a/chrome/browser/vr/compositor_ui_interface.h b/chrome/browser/vr/compositor_ui_interface.h new file mode 100644 index 0000000..9151c56 --- /dev/null +++ b/chrome/browser/vr/compositor_ui_interface.h
@@ -0,0 +1,41 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_VR_COMPOSITOR_UI_INTERFACE_H_ +#define CHROME_BROWSER_VR_COMPOSITOR_UI_INTERFACE_H_ + +#include <utility> + +#include "chrome/browser/vr/gl_texture_location.h" +#include "chrome/browser/vr/vr_export.h" + +namespace vr { + +struct FovRectangle { + float left; + float right; + float bottom; + float top; +}; + +using FovRectangles = std::pair<FovRectangle, FovRectangle>; + +class VR_EXPORT CompositorUiInterface { + public: + virtual ~CompositorUiInterface() {} + + virtual void OnGlInitialized(unsigned int content_texture_id, + GlTextureLocation content_location, + unsigned int content_overlay_texture_id, + GlTextureLocation content_overlay_location, + unsigned int ui_texture_id) = 0; + + virtual void OnWebXrFrameAvailable() = 0; + virtual void OnWebXrTimedOut() = 0; + virtual void OnWebXrTimeoutImminent() = 0; +}; + +} // namespace vr + +#endif // CHROME_BROWSER_VR_COMPOSITOR_UI_INTERFACE_H_
diff --git a/chrome/browser/vr/render_loop.cc b/chrome/browser/vr/render_loop.cc index 2cc41fb..c382baf 100644 --- a/chrome/browser/vr/render_loop.cc +++ b/chrome/browser/vr/render_loop.cc
@@ -8,42 +8,195 @@ #include "base/time/time.h" #include "base/trace_event/common/trace_event_common.h" -#include "chrome/browser/vr/compositor_delegate.h" #include "chrome/browser/vr/controller_delegate_for_testing.h" #include "chrome/browser/vr/input_event.h" #include "chrome/browser/vr/model/controller_model.h" #include "chrome/browser/vr/model/reticle_model.h" +#include "chrome/browser/vr/platform_ui_input_delegate.h" #include "chrome/browser/vr/render_info.h" #include "chrome/browser/vr/render_loop_browser_interface.h" +#include "chrome/browser/vr/scheduler_delegate.h" #include "chrome/browser/vr/ui_interface.h" #include "chrome/browser/vr/ui_test_input.h" +#include "ui/gl/gl_bindings.h" namespace vr { RenderLoop::RenderLoop(std::unique_ptr<UiInterface> ui, CompositorDelegate* compositor_delegate, + SchedulerDelegate* scheduler_delegate, std::unique_ptr<ControllerDelegate> controller_delegate, RenderLoopBrowserInterface* browser, size_t sliding_time_size) : ui_(std::move(ui)), compositor_delegate_(compositor_delegate), + scheduler_delegate_(scheduler_delegate), controller_delegate_(std::move(controller_delegate)), browser_(browser), ui_processing_time_(sliding_time_size), - ui_controller_update_time_(sliding_time_size) {} + ui_controller_update_time_(sliding_time_size) { + compositor_delegate_->SetUiInterface(ui_.get()); +} + RenderLoop::~RenderLoop() = default; +void RenderLoop::Draw(CompositorDelegate::FrameType frame_type, + base::TimeTicks current_time) { + TRACE_EVENT1("gpu", __func__, "frame_type", frame_type); + const auto& render_info = compositor_delegate_->GetRenderInfo(frame_type); + UpdateUi(render_info, current_time, frame_type); + ui_->OnProjMatrixChanged(render_info.left_eye_model.proj_matrix); + bool use_quad_layer = ui_->IsContentVisibleAndOpaque() && + compositor_delegate_->IsContentQuadReady(); + ui_->SetContentUsesQuadLayer(use_quad_layer); + + compositor_delegate_->InitializeBuffers(); + if (frame_type == CompositorDelegate::kWebXrFrame) { + DCHECK(!use_quad_layer); + DrawWebXr(); + if (ui_->HasWebXrOverlayElementsToDraw()) + DrawWebXrOverlay(render_info); + } else { + if (use_quad_layer) + DrawContentQuad(); + DrawBrowserUi(render_info); + } + + compositor_delegate_->SubmitFrame(frame_type); +} + +void RenderLoop::DrawWebXr() { + TRACE_EVENT0("gpu", __func__); + compositor_delegate_->PrepareBufferForWebXr(); + + int texture_id; + CompositorDelegate::Transform uv_transform; + compositor_delegate_->GetWebXrDrawParams(&texture_id, &uv_transform); + ui_->DrawWebXr(texture_id, uv_transform); + compositor_delegate_->OnFinishedDrawingBuffer(); +} + +void RenderLoop::DrawWebXrOverlay(const RenderInfo& render_info) { + TRACE_EVENT0("gpu", __func__); + // Calculate optimized viewport and corresponding render info. + const auto& recommended_fovs = compositor_delegate_->GetRecommendedFovs(); + const auto& fovs = ui_->GetMinimalFovForWebXrOverlayElements( + render_info.left_eye_model.view_matrix, recommended_fovs.first, + render_info.right_eye_model.view_matrix, recommended_fovs.second, + compositor_delegate_->GetZNear()); + const auto& webxr_overlay_render_info = + compositor_delegate_->GetOptimizedRenderInfoForFovs(fovs); + + compositor_delegate_->PrepareBufferForWebXrOverlayElements(); + ui_->DrawWebVrOverlayForeground(webxr_overlay_render_info); + compositor_delegate_->OnFinishedDrawingBuffer(); +} + +void RenderLoop::DrawContentQuad() { + TRACE_EVENT0("gpu", __func__); + compositor_delegate_->PrepareBufferForContentQuadLayer( + ui_->GetContentWorldSpaceTransform()); + + CompositorDelegate::Transform uv_transform; + float border_x; + float border_y; + compositor_delegate_->GetContentQuadDrawParams(&uv_transform, &border_x, + &border_y); + ui_->DrawContent(uv_transform, border_x, border_y); + compositor_delegate_->OnFinishedDrawingBuffer(); +} + +void RenderLoop::DrawBrowserUi(const RenderInfo& render_info) { + TRACE_EVENT0("gpu", __func__); + compositor_delegate_->PrepareBufferForBrowserUi(); + ui_->Draw(render_info); + compositor_delegate_->OnFinishedDrawingBuffer(); +} + void RenderLoop::OnPause() { DCHECK(controller_delegate_); controller_delegate_->OnPause(); + scheduler_delegate_->OnSchedulerPause(); ui_->OnPause(); } void RenderLoop::OnResume() { DCHECK(controller_delegate_); + scheduler_delegate_->OnSchedulerResume(); controller_delegate_->OnResume(); } +void RenderLoop::OnSwapContents(int new_content_id) { + ui_->OnSwapContents(new_content_id); +} + +void RenderLoop::EnableAlertDialog(PlatformInputHandler* input_handler, + float width, + float height) { + compositor_delegate_->SetShowingVrDialog(true); + vr_dialog_input_delegate_ = + std::make_unique<PlatformUiInputDelegate>(input_handler); + vr_dialog_input_delegate_->SetSize(width, height); + auto content_width = compositor_delegate_->GetContentBufferWidth(); + if (content_width) { + ui_->SetContentOverlayAlertDialogEnabled( + true, vr_dialog_input_delegate_.get(), width / content_width, + height / content_width); + } else { + ui_->SetAlertDialogEnabled(true, vr_dialog_input_delegate_.get(), width, + height); + } +} + +void RenderLoop::DisableAlertDialog() { + ui_->SetAlertDialogEnabled(false, nullptr, 0, 0); + vr_dialog_input_delegate_ = nullptr; + compositor_delegate_->SetShowingVrDialog(false); +} + +void RenderLoop::SetAlertDialogSize(float width, float height) { + if (vr_dialog_input_delegate_) + vr_dialog_input_delegate_->SetSize(width, height); + // If not floating, dialogs are rendered with a fixed width, so that only the + // ratio matters. But, if they are floating, its size should be relative to + // the contents. During a WebXR presentation, the contents are not present + // but, in this case, the dialogs are never floating. + auto content_width = compositor_delegate_->GetContentBufferWidth(); + if (content_width) { + ui_->SetContentOverlayAlertDialogEnabled( + true, vr_dialog_input_delegate_.get(), width / content_width, + height / content_width); + } else { + ui_->SetAlertDialogEnabled(true, vr_dialog_input_delegate_.get(), width, + height); + } +} + +void RenderLoop::SetDialogLocation(float x, float y) { + ui_->SetDialogLocation(x, y); +} + +void RenderLoop::SetDialogFloating(bool floating) { + ui_->SetDialogFloating(floating); +} + +void RenderLoop::ShowToast(const base::string16& text) { + ui_->ShowPlatformToast(text); +} + +void RenderLoop::CancelToast() { + ui_->CancelPlatformToast(); +} + +void RenderLoop::ContentBoundsChanged(int width, int height) { + TRACE_EVENT0("gpu", __func__); + ui_->OnContentBoundsChanged(width, height); +} + +base::WeakPtr<BrowserUiInterface> RenderLoop::GetBrowserUiWeakPtr() { + return ui_->GetBrowserUiWeakPtr(); +} + void RenderLoop::SetUiExpectingActivityForTesting( UiTestActivityExpectation ui_expectation) { DCHECK(ui_test_state_ == nullptr) @@ -53,9 +206,13 @@ base::TimeDelta::FromMilliseconds(ui_expectation.quiescence_timeout_ms); } +void RenderLoop::AcceptDoffPromptForTesting() { + ui_->AcceptDoffPromptForTesting(); +} + void RenderLoop::UpdateUi(const RenderInfo& render_info, base::TimeTicks current_time, - FrameType frame_type) { + CompositorDelegate::FrameType frame_type) { TRACE_EVENT0("gpu", __func__); // Update the render position of all UI elements. @@ -64,7 +221,7 @@ // WebXR handles controller input in OnVsync. base::TimeDelta controller_time; - if (frame_type == kUiFrame) + if (frame_type == CompositorDelegate::kUiFrame) controller_time = ProcessControllerInput(render_info, current_time); if (ui_->SceneHasDirtyTextures()) {
diff --git a/chrome/browser/vr/render_loop.h b/chrome/browser/vr/render_loop.h index 62f61f2..3fc6e46 100644 --- a/chrome/browser/vr/render_loop.h +++ b/chrome/browser/vr/render_loop.h
@@ -8,6 +8,8 @@ #include <memory> #include "base/macros.h" +#include "chrome/browser/vr/compositor_delegate.h" +#include "chrome/browser/vr/gl_texture_location.h" #include "chrome/browser/vr/sliding_average.h" #include "chrome/browser/vr/vr_export.h" #include "device/vr/public/mojom/vr_service.mojom.h" @@ -20,9 +22,12 @@ namespace vr { enum class VrUiTestActivityResult; -class CompositorDelegate; +class BrowserUiInterface; class ControllerDelegate; +class PlatformInputHandler; +class PlatformUiInputDelegate; class RenderLoopBrowserInterface; +class SchedulerDelegate; class UiInterface; struct ControllerTestInput; struct RenderInfo; @@ -36,28 +41,40 @@ // VrShellGl and make this class concrete (http://crbug.com/767282). class VR_EXPORT RenderLoop { public: - enum FrameType { kUiFrame, kWebXrFrame }; - RenderLoop(std::unique_ptr<UiInterface> ui, CompositorDelegate* compositor_delegate, + SchedulerDelegate* scheduler_delegate, std::unique_ptr<ControllerDelegate> controller_delegate, RenderLoopBrowserInterface* browser, size_t sliding_time_size); virtual ~RenderLoop(); - virtual void OnPause(); - virtual void OnResume(); + void Draw(CompositorDelegate::FrameType frame_type, + base::TimeTicks current_time); + + void OnPause(); + void OnResume(); + + void OnSwapContents(int new_content_id); + void EnableAlertDialog(PlatformInputHandler* input_handler, + float width, + float height); + void DisableAlertDialog(); + void SetAlertDialogSize(float width, float height); + void SetDialogLocation(float x, float y); + void SetDialogFloating(bool floating); + void ShowToast(const base::string16& text); + void CancelToast(); + void ContentBoundsChanged(int width, int height); + + base::WeakPtr<BrowserUiInterface> GetBrowserUiWeakPtr(); void PerformControllerActionForTesting(ControllerTestInput controller_input); void SetUiExpectingActivityForTesting( UiTestActivityExpectation ui_expectation); + void AcceptDoffPromptForTesting(); protected: - // Position, hide and/or show UI elements, process input and update textures. - // Returns true if the scene changed. - void UpdateUi(const RenderInfo& render_info, - base::TimeTicks currrent_time, - FrameType frame_type); device::mojom::XRInputSourceStatePtr ProcessControllerInputForWebXr( const RenderInfo& render_info, base::TimeTicks current_time); @@ -70,9 +87,16 @@ return ui_processing_time_; } - std::unique_ptr<UiInterface> ui_; - private: + // Position, hide and/or show UI elements, process input and update textures. + // Returns true if the scene changed. + void UpdateUi(const RenderInfo& render_info, + base::TimeTicks currrent_time, + CompositorDelegate::FrameType frame_type); + void DrawWebXr(); + void DrawWebXrOverlay(const RenderInfo& render_info); + void DrawContentQuad(); + void DrawBrowserUi(const RenderInfo& render_info); base::TimeDelta ProcessControllerInput(const RenderInfo& render_info, base::TimeTicks current_time); @@ -80,11 +104,15 @@ bool ui_updated); void ReportUiActivityResultForTesting(VrUiTestActivityResult result); + std::unique_ptr<UiInterface> ui_; CompositorDelegate* compositor_delegate_; + SchedulerDelegate* scheduler_delegate_; std::unique_ptr<ControllerDelegate> controller_delegate_; std::unique_ptr<ControllerDelegate> controller_delegate_for_testing_; bool using_controller_delegate_for_testing_ = false; + std::unique_ptr<PlatformUiInputDelegate> vr_dialog_input_delegate_; + RenderLoopBrowserInterface* browser_; std::unique_ptr<UiTestState> ui_test_state_;
diff --git a/chrome/browser/vr/scheduler_delegate.h b/chrome/browser/vr/scheduler_delegate.h new file mode 100644 index 0000000..e73404f --- /dev/null +++ b/chrome/browser/vr/scheduler_delegate.h
@@ -0,0 +1,30 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_VR_SCHEDULER_DELEGATE_H_ +#define CHROME_BROWSER_VR_SCHEDULER_DELEGATE_H_ + +#include "base/callback.h" +#include "base/time/time.h" +#include "chrome/browser/vr/vr_export.h" + +namespace vr { + +class VR_EXPORT SchedulerDelegate { + public: + using DrawCallback = base::RepeatingCallback<void(base::TimeTicks)>; + virtual ~SchedulerDelegate() {} + + // TODO(acondor): Drop "Scheduler" from these names once RenderLoop owns + // VrShellGl. + virtual void OnSchedulerPause() = 0; + virtual void OnSchedulerResume() = 0; + + virtual void SetDrawWebXrCallback(DrawCallback callback) = 0; + virtual void SetDrawBrowserCallback(DrawCallback callback) = 0; +}; + +} // namespace vr + +#endif // CHROME_BROWSER_VR_SCHEDULER_DELEGATE_H_
diff --git a/chrome/browser/vr/test/gl_test_environment.cc b/chrome/browser/vr/test/gl_test_environment.cc index 9d1df9d8..ae48b613 100644 --- a/chrome/browser/vr/test/gl_test_environment.cc +++ b/chrome/browser/vr/test/gl_test_environment.cc
@@ -4,7 +4,6 @@ #include "chrome/browser/vr/test/gl_test_environment.h" -#include "chrome/browser/vr/base_compositor_delegate.h" #include "ui/gl/gl_version_info.h" #include "ui/gl/init/gl_factory.h" #include "ui/gl/test/gl_image_test_support.h" @@ -16,9 +15,9 @@ // Setup offscreen GL context. gl::GLImageTestSupport::InitializeGL(base::nullopt); surface_ = gl::init::CreateOffscreenGLSurface(gfx::Size()); - compositor_delegate_ = std::make_unique<BaseCompositorDelegate>(); - if (!compositor_delegate_->Initialize(surface_)) - return; + context_ = gl::init::CreateGLContext(nullptr, surface_.get(), + gl::GLContextAttribs()); + context_->MakeCurrent(surface_.get()); if (gl::GLContext::GetCurrent()->GetVersionInfo()->IsAtLeastGL(3, 3)) { // To avoid glGetVertexAttribiv(0, ...) failing. @@ -36,7 +35,8 @@ if (vao_) { glDeleteVertexArraysOES(1, &vao_); } - compositor_delegate_.reset(); + context_->ReleaseCurrent(surface_.get()); + context_ = nullptr; surface_ = nullptr; gl::GLImageTestSupport::CleanupGL(); }
diff --git a/chrome/browser/vr/test/gl_test_environment.h b/chrome/browser/vr/test/gl_test_environment.h index d373cd3..f4fcf433 100644 --- a/chrome/browser/vr/test/gl_test_environment.h +++ b/chrome/browser/vr/test/gl_test_environment.h
@@ -14,8 +14,6 @@ namespace vr { -class CompositorDelegate; - class GlTestEnvironment { public: explicit GlTestEnvironment(const gfx::Size frame_buffer_size); @@ -25,7 +23,7 @@ private: scoped_refptr<gl::GLSurface> surface_; - std::unique_ptr<CompositorDelegate> compositor_delegate_; + scoped_refptr<gl::GLContext> context_; GLuint vao_ = 0; GLuint frame_buffer_ = 0; };
diff --git a/chrome/browser/vr/testapp/gl_renderer.cc b/chrome/browser/vr/testapp/gl_renderer.cc index f0cdfe86..6d2a9f7 100644 --- a/chrome/browser/vr/testapp/gl_renderer.cc +++ b/chrome/browser/vr/testapp/gl_renderer.cc
@@ -10,6 +10,7 @@ #include "base/threading/thread_task_runner_handle.h" #include "base/time/time.h" #include "chrome/browser/vr/base_compositor_delegate.h" +#include "chrome/browser/vr/render_info.h" #include "chrome/browser/vr/testapp/vr_test_context.h" #include "ui/gl/gl_bindings.h" #include "ui/gl/gl_context.h" @@ -40,6 +41,41 @@ return true; } +// TODO(acondor): Provide actual implementation for the methods. +FovRectangles GlRenderer::GetRecommendedFovs() { + return {{}, {}}; +} +float GlRenderer::GetZNear() { + return 0; +} +RenderInfo GlRenderer::GetRenderInfo(FrameType frame_type) { + return {}; +} +RenderInfo GlRenderer::GetOptimizedRenderInfoForFovs( + const FovRectangles& fovs) { + return {}; +} +void GlRenderer::InitializeBuffers() {} +void GlRenderer::PrepareBufferForWebXr() {} +void GlRenderer::PrepareBufferForWebXrOverlayElements() {} +void GlRenderer::PrepareBufferForContentQuadLayer( + const gfx::Transform& quad_transform) {} +void GlRenderer::PrepareBufferForBrowserUi() {} +void GlRenderer::OnFinishedDrawingBuffer() {} +void GlRenderer::GetWebXrDrawParams(int* texture_id, Transform* uv_transform) {} +bool GlRenderer::IsContentQuadReady() { + return true; +} +void GlRenderer::GetContentQuadDrawParams(Transform* uv_transform, + float* border_x, + float* border_y) {} +void GlRenderer::SubmitFrame(FrameType frame_type) {} +void GlRenderer::SetUiInterface(CompositorUiInterface* ui) {} +void GlRenderer::SetShowingVrDialog(bool showing) {} +int GlRenderer::GetContentBufferWidth() { + return 0; +} + void GlRenderer::RenderFrame() { // Checking and clearing GL errors can be expensive, but we can afford to do // this in the testapp as a sanity check. Clear errors before drawing UI,
diff --git a/chrome/browser/vr/testapp/gl_renderer.h b/chrome/browser/vr/testapp/gl_renderer.h index fdc82c1..a9736f6 100644 --- a/chrome/browser/vr/testapp/gl_renderer.h +++ b/chrome/browser/vr/testapp/gl_renderer.h
@@ -25,7 +25,29 @@ GlRenderer(); ~GlRenderer() override; + // CompositorDelegate implementation. bool Initialize(const scoped_refptr<gl::GLSurface>& surface) override; + FovRectangles GetRecommendedFovs() override; + float GetZNear() override; + RenderInfo GetRenderInfo(FrameType frame_type) override; + RenderInfo GetOptimizedRenderInfoForFovs(const FovRectangles& fovs) override; + void InitializeBuffers() override; + void PrepareBufferForWebXr() override; + void PrepareBufferForWebXrOverlayElements() override; + void PrepareBufferForContentQuadLayer( + const gfx::Transform& quad_transform) override; + void PrepareBufferForBrowserUi() override; + void OnFinishedDrawingBuffer() override; + void GetWebXrDrawParams(int* texture_id, Transform* uv_transform) override; + bool IsContentQuadReady() override; + void GetContentQuadDrawParams(Transform* uv_transform, + float* border_x, + float* border_y) override; + void SubmitFrame(FrameType frame_type) override; + void SetUiInterface(CompositorUiInterface* ui) override; + void SetShowingVrDialog(bool showing) override; + int GetContentBufferWidth() override; + void RenderFrame(); void PostRenderFrameTask(); void set_vr_context(VrTestContext* vr_context) { vr_context_ = vr_context; }
diff --git a/chrome/browser/vr/testapp/vr_test_context.cc b/chrome/browser/vr/testapp/vr_test_context.cc index b925f24..726bc2e 100644 --- a/chrome/browser/vr/testapp/vr_test_context.cc +++ b/chrome/browser/vr/testapp/vr_test_context.cc
@@ -264,7 +264,7 @@ active_capturing.location_access_enabled = true; ui_->SetCapturingState(active_capturing, background_capturing, potential_capturing); - ui_->OnWebVrFrameAvailable(); + ui_->OnWebXrFrameAvailable(); break; } case ui::DomCode::US_O: @@ -504,10 +504,10 @@ break; } case kWebVrAwaitingFirstFrame: - ui_->OnWebVrTimeoutImminent(); + ui_->OnWebXrTimeoutImminent(); break; case kWebVrTimeoutImminent: - ui_->OnWebVrTimedOut(); + ui_->OnWebXrTimedOut(); break; case kWebVrTimedOut: ui_->SetWebVrMode(false);
diff --git a/chrome/browser/vr/ui.cc b/chrome/browser/vr/ui.cc index 14f1a860..8720336 100644 --- a/chrome/browser/vr/ui.cc +++ b/chrome/browser/vr/ui.cc
@@ -317,10 +317,6 @@ model_->incognito_tabs.clear(); } -bool Ui::CanSendWebVrVSync() { - return model_->web_vr_enabled() && !model_->web_vr.showing_hosted_ui; -} - void Ui::SetAlertDialogEnabled(bool enabled, PlatformUiInputDelegate* delegate, float width, @@ -466,17 +462,17 @@ model_->projection_matrix = proj_matrix; } -void Ui::OnWebVrFrameAvailable() { +void Ui::OnWebXrFrameAvailable() { if (model_->web_vr_enabled()) model_->web_vr.state = kWebVrPresenting; } -void Ui::OnWebVrTimeoutImminent() { +void Ui::OnWebXrTimeoutImminent() { if (model_->web_vr_enabled()) model_->web_vr.state = kWebVrTimeoutImminent; } -void Ui::OnWebVrTimedOut() { +void Ui::OnWebXrTimedOut() { if (model_->web_vr_enabled()) model_->web_vr.state = kWebVrTimedOut; } @@ -725,8 +721,7 @@ } } -std::pair<UiInterface::FovRectangle, UiInterface::FovRectangle> -Ui::GetMinimalFovForWebXrOverlayElements( +std::pair<FovRectangle, FovRectangle> Ui::GetMinimalFovForWebXrOverlayElements( const gfx::Transform& left_view, const FovRectangle& fov_recommended_left, const gfx::Transform& right_view, @@ -737,11 +732,10 @@ GetMinimalFov(right_view, elements, fov_recommended_right, z_near)}; } -Ui::FovRectangle Ui::GetMinimalFov( - const gfx::Transform& view_matrix, - const std::vector<const UiElement*>& elements, - const Ui::FovRectangle& fov_recommended, - float z_near) { +FovRectangle Ui::GetMinimalFov(const gfx::Transform& view_matrix, + const std::vector<const UiElement*>& elements, + const FovRectangle& fov_recommended, + float z_near) { // Calculate boundary of Z near plane in view space. float z_near_left = -z_near * std::tan(fov_recommended.left * base::kPiFloat / 180); @@ -812,7 +806,7 @@ } if (!has_visible_element) { - return Ui::FovRectangle{0.f, 0.f, 0.f, 0.f}; + return FovRectangle{0.f, 0.f, 0.f, 0.f}; } // Add a small margin to fix occasional border clipping due to precision. @@ -826,8 +820,7 @@ float right_degrees = std::atan(right / z_near) * 180 / base::kPiFloat; float bottom_degrees = std::atan(-bottom / z_near) * 180 / base::kPiFloat; float top_degrees = std::atan(top / z_near) * 180 / base::kPiFloat; - return Ui::FovRectangle{left_degrees, right_degrees, bottom_degrees, - top_degrees}; + return FovRectangle{left_degrees, right_degrees, bottom_degrees, top_degrees}; } #if defined(FEATURE_MODULES)
diff --git a/chrome/browser/vr/ui.h b/chrome/browser/vr/ui.h index 3c4a4603..981390f5 100644 --- a/chrome/browser/vr/ui.h +++ b/chrome/browser/vr/ui.h
@@ -120,7 +120,6 @@ // UiInterface base::WeakPtr<BrowserUiInterface> GetBrowserUiWeakPtr() override; - bool CanSendWebVrVSync() override; void SetAlertDialogEnabled(bool enabled, PlatformUiInputDelegate* delegate, float width, @@ -137,19 +136,11 @@ void ShowPlatformToast(const base::string16& text) override; void CancelPlatformToast() override; bool ShouldRenderWebVr() override; - void OnGlInitialized(unsigned int content_texture_id, - GlTextureLocation content_location, - unsigned int content_overlay_texture_id, - GlTextureLocation content_overlay_location, - unsigned int ui_texture_id) override; void OnPause() override; void OnControllerUpdated(const ControllerModel& controller_model, const ReticleModel& reticle_model) override; void OnProjMatrixChanged(const gfx::Transform& proj_matrix) override; - void OnWebVrFrameAvailable() override; - void OnWebVrTimedOut() override; - void OnWebVrTimeoutImminent() override; bool IsControllerVisible() const override; bool SkipsRedrawWhenNotDirty() const override; void OnSwapContents(int new_content_id) override; @@ -189,6 +180,16 @@ const FovRectangle& fov_recommended_right, float z_near) override; + // CompositorUiInterface + void OnGlInitialized(unsigned int content_texture_id, + GlTextureLocation content_location, + unsigned int content_overlay_texture_id, + GlTextureLocation content_overlay_location, + unsigned int ui_texture_id) override; + void OnWebXrFrameAvailable() override; + void OnWebXrTimedOut() override; + void OnWebXrTimeoutImminent() override; + // KeyboardUiInterface void OnInputEdited(const EditedText& info) override; void OnInputCommitted(const EditedText& info) override;
diff --git a/chrome/browser/vr/ui_interface.h b/chrome/browser/vr/ui_interface.h index ba2fdef8..ca91d508 100644 --- a/chrome/browser/vr/ui_interface.h +++ b/chrome/browser/vr/ui_interface.h
@@ -12,6 +12,7 @@ #include "base/memory/weak_ptr.h" #include "chrome/browser/vr/browser_ui_interface.h" +#include "chrome/browser/vr/compositor_ui_interface.h" #include "chrome/browser/vr/gl_texture_location.h" #include "chrome/browser/vr/keyboard_ui_interface.h" @@ -36,18 +37,14 @@ // This interface represents the methods that should be called by its owner, and // also serves to make all such methods virtual for the sake of separating a UI // feature module. -class UiInterface : public BrowserUiInterface, public KeyboardUiInterface { +class UiInterface : public BrowserUiInterface, + public CompositorUiInterface, + public KeyboardUiInterface { public: ~UiInterface() override {} virtual base::WeakPtr<BrowserUiInterface> GetBrowserUiWeakPtr() = 0; - // TODO(ymalik): We expose this to stop sending VSync to the WebVR page until - // the splash screen has been visible for its minimum duration. The visibility - // logic currently lives in the UI, and it'd be much cleaner if the UI didn't - // have to worry about this, and if it were told to hide the splash screen - // like other WebVR phases (e.g. OnWebVrFrameAvailable below). - virtual bool CanSendWebVrVSync() = 0; virtual void SetAlertDialogEnabled(bool enabled, PlatformUiInputDelegate* delegate, float width, @@ -65,18 +62,10 @@ virtual void ShowPlatformToast(const base::string16& text) = 0; virtual void CancelPlatformToast() = 0; virtual bool ShouldRenderWebVr() = 0; - virtual void OnGlInitialized(unsigned int content_texture_id, - GlTextureLocation content_location, - unsigned int content_overlay_texture_id, - GlTextureLocation content_overlay_location, - unsigned int ui_texture_id) = 0; virtual void OnPause() = 0; virtual void OnControllerUpdated(const ControllerModel& controller_model, const ReticleModel& reticle_model) = 0; virtual void OnProjMatrixChanged(const gfx::Transform& proj_matrix) = 0; - virtual void OnWebVrFrameAvailable() = 0; - virtual void OnWebVrTimedOut() = 0; - virtual void OnWebVrTimeoutImminent() = 0; virtual bool IsControllerVisible() const = 0; virtual bool SkipsRedrawWhenNotDirty() const = 0; virtual void OnSwapContents(int new_content_id) = 0; @@ -117,14 +106,7 @@ // 10.f, 10.f} in the example case. // Using a smaller FOV could improve the performance a lot while we are // showing UIs on top of WebVR content. - struct FovRectangle { - float left; - float right; - float bottom; - float top; - }; - virtual std::pair<FovRectangle, FovRectangle> - GetMinimalFovForWebXrOverlayElements( + virtual FovRectangles GetMinimalFovForWebXrOverlayElements( const gfx::Transform& left_view, const FovRectangle& fov_recommended_left, const gfx::Transform& right_view,
diff --git a/chrome/browser/vr/ui_unittest.cc b/chrome/browser/vr/ui_unittest.cc index 99c2c3e..ff46e18 100644 --- a/chrome/browser/vr/ui_unittest.cc +++ b/chrome/browser/vr/ui_unittest.cc
@@ -115,7 +115,7 @@ EXPECT_FALSE(IsVisible(kWebVrExclusiveScreenToast)); ui_->SetWebVrMode(true); - ui_->OnWebVrFrameAvailable(); + ui_->OnWebXrFrameAvailable(); ui_->SetCapturingState(CapturingStateModel(), CapturingStateModel(), CapturingStateModel()); EXPECT_TRUE(IsVisible(kWebVrExclusiveScreenToast)); @@ -134,7 +134,7 @@ CreateScene(kNotInWebVr); ui_->SetWebVrMode(true); - ui_->OnWebVrFrameAvailable(); + ui_->OnWebXrFrameAvailable(); ui_->SetCapturingState(CapturingStateModel(), CapturingStateModel(), CapturingStateModel()); EXPECT_TRUE(IsVisible(kWebVrExclusiveScreenToast)); @@ -177,7 +177,7 @@ for (auto& spec : GetIndicatorSpecs()) { for (int i = 0; i < 3; ++i) { ui_->SetWebVrMode(true); - ui_->OnWebVrFrameAvailable(); + ui_->OnWebXrFrameAvailable(); CapturingStateModel active_capturing; CapturingStateModel background_capturing; @@ -390,15 +390,12 @@ TEST_F(UiTest, HostedUiInWebVr) { CreateScene(kInWebVr); VerifyVisibility({kWebVrHostedUi, kWebVrFloor}, false); - EXPECT_TRUE(ui_->CanSendWebVrVSync()); ui_->SetAlertDialogEnabled(true, nullptr, 0, 0); - EXPECT_FALSE(ui_->CanSendWebVrVSync()); OnBeginFrame(); VerifyVisibility({kWebVrHostedUi, kWebVrBackground, kWebVrFloor}, true); ui_->SetAlertDialogEnabled(false, nullptr, 0, 0); - EXPECT_TRUE(ui_->CanSendWebVrVSync()); OnBeginFrame(); VerifyVisibility({kWebVrHostedUi, kWebVrFloor}, false); } @@ -623,13 +620,13 @@ TEST_F(UiTest, WebVrFramesIgnoredWhenUnexpected) { CreateScene(kInWebVr); - ui_->OnWebVrFrameAvailable(); + ui_->OnWebXrFrameAvailable(); VerifyOnlyElementsVisible("Elements hidden", std::set<UiElementName>{}); // Disable WebVR mode. ui_->SetWebVrMode(false); // New frame available after exiting WebVR mode. - ui_->OnWebVrFrameAvailable(); + ui_->OnWebXrFrameAvailable(); VerifyOnlyElementsVisible("Browser visible", kElementsVisibleInBrowsing); } @@ -643,7 +640,7 @@ // Transition to WebVR mode ui_->SetWebVrMode(true); - ui_->OnWebVrFrameAvailable(); + ui_->OnWebXrFrameAvailable(); // All elements should be hidden. VerifyOnlyElementsVisible("Elements hidden", std::set<UiElementName>{}); @@ -1283,7 +1280,7 @@ CreateScene(kInWebVr); ui_->SetWebVrMode(true); EXPECT_FALSE(IsVisible(kWebVrExclusiveScreenToast)); - ui_->OnWebVrFrameAvailable(); + ui_->OnWebXrFrameAvailable(); ui_->SetCapturingState(CapturingStateModel(), CapturingStateModel(), CapturingStateModel()); OnBeginFrame(); @@ -1304,7 +1301,7 @@ CreateScene(kInWebVr); ui_->SetWebVrMode(true); EXPECT_FALSE(IsVisible(kWebVrExclusiveScreenToast)); - ui_->OnWebVrFrameAvailable(); + ui_->OnWebXrFrameAvailable(); ui_->SetCapturingState(CapturingStateModel(), CapturingStateModel(), CapturingStateModel()); OnBeginFrame();
diff --git a/chrome/browser/web_applications/BUILD.gn b/chrome/browser/web_applications/BUILD.gn index cbcf14a..621fc64 100644 --- a/chrome/browser/web_applications/BUILD.gn +++ b/chrome/browser/web_applications/BUILD.gn
@@ -17,7 +17,11 @@ deps = [ ":web_app_group", "//chrome/browser/web_applications/bookmark_apps", + "//chrome/browser/web_applications/components", + "//chrome/browser/web_applications/extensions", "//chrome/common", + "//components/keyed_service/content", + "//extensions/browser", ] } @@ -31,3 +35,12 @@ "//chrome/browser/web_applications/extensions:unit_tests", ] } + +source_set("browser_tests") { + testonly = true + + deps = [ + ":web_app_group", + "//chrome/browser/web_applications/extensions:browser_tests", + ] +}
diff --git a/chrome/browser/web_applications/bookmark_apps/BUILD.gn b/chrome/browser/web_applications/bookmark_apps/BUILD.gn index f46136e..33ac9ca 100644 --- a/chrome/browser/web_applications/bookmark_apps/BUILD.gn +++ b/chrome/browser/web_applications/bookmark_apps/BUILD.gn
@@ -19,7 +19,11 @@ deps = [ "//chrome/browser/extensions", "//chrome/browser/web_applications:web_app_group", + "//chrome/browser/web_applications/components", + "//chrome/browser/web_applications/extensions", "//chrome/common", + "//components/favicon/content", + "//components/pref_registry", "//skia", ] } @@ -34,9 +38,17 @@ deps = [ ":bookmark_apps", + "//base", + "//chrome/browser", "//chrome/browser/web_applications:web_app_group", + "//chrome/browser/web_applications/components", "//chrome/browser/web_applications/components:test_support", + "//chrome/common:constants", + "//components/sync_preferences:test_support", + "//content/test:test_support", "//skia", "//testing/gmock", + "//testing/gtest", + "//url", ] }
diff --git a/chrome/browser/web_applications/components/BUILD.gn b/chrome/browser/web_applications/components/BUILD.gn index 4963eeb..3b59610 100644 --- a/chrome/browser/web_applications/components/BUILD.gn +++ b/chrome/browser/web_applications/components/BUILD.gn
@@ -39,14 +39,18 @@ } deps = [ + "//chrome/app/resources:platform_locale_settings", + "//chrome/app/theme:chrome_unscaled_resources", "//chrome/browser/web_applications:web_app_group", "//chrome/common", + "//components/crx_file", + "//components/favicon/content", "//content/public/browser", "//skia", ] } -static_library("test_support") { +source_set("test_support") { testonly = true sources = [ @@ -57,6 +61,7 @@ deps = [ ":components", "//base", + "//url", ] } @@ -78,8 +83,10 @@ deps = [ ":components", + "//base/test:test_support", "//chrome/app/theme:theme_resources", "//chrome/browser/web_applications:web_app_group", + "//chrome/test:test_support", "//content/public/browser", "//skia", "//testing/gmock",
diff --git a/chrome/browser/web_applications/extensions/BUILD.gn b/chrome/browser/web_applications/extensions/BUILD.gn index ec7b5fa9..994d2c9 100644 --- a/chrome/browser/web_applications/extensions/BUILD.gn +++ b/chrome/browser/web_applications/extensions/BUILD.gn
@@ -32,6 +32,7 @@ "//chrome/browser/web_applications/components", "//chrome/common", "//content/public/browser", + "//extensions/browser", "//skia", ] } @@ -48,10 +49,40 @@ deps = [ ":extensions", + "//chrome/browser", "//chrome/browser/web_applications:web_app_group", "//chrome/browser/web_applications/components", + "//chrome/common", + "//chrome/test:test_support", "//content/public/browser", + "//content/test:test_support", + "//extensions/browser/install", + "//extensions/common", "//skia", "//testing/gtest", ] } + +source_set("browser_tests") { + testonly = true + + sources = [ + "pending_bookmark_app_manager_browsertest.cc", + ] + + defines = [ "HAS_OUT_OF_PROC_TEST_RUNNER" ] + + deps = [ + ":extensions", + "//base/test:test_support", + "//chrome/browser", + "//chrome/browser/ui", + "//chrome/browser/web_applications", + "//chrome/browser/web_applications:web_app_group", + "//chrome/browser/web_applications/components", + "//chrome/test:test_support_ui", + "//extensions/browser", + "//extensions/common", + "//net:test_support", + ] +}
diff --git a/chrome/common/DEPS b/chrome/common/DEPS index 4aa2abe..b9b93a4 100644 --- a/chrome/common/DEPS +++ b/chrome/common/DEPS
@@ -29,7 +29,7 @@ "+components/net_log", "+components/network_session_configurator/common", "+components/ntp_tiles", - "+components/nux_google_apps", + "+components/nux", "+components/offline_pages/buildflags", "+components/password_manager/core/common", "+components/policy/core/common",
diff --git a/chrome/common/extensions/chrome_extensions_api_provider.cc b/chrome/common/extensions/chrome_extensions_api_provider.cc index 4248878..c8ecaf2 100644 --- a/chrome/common/extensions/chrome_extensions_api_provider.cc +++ b/chrome/common/extensions/chrome_extensions_api_provider.cc
@@ -9,6 +9,7 @@ #include "chrome/common/extensions/api/manifest_features.h" #include "chrome/common/extensions/api/permission_features.h" #include "chrome/common/extensions/chrome_aliases.h" +#include "chrome/common/extensions/chrome_manifest_handlers.h" #include "chrome/grit/common_resources.h" #include "extensions/common/features/json_feature_provider_source.h" #include "extensions/common/permissions/permissions_info.h" @@ -57,4 +58,8 @@ permissions_info->AddProvider(api_permissions_, GetChromePermissionAliases()); } +void ChromeExtensionsAPIProvider::RegisterManifestHandlers() { + RegisterChromeManifestHandlers(); +} + } // namespace extensions
diff --git a/chrome/common/extensions/chrome_extensions_api_provider.h b/chrome/common/extensions/chrome_extensions_api_provider.h index 5f214b9a..4e33a1e 100644 --- a/chrome/common/extensions/chrome_extensions_api_provider.h +++ b/chrome/common/extensions/chrome_extensions_api_provider.h
@@ -25,6 +25,7 @@ bool IsAPISchemaGenerated(const std::string& name) override; base::StringPiece GetAPISchema(const std::string& name) override; void AddPermissionsProviders(PermissionsInfo* permissions_info) override; + void RegisterManifestHandlers() override; private: const ChromeAPIPermissions api_permissions_;
diff --git a/chrome/common/extensions/chrome_extensions_client.cc b/chrome/common/extensions/chrome_extensions_client.cc index 3197172..254dc0a 100644 --- a/chrome/common/extensions/chrome_extensions_client.cc +++ b/chrome/common/extensions/chrome_extensions_client.cc
@@ -17,13 +17,11 @@ #include "chrome/common/chrome_switches.h" #include "chrome/common/extensions/api/extension_action/action_info.h" #include "chrome/common/extensions/chrome_extensions_api_provider.h" -#include "chrome/common/extensions/chrome_manifest_handlers.h" #include "chrome/common/extensions/manifest_handlers/theme_handler.h" #include "chrome/common/url_constants.h" #include "chrome/grit/chromium_strings.h" #include "components/version_info/version_info.h" #include "content/public/common/url_constants.h" -#include "extensions/common/common_manifest_handlers.h" #include "extensions/common/constants.h" #include "extensions/common/core_extensions_api_provider.h" #include "extensions/common/extension.h" @@ -32,7 +30,6 @@ #include "extensions/common/extension_urls.h" #include "extensions/common/features/feature_channel.h" #include "extensions/common/manifest_constants.h" -#include "extensions/common/manifest_handler.h" #include "extensions/common/manifest_handlers/icons_handler.h" #include "extensions/common/permissions/api_permission_set.h" #include "extensions/common/url_pattern.h" @@ -93,14 +90,6 @@ void ChromeExtensionsClient::Initialize() { SCOPED_UMA_HISTOGRAM_TIMER("Extensions.ChromeExtensionsClientInitTime"); - // Registration could already be finalized in unit tests, where the utility - // thread runs in-process. - if (!ManifestHandler::IsRegistrationFinalized()) { - RegisterCommonManifestHandlers(); - RegisterChromeManifestHandlers(); - ManifestHandler::FinalizeRegistration(); - } - // Set up the scripting whitelist. // Whitelist ChromeVox, an accessibility extension from Google that needs // the ability to script webui pages. This is temporary and is not
diff --git a/chrome/common/extensions/manifest_unittest.cc b/chrome/common/extensions/manifest_unittest.cc index 609714bc..0879fcf 100644 --- a/chrome/common/extensions/manifest_unittest.cc +++ b/chrome/common/extensions/manifest_unittest.cc
@@ -89,8 +89,8 @@ EXPECT_TRUE(manifest->GetString("unknown_key", &value)); EXPECT_EQ("foo", value); - // Test DeepCopy and Equals. - std::unique_ptr<Manifest> manifest2(manifest->DeepCopy()); + // Test CreateDeepCopy and Equals. + std::unique_ptr<Manifest> manifest2 = manifest->CreateDeepCopy(); EXPECT_TRUE(manifest->Equals(manifest2.get())); EXPECT_TRUE(manifest2->Equals(manifest.get())); MutateManifest(&manifest, "foo", std::make_unique<base::Value>("blah"));
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc index 866e018..7b7c6536 100644 --- a/chrome/common/pref_names.cc +++ b/chrome/common/pref_names.cc
@@ -880,6 +880,12 @@ extern const char kTPMFirmwareUpdateCleanupDismissed[] = "tpm_firmware_update.cleanup_dismissed"; +// Boolean pref indicating whether the NetBios Name Query Request Protocol is +// used for discovering shares on the user's network by the Network File +// Shares for Chrome OS feature. +const char kNetBiosShareDiscoveryEnabled[] = + "network_file_shares.netbios_discovery.enabled"; + #endif // defined(OS_CHROMEOS) // A boolean pref set to true if a Home button to open the Home pages should be
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h index 5d73987..9d8c15f2 100644 --- a/chrome/common/pref_names.h +++ b/chrome/common/pref_names.h
@@ -282,6 +282,7 @@ extern const char kNetworkFileSharesAllowed[]; extern const char kManagedSessionEnabled[]; extern const char kTPMFirmwareUpdateCleanupDismissed[]; +extern const char kNetBiosShareDiscoveryEnabled[]; #endif // defined(OS_CHROMEOS) extern const char kShowHomeButton[]; extern const char kSpeechRecognitionFilterProfanities[];
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index b31d28cd..9408de4 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -934,7 +934,6 @@ "../browser/ui/zoom/zoom_controller_browsertest.cc", "../browser/unload_browsertest.cc", "../browser/usb/usb_browsertest.cc", - "../browser/web_applications/extensions/pending_bookmark_app_manager_browsertest.cc", "../browser/web_bluetooth_browsertest.cc", "../common/mac/app_mode_chrome_locator_browsertest.mm", "../common/mac/mock_launchd.cc", @@ -994,6 +993,7 @@ "//chrome:strings", "//chrome/browser", "//chrome/browser/devtools:test_support", + "//chrome/browser/web_applications:browser_tests", "//chrome/renderer", "//chrome/services/removable_storage_writer:lib", "//components/autofill/content/browser:risk_proto",
diff --git a/chrome/test/data/policy/policy_test_cases.json b/chrome/test/data/policy/policy_test_cases.json index 9a6003ad..38d0d57 100644 --- a/chrome/test/data/policy/policy_test_cases.json +++ b/chrome/test/data/policy/policy_test_cases.json
@@ -3222,6 +3222,14 @@ "pref_mappings": [ { "pref": "ssl.client_certs.h2_coalescing_hosts", "local_state": true } ] }, + "NetBiosShareDiscoveryEnabled": { + "os": ["chromeos"], + "test_policy": { "NetBiosShareDiscoveryEnabled": true }, + "pref_mappings": [ + { "pref": "network_file_shares.netbios_discovery.enabled" } + ] + }, + "----- Chrome OS device policies ---------------------------------------": {}, "DevicePolicyRefreshRate": {
diff --git a/chrome/test/data/webui/extensions/runtime_hosts_dialog_test.js b/chrome/test/data/webui/extensions/runtime_hosts_dialog_test.js index 0e18d23..f29d75f 100644 --- a/chrome/test/data/webui/extensions/runtime_hosts_dialog_test.js +++ b/chrome/test/data/webui/extensions/runtime_hosts_dialog_test.js
@@ -36,7 +36,7 @@ let id = args[0]; let input = args[1]; assertEquals(ITEM_ID, id); - assertEquals(site, input); + assertEquals('http://www.example.com/*', input); }); }); @@ -66,7 +66,7 @@ delegate.acceptRuntimeHostPermission = false; const input = dialog.$$('cr-input'); - const site = 'http://http://http://'; + const site = 'http://....a'; input.value = site; input.fire('input'); assertFalse(input.invalid); @@ -81,12 +81,12 @@ }); test('editing current entry', function() { - const oldSite = 'http://example.com'; - const newSite = 'http://chromium.org'; + const oldPattern = 'http://example.com/*'; + const newPattern = 'http://chromium.org/*'; - dialog.currentSite = oldSite; + dialog.currentSite = oldPattern; const input = dialog.$$('cr-input'); - input.value = newSite; + input.value = newPattern; input.fire('input'); const submit = dialog.$.submit; @@ -94,12 +94,32 @@ return delegate.whenCalled('removeRuntimeHostPermission') .then((args) => { expectEquals(ITEM_ID, args[0] /* id */); - expectEquals(oldSite, args[1] /* site */); + expectEquals(oldPattern, args[1] /* pattern */); return delegate.whenCalled('addRuntimeHostPermission'); }) .then((args) => { expectEquals(ITEM_ID, args[0] /* id */); - expectEquals(newSite, args[1] /* site */); + expectEquals(newPattern, args[1] /* pattern */); }); }); + + test('get pattern from url', function() { + expectEquals( + 'https://example.com/*', + extensions.getPatternFromSite('https://example.com/*')); + expectEquals( + 'https://example.com/*', + extensions.getPatternFromSite('https://example.com/')); + expectEquals( + 'https://example.com/*', + extensions.getPatternFromSite('https://example.com')); + expectEquals( + 'https://*.example.com/*', + extensions.getPatternFromSite('https://*.example.com/*')); + expectEquals( + '*://example.com/*', extensions.getPatternFromSite('example.com')); + expectEquals( + 'https://example.com:80/*', + extensions.getPatternFromSite('https://example.com:80/*')); + }); });
diff --git a/chrome/test/data/webui/settings/cr_settings_browsertest.js b/chrome/test/data/webui/settings/cr_settings_browsertest.js index f426339..fe3bd4b 100644 --- a/chrome/test/data/webui/settings/cr_settings_browsertest.js +++ b/chrome/test/data/webui/settings/cr_settings_browsertest.js
@@ -831,7 +831,7 @@ __proto__: CrSettingsBrowserTest.prototype, /** - * The certificate-manager subpage is embeded in privacy_page.html. + * The certificate-manager subpage is embedded in privacy_page.html. * @override */ browsePreload: 'chrome://settings/privacy_page/privacy_page.html', @@ -1139,6 +1139,30 @@ * @constructor * @extends {CrSettingsBrowserTest} */ +function CrSettingsSiteListEntryTest() {} + +CrSettingsSiteListEntryTest.prototype = { + __proto__: CrSettingsBrowserTest.prototype, + + /** @override */ + browsePreload: 'chrome://settings/site_settings/site_list_entry.html', + + /** @override */ + extraLibraries: CrSettingsBrowserTest.prototype.extraLibraries.concat([ + '../cr_elements/cr_policy_strings.js', + 'site_list_entry_tests.js', + 'test_util.js', + ]), +}; + +TEST_F('CrSettingsSiteListEntryTest', 'All', function() { + mocha.run(); +}); + +/** + * @constructor + * @extends {CrSettingsBrowserTest} + */ function CrSettingsZoomLevelsTest() {} CrSettingsZoomLevelsTest.prototype = {
diff --git a/chrome/test/data/webui/settings/site_list_entry_tests.js b/chrome/test/data/webui/settings/site_list_entry_tests.js new file mode 100644 index 0000000..a2bf52e --- /dev/null +++ b/chrome/test/data/webui/settings/site_list_entry_tests.js
@@ -0,0 +1,36 @@ +// 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. + +/** @fileoverview Suite of tests for site-list-entry. */ + +suite('SiteListEntry', function() { + let testElement; + setup(function() { + testElement = document.createElement('site-list-entry'); + document.body.appendChild(testElement); + }); + + test('fires show-tooltip when mouse over policy indicator', function() { + testElement.model = { + controlledBy: chrome.settingsPrivate.ControlledBy.USER_POLICY, + enforcement: chrome.settingsPrivate.Enforcement.ENFORCED, + origin: 'http://example.com', + }; + Polymer.dom.flush(); + const prefIndicator = testElement.$$('cr-policy-pref-indicator'); + assertTrue(!!prefIndicator); + const icon = prefIndicator.$$('cr-tooltip-icon'); + const paperTooltip = icon.$$('paper-tooltip'); + const tooltip = paperTooltip.$.tooltip; + // Never shown since site-list will show a common tooltip. + assertEquals('none', tooltip.computedStyleMap().get('display').value); + assertFalse(paperTooltip._showing); + const wait = test_util.eventToPromise('show-tooltip', document); + icon.$.indicator.dispatchEvent(new MouseEvent('mouseenter')); + return wait.then(() => { + assertTrue(paperTooltip._showing); + assertEquals('none', tooltip.computedStyleMap().get('display').value); + }); + }); +});
diff --git a/chrome/test/data/webui/settings/site_list_tests.js b/chrome/test/data/webui/settings/site_list_tests.js index 627ffd7b..d1f674a 100644 --- a/chrome/test/data/webui/settings/site_list_tests.js +++ b/chrome/test/data/webui/settings/site_list_tests.js
@@ -882,6 +882,35 @@ assertEquals(settings.ContentSetting.ALLOW, args[3]); }); }); + + test('show-tooltip event fires on entry shows common tooltip', function() { + setUpCategory( + settings.ContentSettingsTypes.GEOLOCATION, + settings.ContentSetting.ALLOW, prefsGeolocation); + return browserProxy.whenCalled('getExceptionList').then(() => { + Polymer.dom.flush(); + const entry = + testElement.$.listContainer.querySelector('site-list-entry'); + const tooltip = testElement.$.tooltip; + + const testsParams = [ + ['a', testElement, new MouseEvent('mouseleave')], + ['b', testElement, new MouseEvent('tap')], + ['c', testElement, new Event('blur')], + ['d', tooltip, new MouseEvent('mouseenter')], + ]; + testsParams.forEach(params => { + const text = params[0]; + const eventTarget = params[1]; + const event = params[2]; + entry.fire('show-tooltip', {target: testElement, text}); + assertTrue(tooltip._showing); + assertEquals(text, tooltip.innerHTML.trim()); + eventTarget.dispatchEvent(event); + assertFalse(tooltip._showing); + }); + }); + }); }); suite('EditExceptionDialog', function() {
diff --git a/chrome/test/media_router/BUILD.gn b/chrome/test/media_router/BUILD.gn index 1997a98..a47a707 100644 --- a/chrome/test/media_router/BUILD.gn +++ b/chrome/test/media_router/BUILD.gn
@@ -2,6 +2,14 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +declare_args() { + # Many of the targets defined in this file have dependencies that cannot be + # satisfied without additional downstream resources. Explicitly guard them + # them behind this flag so that we do not attempt to build or isolate targets + # in public chromium checkouts. + enable_downstream_media_tests = false +} + source_set("browser_tests") { testonly = true defines = [ "HAS_OUT_OF_PROC_TEST_RUNNER" ] @@ -66,17 +74,19 @@ # Run separately from the Chromium waterfall with the external component # extension. See README.md -group("media_router_e2e_tests") { - testonly = true - data_deps = [ - ":browser_test_resources", - ":e2e_test_resources", - "//chrome/test:browser_tests", - ] - data = [ - "$root_out_dir/mr_extension/", - "internal/", - ] +if (enable_downstream_media_tests) { + group("media_router_e2e_tests") { + testonly = true + data_deps = [ + ":browser_test_resources", + ":e2e_test_resources", + "//chrome/test:browser_tests", + ] + data = [ + "$root_out_dir/mr_extension/", + "internal/", + ] + } } copy("e2e_test_resources") { @@ -91,16 +101,18 @@ } # Run separately. TODO: Documentation on how to run -group("swarming_tests") { - testonly = true - data_deps = [ - ":browser_test_resources", - "//chrome/test:browser_tests", - ] - data = [ - "internal/", - "$root_out_dir/mr_extension/", - ] +if (enable_downstream_media_tests) { + group("swarming_tests") { + testonly = true + data_deps = [ + ":browser_test_resources", + "//chrome/test:browser_tests", + ] + data = [ + "internal/", + "$root_out_dir/mr_extension/", + ] + } } source_set("test_support") { @@ -129,20 +141,22 @@ ] } -group("media_router_perf_tests") { - testonly = true - data = [ - "$root_out_dir/media_router/telemetry_extension/", - "$root_out_dir/mr_extension/release/", - "internal/", - "telemetry/", - ] - deps = [ - "//tools/perf:perf", - ] - data_deps = [ - ":telemetry_extension_resources", - ] +if (enable_downstream_media_tests) { + group("media_router_perf_tests") { + testonly = true + data = [ + "$root_out_dir/media_router/telemetry_extension/", + "$root_out_dir/mr_extension/release/", + "internal/", + "telemetry/", + ] + deps = [ + "//tools/perf:perf", + ] + data_deps = [ + ":telemetry_extension_resources", + ] + } } copy("telemetry_extension_resources") {
diff --git a/chrome_elf/pe_image_safe/pe_image_safe.cc b/chrome_elf/pe_image_safe/pe_image_safe.cc index 7778c5ec..4f30d8f 100644 --- a/chrome_elf/pe_image_safe/pe_image_safe.cc +++ b/chrome_elf/pe_image_safe/pe_image_safe.cc
@@ -73,8 +73,8 @@ PIMAGE_OPTIONAL_HEADER optional_header = reinterpret_cast<PIMAGE_OPTIONAL_HEADER>( reinterpret_cast<char*>(file_header) + sizeof(IMAGE_FILE_HEADER)); - DWORD optional_header_offset = reinterpret_cast<char*>(optional_header) - - reinterpret_cast<char*>(dos_header_); + uintptr_t optional_header_offset = reinterpret_cast<char*>(optional_header) - + reinterpret_cast<char*>(dos_header_); if (optional_header_offset + sizeof(IMAGE_OPTIONAL_HEADER::Magic) > image_size_) { return nullptr;
diff --git a/chrome_elf/third_party_dlls/hook.cc b/chrome_elf/third_party_dlls/hook.cc index 85014b6..af9d1e5 100644 --- a/chrome_elf/third_party_dlls/hook.cc +++ b/chrome_elf/third_party_dlls/hook.cc
@@ -4,6 +4,7 @@ #include "chrome_elf/third_party_dlls/hook.h" +#include <limits> #include <memory> #include <assert.h> @@ -280,8 +281,15 @@ std::string image_name; std::string section_path; std::string section_basename; - if (!GetDataFromImage(*base, *view_size, &time_date_stamp, &image_size, - &image_name, §ion_path, §ion_basename)) { + + assert(*view_size < std::numeric_limits<DWORD>::max()); + // A memory section can be > 32-bits, but an image/PE in memory can only be <= + // 32-bits in size. That's a limitation of Windows and its interactions with + // processors. No section that appears to be an image (checked above) should + // have such a large size. + if (!GetDataFromImage(*base, static_cast<DWORD>(*view_size), &time_date_stamp, + &image_size, &image_name, §ion_path, + §ion_basename)) { return ret; }
diff --git a/chrome_elf/third_party_dlls/logs.cc b/chrome_elf/third_party_dlls/logs.cc index de63f3d..72cc5e9 100644 --- a/chrome_elf/third_party_dlls/logs.cc +++ b/chrome_elf/third_party_dlls/logs.cc
@@ -122,9 +122,9 @@ // logging events should be added via AddEntry(). void InsertAtEnd(std::vector<LogEntryInternal>::iterator first_element, uint32_t count) { - uint32_t elements = (entries_.size() + count <= kMaxLogEntries) - ? count - : kMaxLogEntries - entries_.size(); + size_t elements = (entries_.size() + count <= kMaxLogEntries) + ? count + : kMaxLogEntries - entries_.size(); assert(elements <= count); if (elements)
diff --git a/chrome_elf/third_party_dlls/main.cc b/chrome_elf/third_party_dlls/main.cc index 48442ced..4169884 100644 --- a/chrome_elf/third_party_dlls/main.cc +++ b/chrome_elf/third_party_dlls/main.cc
@@ -4,6 +4,8 @@ #include "chrome_elf/third_party_dlls/main.h" +#include <limits> + #include <windows.h> #include <versionhelpers.h> @@ -73,8 +75,10 @@ AddStatusCodeToBuffer(code, &value_bytes); + assert(value_bytes.size() < std::numeric_limits<DWORD>::max()); nt::SetRegKeyValue(key_handle, kStatusCodesRegValue, REG_BINARY, - value_bytes.data(), value_bytes.size()); + value_bytes.data(), + static_cast<DWORD>(value_bytes.size())); nt::CloseRegKey(key_handle); return;
diff --git a/chromecast/browser/BUILD.gn b/chromecast/browser/BUILD.gn index 62b9e42..affa69e 100644 --- a/chromecast/browser/BUILD.gn +++ b/chromecast/browser/BUILD.gn
@@ -277,6 +277,8 @@ "extensions/cast_extension_web_contents_observer.h", "extensions/cast_extensions_api_client.cc", "extensions/cast_extensions_api_client.h", + "extensions/cast_extensions_browser_api_provider.cc", + "extensions/cast_extensions_browser_api_provider.h", "extensions/cast_extensions_browser_client.cc", "extensions/cast_extensions_browser_client.h", "extensions/cast_prefs.cc", @@ -315,6 +317,7 @@ "//components/version_info", "//components/zoom", "//extensions/browser", + "//extensions/browser:core_api_provider", "//extensions/common", "//extensions/common/api", "//google_apis:google_apis",
diff --git a/chromecast/browser/extensions/cast_extensions_browser_api_provider.cc b/chromecast/browser/extensions/cast_extensions_browser_api_provider.cc new file mode 100644 index 0000000..8edf4029 --- /dev/null +++ b/chromecast/browser/extensions/cast_extensions_browser_api_provider.cc
@@ -0,0 +1,19 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chromecast/browser/extensions/cast_extensions_browser_api_provider.h" + +#include "chromecast/browser/extensions/api/generated_api_registration.h" + +namespace extensions { + +CastExtensionsBrowserAPIProvider::CastExtensionsBrowserAPIProvider() = default; +CastExtensionsBrowserAPIProvider::~CastExtensionsBrowserAPIProvider() = default; + +void CastExtensionsBrowserAPIProvider::RegisterExtensionFunctions( + ExtensionFunctionRegistry* registry) { + cast::api::CastGeneratedFunctionRegistry::RegisterAll(registry); +} + +} // namespace extensions
diff --git a/chromecast/browser/extensions/cast_extensions_browser_api_provider.h b/chromecast/browser/extensions/cast_extensions_browser_api_provider.h new file mode 100644 index 0000000..d2433cc --- /dev/null +++ b/chromecast/browser/extensions/cast_extensions_browser_api_provider.h
@@ -0,0 +1,26 @@ +// 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 CHROMECAST_BROWSER_EXTENSIONS_CAST_EXTENSIONS_BROWSER_API_PROVIDER_H_ +#define CHROMECAST_BROWSER_EXTENSIONS_CAST_EXTENSIONS_BROWSER_API_PROVIDER_H_ + +#include "base/macros.h" +#include "extensions/browser/extensions_browser_api_provider.h" + +namespace extensions { + +class CastExtensionsBrowserAPIProvider : public ExtensionsBrowserAPIProvider { + public: + CastExtensionsBrowserAPIProvider(); + ~CastExtensionsBrowserAPIProvider() override; + + void RegisterExtensionFunctions(ExtensionFunctionRegistry* registry) override; + + private: + DISALLOW_COPY_AND_ASSIGN(CastExtensionsBrowserAPIProvider); +}; + +} // namespace extensions + +#endif // CHROMECAST_BROWSER_EXTENSIONS_CAST_EXTENSIONS_BROWSER_API_PROVIDER_H_
diff --git a/chromecast/browser/extensions/cast_extensions_browser_client.cc b/chromecast/browser/extensions/cast_extensions_browser_client.cc index 71be0cb5..9e302ad 100644 --- a/chromecast/browser/extensions/cast_extensions_browser_client.cc +++ b/chromecast/browser/extensions/cast_extensions_browser_client.cc
@@ -8,21 +8,20 @@ #include "base/memory/ptr_util.h" #include "build/build_config.h" -#include "chromecast/browser/extensions/api/generated_api_registration.h" #include "chromecast/browser/extensions/cast_extension_host_delegate.h" #include "chromecast/browser/extensions/cast_extension_system_factory.h" #include "chromecast/browser/extensions/cast_extension_web_contents_observer.h" #include "chromecast/browser/extensions/cast_extensions_api_client.h" +#include "chromecast/browser/extensions/cast_extensions_browser_api_provider.h" #include "components/version_info/version_info.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/render_frame_host.h" #include "content/public/browser/resource_request_info.h" #include "extensions/browser/api/extensions_api_client.h" -#include "extensions/browser/api/generated_api_registration.h" #include "extensions/browser/api/runtime/runtime_api_delegate.h" +#include "extensions/browser/core_extensions_browser_api_provider.h" #include "extensions/browser/event_router.h" -#include "extensions/browser/extension_function_registry.h" #include "extensions/browser/mojo/interface_registration.h" #include "extensions/browser/null_app_sorting.h" #include "extensions/browser/updater/null_extension_cache.h" @@ -43,6 +42,9 @@ // Set to UNKNOWN to enable all APIs. // TODO(achaulk): figure out what channel to use here. SetCurrentChannel(version_info::Channel::UNKNOWN); + + AddAPIProvider(std::make_unique<CoreExtensionsBrowserAPIProvider>()); + AddAPIProvider(std::make_unique<CastExtensionsBrowserAPIProvider>()); } CastExtensionsBrowserClient::~CastExtensionsBrowserClient() {} @@ -193,15 +195,6 @@ return CastExtensionSystemFactory::GetInstance(); } -void CastExtensionsBrowserClient::RegisterExtensionFunctions( - ExtensionFunctionRegistry* registry) const { - // Register core extension-system APIs. - api::GeneratedFunctionRegistry::RegisterAll(registry); - - // cast_shell-only APIs. - cast::api::CastGeneratedFunctionRegistry::RegisterAll(registry); -} - void CastExtensionsBrowserClient::RegisterExtensionInterfaces( service_manager::BinderRegistryWithArgs<content::RenderFrameHost*>* registry,
diff --git a/chromecast/browser/extensions/cast_extensions_browser_client.h b/chromecast/browser/extensions/cast_extensions_browser_client.h index 984abf0..223b337a 100644 --- a/chromecast/browser/extensions/cast_extensions_browser_client.h +++ b/chromecast/browser/extensions/cast_extensions_browser_client.h
@@ -88,8 +88,6 @@ bool IsAppModeForcedForApp(const ExtensionId& id) override; bool IsLoggedInAsPublicAccount() override; ExtensionSystemProvider* GetExtensionSystemFactory() override; - void RegisterExtensionFunctions( - ExtensionFunctionRegistry* registry) const override; void RegisterExtensionInterfaces(service_manager::BinderRegistryWithArgs< content::RenderFrameHost*>* registry, content::RenderFrameHost* render_frame_host,
diff --git a/chromecast/common/cast_extensions_api_provider.cc b/chromecast/common/cast_extensions_api_provider.cc index ced0434..881d2966 100644 --- a/chromecast/common/cast_extensions_api_provider.cc +++ b/chromecast/common/cast_extensions_api_provider.cc
@@ -4,6 +4,7 @@ #include "chromecast/common/cast_extensions_api_provider.h" +#include "chromecast/common/cast_redirect_manifest_handler.h" #include "chromecast/common/extensions_api/cast_aliases.h" #include "chromecast/common/extensions_api/cast_api_features.h" #include "chromecast/common/extensions_api/cast_api_permissions.h" @@ -11,6 +12,9 @@ #include "chromecast/common/extensions_api/cast_permission_features.h" #include "chromecast/common/extensions_api/generated_schemas.h" #include "extensions/common/features/json_feature_provider_source.h" +#include "extensions/common/manifest_handler.h" +#include "extensions/common/manifest_handlers/automation.h" +#include "extensions/common/manifest_handlers/content_scripts_handler.h" #include "extensions/common/permissions/permissions_info.h" #include "extensions/shell/grit/app_shell_resources.h" @@ -55,4 +59,10 @@ permissions_info->AddProvider(api_permissions_, GetCastPermissionAliases()); } +void CastExtensionsAPIProvider::RegisterManifestHandlers() { + (new AutomationHandler)->Register(); // TODO(crbug/837773) De-dupe later. + (new chromecast::CastRedirectHandler)->Register(); + (new ContentScriptsHandler)->Register(); +} + } // namespace extensions
diff --git a/chromecast/common/cast_extensions_api_provider.h b/chromecast/common/cast_extensions_api_provider.h index bdd187a..9a7db3cf 100644 --- a/chromecast/common/cast_extensions_api_provider.h +++ b/chromecast/common/cast_extensions_api_provider.h
@@ -25,6 +25,7 @@ bool IsAPISchemaGenerated(const std::string& name) override; base::StringPiece GetAPISchema(const std::string& name) override; void AddPermissionsProviders(PermissionsInfo* permissions_info) override; + void RegisterManifestHandlers() override; private: const CastAPIPermissions api_permissions_;
diff --git a/chromecast/common/cast_extensions_client.cc b/chromecast/common/cast_extensions_client.cc index 8a503e5..29472362 100644 --- a/chromecast/common/cast_extensions_client.cc +++ b/chromecast/common/cast_extensions_client.cc
@@ -11,7 +11,6 @@ #include "base/macros.h" #include "base/no_destructor.h" #include "chromecast/common/cast_extensions_api_provider.h" -#include "chromecast/common/cast_redirect_manifest_handler.h" #include "components/version_info/version_info.h" #include "content/public/common/user_agent.h" #include "extensions/common/api/api_features.h" @@ -19,15 +18,11 @@ #include "extensions/common/api/generated_schemas.h" #include "extensions/common/api/manifest_features.h" #include "extensions/common/api/permission_features.h" -#include "extensions/common/common_manifest_handlers.h" #include "extensions/common/core_extensions_api_provider.h" #include "extensions/common/extension_urls.h" #include "extensions/common/features/feature_provider.h" #include "extensions/common/features/manifest_feature.h" #include "extensions/common/features/simple_feature.h" -#include "extensions/common/manifest_handler.h" -#include "extensions/common/manifest_handlers/automation.h" -#include "extensions/common/manifest_handlers/content_scripts_handler.h" #include "extensions/common/permissions/permission_message_provider.h" #include "extensions/common/url_pattern_set.h" @@ -35,13 +30,6 @@ namespace { -void RegisterCastManifestHandlers() { - DCHECK(!ManifestHandler::IsRegistrationFinalized()); - (new AutomationHandler)->Register(); // TODO(crbug/837773) De-dupe later. - (new chromecast::CastRedirectHandler)->Register(); - (new ContentScriptsHandler)->Register(); -} - // TODO(jamescook): Refactor ChromePermissionsMessageProvider so we can share // code. For now, this implementation does nothing. class ShellPermissionMessageProvider : public PermissionMessageProvider { @@ -85,9 +73,6 @@ CastExtensionsClient::~CastExtensionsClient() {} void CastExtensionsClient::Initialize() { - RegisterCommonManifestHandlers(); - RegisterCastManifestHandlers(); - ManifestHandler::FinalizeRegistration(); // TODO(jamescook): Do we need to whitelist any extensions? }
diff --git a/chromecast/public/media/media_pipeline_device_params.h b/chromecast/public/media/media_pipeline_device_params.h index 5f110a99..cf656b8 100644 --- a/chromecast/public/media/media_pipeline_device_params.h +++ b/chromecast/public/media/media_pipeline_device_params.h
@@ -72,7 +72,7 @@ MediaPipelineDeviceParams(const MediaPipelineDeviceParams& other); MediaPipelineDeviceParams(MediaPipelineDeviceParams&& other); - const MediaSyncType sync_type; + MediaSyncType sync_type; const AudioStreamType audio_type; // task_runner allows backend implementations to post tasks to the media
diff --git a/components/OWNERS b/components/OWNERS index 4544b2b..994a18aa 100644 --- a/components/OWNERS +++ b/components/OWNERS
@@ -13,7 +13,7 @@ per-file dom_distiller_strings.grdp=file://components/dom_distiller/OWNERS per-file error_page_strings.grdp=file://components/error_page/OWNERS per-file ntp_snippets_strings.grdp=file://components/ntp_snippets/OWNERS -per-file nux_google_apps_strings.grdp=file://components/nux_google_apps/OWNERS +per-file nux_google_apps_strings.grdp=file://components/nux/OWNERS per-file omnibox_strings.grdp=file://components/omnibox/OWNERS per-file page_info_strings.grdp=file://chrome/browser/ui/page_info/OWNERS per-file page_info_strings_grdp=file://chrome/browser/ui/page_info/OWNERS
diff --git a/components/autofill_strings.grdp b/components/autofill_strings.grdp index e4e3ffa..7bc8f22 100644 --- a/components/autofill_strings.grdp +++ b/components/autofill_strings.grdp
@@ -448,27 +448,39 @@ <message name="IDS_AUTOFILL_ADDRESSES" desc="Title for the list of addresses that chrome has saved for use in filling in forms."> Addresses </message> + <message name="IDS_AUTOFILL_ENABLE_PROFILES_TOGGLE_SUBLABEL" desc="Sublabel for a toggle that allows users to control whether addresses should be saved and forms should be autofilled with them."> + Includes information like phone numbers, email addresses, and shipping addresses + </message> + <message name="IDS_AUTOFILL_ENABLE_CREDIT_CARDS_TOGGLE_SUBLABEL" desc="Sublabel for a toggle that allows users to control whether credit cards should be saved and forms should be autofilled with it."> + Makes it faster to pay for things online + </message> <if expr="not is_ios"> <then> - <message name="IDS_AUTOFILL_PAYMENT_METHODS" desc="Title for the list of saved payment methods that can be used to fill in forms. Sentence-Cased."> + <message name="IDS_AUTOFILL_ADDRESSES_SETTINGS_TITLE" desc="Title for the Autofill settings page that allows user to manage their list of saved addresses and Autofill preferences for addresses. Sentence-Cased."> + Addresses and more + </message> + <message name="IDS_AUTOFILL_PAYMENT_METHODS" desc="Title for the list of saved payment methods that can be used to fill in forms. Also used as the title for the Autofill settings page that allows user to manage their list of saved payment methods and Autofill preferences for payment methods. Sentence-Cased."> Payment methods </message> <message name="IDS_AUTOFILL_ENABLE_PROFILES_TOGGLE_LABEL" desc="Label for a toggle that allows users to control whether addresses should be saved and forms should be autofilled with them. Sentence-Cased."> - Save and fill addresses + Remember addresses and other information </message> <message name="IDS_AUTOFILL_ENABLE_CREDIT_CARDS_TOGGLE_LABEL" desc="Label for a toggle that allows users to control whether credit cards should be saved and forms should be autofilled with it. Sentence-Cased."> - Save and fill payment methods + Remember payment methods </message> </then> <else> - <message name="IDS_AUTOFILL_PAYMENT_METHODS" desc="Title for the list of saved payment methods that can be used to fill in forms. Title-Cased."> + <message name="IDS_AUTOFILL_ADDRESSES_SETTINGS_TITLE" desc="Title for the Autofill settings page that allows user to manage their list of saved addresses and Autofill preferences for addresses. Title-Cased."> + Addresses and More + </message> + <message name="IDS_AUTOFILL_PAYMENT_METHODS" desc="Title for the list of saved payment methods that can be used to fill in forms. Also used as the title for the Autofill settings page that allows user to manage their list of saved payment methods and Autofill preferences for payment methods. Title-Cased."> Payment Methods </message> <message name="IDS_AUTOFILL_ENABLE_PROFILES_TOGGLE_LABEL" desc="Label for a toggle that allows users to control whether addresses should be saved and forms should be autofilled with them. Title-Cased."> - Save and Fill Addresses + Remember Addresses and Other Information </message> <message name="IDS_AUTOFILL_ENABLE_CREDIT_CARDS_TOGGLE_LABEL" desc="Label for a toggle that allows users to control whether credit cards should be saved and forms should be autofilled with it. Title-Cased."> - Save and Fill Payment Methods + Remember Payment Methods </message> </else> </if>
diff --git a/components/mirroring/browser/single_client_video_capture_host.cc b/components/mirroring/browser/single_client_video_capture_host.cc index aa16cb85e..8193730 100644 --- a/components/mirroring/browser/single_client_video_capture_host.cc +++ b/components/mirroring/browser/single_client_video_capture_host.cc
@@ -30,9 +30,9 @@ video_capture_host_->OnDeviceLaunched(std::move(device)); } - void OnDeviceLaunchFailed() override { + void OnDeviceLaunchFailed(media::VideoCaptureError error) override { if (video_capture_host_) - video_capture_host_->OnDeviceLaunchFailed(); + video_capture_host_->OnDeviceLaunchFailed(error); } void OnDeviceLaunchAborted() override { @@ -86,7 +86,9 @@ launcher->LaunchDeviceAsync( device_id_, type_, params, weak_factory_.GetWeakPtr(), base::BindOnce(&SingleClientVideoCaptureHost::OnError, - weak_factory_.GetWeakPtr()), + weak_factory_.GetWeakPtr(), + media::VideoCaptureError:: + kSingleClientVideoCaptureHostLostConnectionToDevice), callbacks, // The |device_launcher| and |device_launcher_callbacks| must be kept // alive until the device launching completes. @@ -221,7 +223,7 @@ } } -void SingleClientVideoCaptureHost::OnError() { +void SingleClientVideoCaptureHost::OnError(media::VideoCaptureError) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); VLOG(1) << __func__; if (observer_) @@ -251,16 +253,18 @@ launched_device_ = std::move(device); } -void SingleClientVideoCaptureHost::OnDeviceLaunchFailed() { +void SingleClientVideoCaptureHost::OnDeviceLaunchFailed( + media::VideoCaptureError error) { DVLOG(1) << __func__; launched_device_ = nullptr; - OnError(); + OnError(error); } void SingleClientVideoCaptureHost::OnDeviceLaunchAborted() { DVLOG(1) << __func__; launched_device_ = nullptr; - OnError(); + OnError( + media::VideoCaptureError::kSingleClientVideoCaptureDeviceLaunchAborted); } void SingleClientVideoCaptureHost::OnFinishedConsumingBuffer(
diff --git a/components/mirroring/browser/single_client_video_capture_host.h b/components/mirroring/browser/single_client_video_capture_host.h index 20fd5f1d..5e0a455a 100644 --- a/components/mirroring/browser/single_client_video_capture_host.h +++ b/components/mirroring/browser/single_client_video_capture_host.h
@@ -78,14 +78,14 @@ buffer_read_permission, media::mojom::VideoFrameInfoPtr frame_info) override; void OnBufferRetired(int buffer_id) override; - void OnError() override; + void OnError(media::VideoCaptureError error) override; void OnLog(const std::string& message) override; void OnStarted() override; void OnStartedUsingGpuDecode() override; void OnDeviceLaunched( std::unique_ptr<content::LaunchedVideoCaptureDevice> device); - void OnDeviceLaunchFailed(); + void OnDeviceLaunchFailed(media::VideoCaptureError error); void OnDeviceLaunchAborted(); private:
diff --git a/components/nux_google_apps/BUILD.gn b/components/nux/BUILD.gn similarity index 77% rename from components/nux_google_apps/BUILD.gn rename to components/nux/BUILD.gn index 833a110..87cb308 100644 --- a/components/nux_google_apps/BUILD.gn +++ b/components/nux/BUILD.gn
@@ -5,12 +5,12 @@ import("//build/config/chrome_build.gni") if (is_win && is_chrome_branded) { - static_library("nux_google_apps_feature") { + static_library("google_apps_feature") { sources = [ - "constants.cc", - "constants.h", - "google_apps_handler.cc", - "google_apps_handler.h", + "google_apps/constants.cc", + "google_apps/constants.h", + "google_apps/google_apps_handler.cc", + "google_apps/google_apps_handler.h", ] public_deps = [
diff --git a/components/nux_google_apps/DEPS b/components/nux/DEPS similarity index 100% rename from components/nux_google_apps/DEPS rename to components/nux/DEPS
diff --git a/components/nux_google_apps/README b/components/nux/README similarity index 100% rename from components/nux_google_apps/README rename to components/nux/README
diff --git a/components/nux_google_apps/constants.cc b/components/nux/google_apps/constants.cc similarity index 77% rename from components/nux_google_apps/constants.cc rename to components/nux/google_apps/constants.cc index 7b63d0c..a2d8b31 100644 --- a/components/nux_google_apps/constants.cc +++ b/components/nux/google_apps/constants.cc
@@ -2,15 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "components/nux_google_apps/constants.h" +#include "components/nux/google_apps/constants.h" #include "base/feature_list.h" -namespace nux_google_apps { +namespace nux { extern const base::Feature kNuxGoogleAppsFeature{ "NuxGoogleApps", base::FEATURE_DISABLED_BY_DEFAULT}; extern const char kNuxGoogleAppsUrl[] = "chrome://welcome/apps"; -} // namespace nux_google_apps \ No newline at end of file +} // namespace nux \ No newline at end of file
diff --git a/components/nux_google_apps/constants.h b/components/nux/google_apps/constants.h similarity index 88% rename from components/nux_google_apps/constants.h rename to components/nux/google_apps/constants.h index 938277d..94f8be64 100644 --- a/components/nux_google_apps/constants.h +++ b/components/nux/google_apps/constants.h
@@ -9,11 +9,11 @@ struct Feature; } // namespace base -namespace nux_google_apps { +namespace nux { extern const base::Feature kNuxGoogleAppsFeature; extern const char kNuxGoogleAppsUrl[]; -} // namespace nux_google_apps +} // namespace nux #endif // COMPONENTS_NUX_GOOGLE_APPS_CONSTANTS_H_
diff --git a/components/nux_google_apps/google_apps_handler.cc b/components/nux/google_apps/google_apps_handler.cc similarity index 97% rename from components/nux_google_apps/google_apps_handler.cc rename to components/nux/google_apps/google_apps_handler.cc index 282ccfa..abbea96 100644 --- a/components/nux_google_apps/google_apps_handler.cc +++ b/components/nux/google_apps/google_apps_handler.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "components/nux_google_apps/google_apps_handler.h" +#include "components/nux/google_apps/google_apps_handler.h" #include "base/bind.h" #include "base/metrics/field_trial_params.h" @@ -14,8 +14,8 @@ #include "components/favicon/core/favicon_service.h" #include "components/grit/components_resources.h" #include "components/grit/components_scaled_resources.h" +#include "components/nux/google_apps/constants.h" #include "components/nux/show_promo_delegate.h" -#include "components/nux_google_apps/constants.h" #include "components/prefs/pref_service.h" #include "components/strings/grit/components_strings.h" #include "content/public/browser/web_contents.h" @@ -23,7 +23,7 @@ #include "content/public/browser/web_ui_data_source.h" #include "ui/base/resource/resource_bundle.h" -namespace nux_google_apps { +namespace nux { // These values are persisted to logs. Entries should not be renumbered and // numeric values should never be reused. @@ -182,4 +182,4 @@ IDR_NUX_GOOGLE_APPS_YOUTUBE_2X); } -} // namespace nux_google_apps \ No newline at end of file +} // namespace nux \ No newline at end of file
diff --git a/components/nux_google_apps/google_apps_handler.h b/components/nux/google_apps/google_apps_handler.h similarity index 96% rename from components/nux_google_apps/google_apps_handler.h rename to components/nux/google_apps/google_apps_handler.h index 4901740..b0c151f 100644 --- a/components/nux_google_apps/google_apps_handler.h +++ b/components/nux/google_apps/google_apps_handler.h
@@ -23,7 +23,7 @@ class FaviconService; } // namespace favicon -namespace nux_google_apps { +namespace nux { extern const char* kGoogleAppsInteractionHistogram; @@ -66,6 +66,6 @@ DISALLOW_COPY_AND_ASSIGN(GoogleAppsHandler); }; -} // namespace nux_google_apps +} // namespace nux #endif // COMPONENTS_NUX_GOOGLE_APPS_GOOGLE_APPS_HANDLER_H_
diff --git a/components/nux_google_apps/resources/BUILD.gn b/components/nux/google_apps/resources/BUILD.gn similarity index 100% rename from components/nux_google_apps/resources/BUILD.gn rename to components/nux/google_apps/resources/BUILD.gn
diff --git a/components/nux_google_apps/resources/apps_chooser.html b/components/nux/google_apps/resources/apps_chooser.html similarity index 100% rename from components/nux_google_apps/resources/apps_chooser.html rename to components/nux/google_apps/resources/apps_chooser.html
diff --git a/components/nux_google_apps/resources/apps_chooser.js b/components/nux/google_apps/resources/apps_chooser.js similarity index 100% rename from components/nux_google_apps/resources/apps_chooser.js rename to components/nux/google_apps/resources/apps_chooser.js
diff --git a/components/nux_google_apps/resources/chrome_store_24dp_1x.png b/components/nux/google_apps/resources/chrome_store_24dp_1x.png similarity index 100% rename from components/nux_google_apps/resources/chrome_store_24dp_1x.png rename to components/nux/google_apps/resources/chrome_store_24dp_1x.png Binary files differ
diff --git a/components/nux_google_apps/resources/chrome_store_24dp_2x.png b/components/nux/google_apps/resources/chrome_store_24dp_2x.png similarity index 100% rename from components/nux_google_apps/resources/chrome_store_24dp_2x.png rename to components/nux/google_apps/resources/chrome_store_24dp_2x.png Binary files differ
diff --git a/components/nux_google_apps/resources/gmail_24dp_1x.png b/components/nux/google_apps/resources/gmail_24dp_1x.png similarity index 100% rename from components/nux_google_apps/resources/gmail_24dp_1x.png rename to components/nux/google_apps/resources/gmail_24dp_1x.png Binary files differ
diff --git a/components/nux_google_apps/resources/gmail_24dp_2x.png b/components/nux/google_apps/resources/gmail_24dp_2x.png similarity index 100% rename from components/nux_google_apps/resources/gmail_24dp_2x.png rename to components/nux/google_apps/resources/gmail_24dp_2x.png Binary files differ
diff --git a/components/nux_google_apps/resources/maps_24dp_1x.png b/components/nux/google_apps/resources/maps_24dp_1x.png similarity index 100% rename from components/nux_google_apps/resources/maps_24dp_1x.png rename to components/nux/google_apps/resources/maps_24dp_1x.png Binary files differ
diff --git a/components/nux_google_apps/resources/maps_24dp_2x.png b/components/nux/google_apps/resources/maps_24dp_2x.png similarity index 100% rename from components/nux_google_apps/resources/maps_24dp_2x.png rename to components/nux/google_apps/resources/maps_24dp_2x.png Binary files differ
diff --git a/components/nux_google_apps/resources/news_24dp_1x.png b/components/nux/google_apps/resources/news_24dp_1x.png similarity index 100% rename from components/nux_google_apps/resources/news_24dp_1x.png rename to components/nux/google_apps/resources/news_24dp_1x.png Binary files differ
diff --git a/components/nux_google_apps/resources/news_24dp_2x.png b/components/nux/google_apps/resources/news_24dp_2x.png similarity index 100% rename from components/nux_google_apps/resources/news_24dp_2x.png rename to components/nux/google_apps/resources/news_24dp_2x.png Binary files differ
diff --git a/components/nux_google_apps/resources/nux_google_apps.html b/components/nux/google_apps/resources/nux_google_apps.html similarity index 100% rename from components/nux_google_apps/resources/nux_google_apps.html rename to components/nux/google_apps/resources/nux_google_apps.html
diff --git a/components/nux_google_apps/resources/nux_google_apps.js b/components/nux/google_apps/resources/nux_google_apps.js similarity index 100% rename from components/nux_google_apps/resources/nux_google_apps.js rename to components/nux/google_apps/resources/nux_google_apps.js
diff --git a/components/nux_google_apps/resources/nux_google_apps_proxy.html b/components/nux/google_apps/resources/nux_google_apps_proxy.html similarity index 100% rename from components/nux_google_apps/resources/nux_google_apps_proxy.html rename to components/nux/google_apps/resources/nux_google_apps_proxy.html
diff --git a/components/nux_google_apps/resources/nux_google_apps_proxy.js b/components/nux/google_apps/resources/nux_google_apps_proxy.js similarity index 100% rename from components/nux_google_apps/resources/nux_google_apps_proxy.js rename to components/nux/google_apps/resources/nux_google_apps_proxy.js
diff --git a/components/nux_google_apps/resources/translate_24dp_1x.png b/components/nux/google_apps/resources/translate_24dp_1x.png similarity index 100% rename from components/nux_google_apps/resources/translate_24dp_1x.png rename to components/nux/google_apps/resources/translate_24dp_1x.png Binary files differ
diff --git a/components/nux_google_apps/resources/translate_24dp_2x.png b/components/nux/google_apps/resources/translate_24dp_2x.png similarity index 100% rename from components/nux_google_apps/resources/translate_24dp_2x.png rename to components/nux/google_apps/resources/translate_24dp_2x.png Binary files differ
diff --git a/components/nux_google_apps/resources/youtube_24dp_1x.png b/components/nux/google_apps/resources/youtube_24dp_1x.png similarity index 100% rename from components/nux_google_apps/resources/youtube_24dp_1x.png rename to components/nux/google_apps/resources/youtube_24dp_1x.png Binary files differ
diff --git a/components/nux_google_apps/resources/youtube_24dp_2x.png b/components/nux/google_apps/resources/youtube_24dp_2x.png similarity index 100% rename from components/nux_google_apps/resources/youtube_24dp_2x.png rename to components/nux/google_apps/resources/youtube_24dp_2x.png Binary files differ
diff --git a/components/nux_google_apps/OWNERS b/components/nux_google_apps/OWNERS deleted file mode 100644 index 08ee1a9..0000000 --- a/components/nux_google_apps/OWNERS +++ /dev/null
@@ -1 +0,0 @@ -hcarmona@chromium.org
diff --git a/components/password_manager/ios/BUILD.gn b/components/password_manager/ios/BUILD.gn index c53bf96..6939676 100644 --- a/components/password_manager/ios/BUILD.gn +++ b/components/password_manager/ios/BUILD.gn
@@ -8,6 +8,10 @@ deps = [ "//base", "//components/autofill/core/common", + "//components/autofill/ios/browser", + "//components/autofill/ios/form_util", + "//components/password_manager/core/browser", + "//components/password_manager/core/browser/form_parsing", "//ios/web/public", "//url", ] @@ -17,6 +21,8 @@ "account_select_fill_data.h", "js_password_manager.h", "js_password_manager.mm", + "password_controller_helper.h", + "password_controller_helper.mm", ] } @@ -39,6 +45,7 @@ testonly = true sources = [ "account_select_fill_data_unittest.cc", + "password_controller_helper_unittest.mm", ] deps = [ ":ios",
diff --git a/components/password_manager/ios/DEPS b/components/password_manager/ios/DEPS index cb7366a..ffdd656a 100644 --- a/components/password_manager/ios/DEPS +++ b/components/password_manager/ios/DEPS
@@ -1,4 +1,6 @@ include_rules = [ "+components/autofill/core/common", + "+components/autofill/ios/browser", + "+components/autofill/ios/form_util", "+ios/web/public", ]
diff --git a/components/password_manager/ios/password_controller_helper.h b/components/password_manager/ios/password_controller_helper.h new file mode 100644 index 0000000..05f22db --- /dev/null +++ b/components/password_manager/ios/password_controller_helper.h
@@ -0,0 +1,62 @@ +// 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 COMPONENTS_PASSWORD_MANAGER_IOS_PASSWORD_CONTROLLER_HELPER_H_ +#define COMPONENTS_PASSWORD_MANAGER_IOS_PASSWORD_CONTROLLER_HELPER_H_ + +#import <Foundation/Foundation.h> + +#import "components/autofill/ios/form_util/form_activity_observer_bridge.h" +#import "ios/web/public/web_state/web_state_observer_bridge.h" +#include "url/gurl.h" + +NS_ASSUME_NONNULL_BEGIN + +@class JsPasswordManager; +@class PasswordControllerHelper; + +namespace autofill { +struct PasswordForm; +} // namespace autofill + +namespace password_manager { +// Returns true if the trust level for the current page URL of |web_state| is +// kAbsolute. If |page_url| is not null, fills it with the current page URL. +bool GetPageURLAndCheckTrustLevel(web::WebState* web_state, + GURL* __nullable page_url); +} // namespace password_manager + +namespace web { +class WebState; +} // namespace web + +// A protocol implemented by a delegate of PasswordControllerHelper. +@protocol PasswordControllerHelperDelegate +// Called when the password form is submitted. +- (void)helper:(PasswordControllerHelper*)helper + didSubmitForm:(const autofill::PasswordForm&)form + inMainFrame:(BOOL)inMainFrame; +@end + +// Handles common logic of password controller for both ios/chrome and +// ios/web_view. +// TODO(crbug.com/865114): Rename to PasswordFormHelper. +@interface PasswordControllerHelper + : NSObject<FormActivityObserver, CRWWebStateObserver> + +// The JsPasswordManager processing password form via javascript. +@property(nonatomic, readonly) JsPasswordManager* jsPasswordManager; + +// Creates a instance with the given WebState, observer and delegate. +- (instancetype)initWithWebState:(web::WebState*)webState + delegate:(nullable id<PasswordControllerHelperDelegate>) + delegate NS_DESIGNATED_INITIALIZER; + +- (instancetype)init NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END + +#endif // COMPONENTS_PASSWORD_MANAGER_IOS_PASSWORD_CONTROLLER_HELPER_H_
diff --git a/components/password_manager/ios/password_controller_helper.mm b/components/password_manager/ios/password_controller_helper.mm new file mode 100644 index 0000000..6fde26c --- /dev/null +++ b/components/password_manager/ios/password_controller_helper.mm
@@ -0,0 +1,244 @@ +// 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. + +#import "components/password_manager/ios/password_controller_helper.h" + +#include <stddef.h> + +#include "base/strings/sys_string_conversions.h" +#include "base/values.h" +#include "components/autofill/core/common/form_data.h" +#include "components/autofill/core/common/password_form.h" +#include "components/autofill/ios/browser/autofill_util.h" +#include "components/password_manager/core/browser/form_parsing/ios_form_parser.h" +#include "components/password_manager/ios/js_password_manager.h" +#import "ios/web/public/web_state/web_state.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +using autofill::FormData; +using autofill::PasswordForm; +using password_manager::GetPageURLAndCheckTrustLevel; + +namespace password_manager { +bool GetPageURLAndCheckTrustLevel(web::WebState* web_state, + GURL* __nullable page_url) { + auto trustLevel = web::URLVerificationTrustLevel::kNone; + GURL dummy; + if (!page_url) { + page_url = &dummy; + } + *page_url = web_state->GetCurrentURL(&trustLevel); + return trustLevel == web::URLVerificationTrustLevel::kAbsolute; +} +} // namespace password_manager + +namespace { +// Script command prefix for form changes. Possible command to be sent from +// injected JS is 'passwordForm.submitButtonClick'. +constexpr char kCommandPrefix[] = "passwordForm"; +} // namespace + +@interface PasswordControllerHelper () + +@property(nonatomic, weak) id<PasswordControllerHelperDelegate> delegate; + +// Handler for injected JavaScript callbacks. +- (BOOL)handleScriptCommand:(const base::DictionaryValue&)JSONCommand; + +// Finds the currently submitted password form named |formName| and calls +// |completionHandler| with the populated data structure. |found| is YES if the +// current form was found successfully, NO otherwise. |completionHandler| +// cannot be nil. +- (void)extractSubmittedPasswordForm:(const std::string&)formName + completionHandler: + (void (^)(BOOL found, + const PasswordForm& form))completionHandler; + +@end + +@implementation PasswordControllerHelper { + // The WebState this instance is observing. Will be null after + // -webStateDestroyed: has been called. + web::WebState* _webState; + + // Bridge to observe WebState from Objective-C. + std::unique_ptr<web::WebStateObserverBridge> _webStateObserverBridge; + + // Bridge to observe form activity in |_webState|. + std::unique_ptr<autofill::FormActivityObserverBridge> + _formActivityObserverBridge; +} + +#pragma mark - Properties + +@synthesize delegate = _delegate; +@synthesize jsPasswordManager = _jsPasswordManager; + +#pragma mark - Initialization + +- (instancetype)initWithWebState:(web::WebState*)webState + delegate: + (id<PasswordControllerHelperDelegate>)delegate { + self = [super init]; + if (self) { + DCHECK(webState); + _webState = webState; + _delegate = delegate; + _webStateObserverBridge = + std::make_unique<web::WebStateObserverBridge>(self); + _webState->AddObserver(_webStateObserverBridge.get()); + _formActivityObserverBridge = + std::make_unique<autofill::FormActivityObserverBridge>(_webState, self); + _jsPasswordManager = [[JsPasswordManager alloc] + initWithReceiver:_webState->GetJSInjectionReceiver()]; + + __weak PasswordControllerHelper* weakSelf = self; + auto callback = base::BindRepeating( + ^bool(const base::DictionaryValue& JSON, const GURL& originURL, + bool interacting, bool isMainFrame) { + if (!isMainFrame) { + // Passwords is only supported on main frame. + return false; + } + // |originURL| and |interacting| aren't used. + return [weakSelf handleScriptCommand:JSON]; + }); + _webState->AddScriptCommandCallback(callback, kCommandPrefix); + } + return self; +} + +#pragma mark - Dealloc + +- (void)dealloc { + if (_webState) { + _webState->RemoveScriptCommandCallback(kCommandPrefix); + _webState->RemoveObserver(_webStateObserverBridge.get()); + } +} + +#pragma mark - CRWWebStateObserver + +- (void)webStateDestroyed:(web::WebState*)webState { + DCHECK_EQ(_webState, webState); + if (_webState) { + _webState->RemoveScriptCommandCallback(kCommandPrefix); + _webState->RemoveObserver(_webStateObserverBridge.get()); + _webState = nullptr; + } + _webStateObserverBridge.reset(); + _formActivityObserverBridge.reset(); +} + +#pragma mark - FormActivityObserver + +- (void)webState:(web::WebState*)webState + submittedDocumentWithFormNamed:(const std::string&)formName + hasUserGesture:(BOOL)hasUserGesture + formInMainFrame:(BOOL)formInMainFrame { + DCHECK_EQ(_webState, webState); + __weak PasswordControllerHelper* weakSelf = self; + // This code is racing against the new page loading and will not get the + // password form data if the page has changed. In most cases this code wins + // the race. + // TODO(crbug.com/418827): Fix this by passing in more data from the JS side. + id completionHandler = ^(BOOL found, const autofill::PasswordForm& form) { + PasswordControllerHelper* strongSelf = weakSelf; + id<PasswordControllerHelperDelegate> strongDelegate = strongSelf.delegate; + if (!strongSelf || !strongSelf->_webState || !strongDelegate) { + return; + } + [strongDelegate helper:strongSelf + didSubmitForm:form + inMainFrame:formInMainFrame]; + }; + [self extractSubmittedPasswordForm:formName + completionHandler:completionHandler]; +} + +#pragma mark - Private methods + +- (BOOL)handleScriptCommand:(const base::DictionaryValue&)JSONCommand { + std::string command; + if (!JSONCommand.GetString("command", &command)) { + return NO; + } + + if (command != "passwordForm.submitButtonClick") { + return NO; + } + + GURL pageURL; + if (!GetPageURLAndCheckTrustLevel(_webState, &pageURL)) { + return NO; + } + + FormData formData; + if (!autofill::ExtractFormData(JSONCommand, false, base::string16(), pageURL, + &formData)) { + return NO; + } + + std::unique_ptr<PasswordForm> form = + ParseFormData(formData, password_manager::FormParsingMode::SAVING); + if (!form) { + return NO; + } + + if (_webState && self.delegate) { + [self.delegate helper:self didSubmitForm:*form inMainFrame:YES]; + return YES; + } + + return NO; +} + +- (void)extractSubmittedPasswordForm:(const std::string&)formName + completionHandler: + (void (^)(BOOL found, + const PasswordForm& form))completionHandler { + DCHECK(completionHandler); + + if (!_webState) { + return; + } + + GURL pageURL; + if (!GetPageURLAndCheckTrustLevel(_webState, &pageURL)) { + completionHandler(NO, PasswordForm()); + return; + } + + id extractSubmittedFormCompletionHandler = ^(NSString* jsonString) { + std::unique_ptr<base::Value> formValue = autofill::ParseJson(jsonString); + if (!formValue) { + completionHandler(NO, PasswordForm()); + return; + } + + FormData formData; + if (!autofill::ExtractFormData(*formValue, false, base::string16(), pageURL, + &formData)) { + completionHandler(NO, PasswordForm()); + return; + } + + std::unique_ptr<PasswordForm> form = + ParseFormData(formData, password_manager::FormParsingMode::SAVING); + if (!form) { + completionHandler(NO, PasswordForm()); + return; + } + + completionHandler(YES, *form); + }; + + [self.jsPasswordManager extractForm:base::SysUTF8ToNSString(formName) + completionHandler:extractSubmittedFormCompletionHandler]; +} + +@end
diff --git a/components/password_manager/ios/password_controller_helper_unittest.mm b/components/password_manager/ios/password_controller_helper_unittest.mm new file mode 100644 index 0000000..66d87df --- /dev/null +++ b/components/password_manager/ios/password_controller_helper_unittest.mm
@@ -0,0 +1,13 @@ +// 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. + +#import "components/password_manager/ios/password_controller_helper.h" + +#include <stddef.h> + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +// TODO(crbug.com/865114): Add unit test in follow up CL.
diff --git a/components/policy/resources/policy_templates.json b/components/policy/resources/policy_templates.json index a4ae57c..f52b960 100644 --- a/components/policy/resources/policy_templates.json +++ b/components/policy/resources/policy_templates.json
@@ -669,6 +669,7 @@ 'desc': '''Configure Network File Share related policies.''', 'policies': [ 'NetworkFileSharesAllowed', + 'NetBiosShareDiscoveryEnabled', ], }, { @@ -12799,6 +12800,25 @@ If this policy is left unset, then the default behavior of not allowing any HTTP/2 connection coalescing on connections using client certificates will be used.''', }, + { + 'id': 467, + 'name': 'NetBiosShareDiscoveryEnabled', + 'type': 'main', + 'schema': {'type': 'boolean', }, + 'tags': [], + 'features': { + 'dynamic_refresh': True, + 'per_profile': True, + }, + 'supported_on': ['chrome_os:70-'], + 'caption': '''Controls Network File Share discovery via <ph name="NETBIOS_NAME">NetBIOS</ph>''', + 'example_value': True, + 'default_for_enterprise_users': False, + 'desc': '''This policy controls whether the Network File Shares feature for <ph name="PRODUCT_NAME">$2<ex>Google Chrome OS</ex></ph> should use the <ph name="NETBIOS_PROTOCOL">NetBIOS Name Query Request protocol</ph> to discover shares on the network. + When this policy is set to True, share discovery will use the <ph name="NETBIOS_PROTOCOL">NetBIOS Name Query Request protocol</ph> protocol to discover shares on the network. + When this policy is set to False, share discovery will not use the <ph name="NETBIOS_PROTOCOL">NetBIOS Name Query Request protocol</ph> protocol to discover shares. + If the policy is left not set, the default is disabled for enterprise-managed users and enabled for non-managed users.''', + }, ], 'messages': { @@ -12940,5 +12960,5 @@ }, 'placeholders': [], 'deleted_policy_ids': [412], - 'highest_id_currently_used': 466 + 'highest_id_currently_used': 467 }
diff --git a/components/printing/common/print_messages.h b/components/printing/common/print_messages.h index 71082b1..0c311c9a 100644 --- a/components/printing/common/print_messages.h +++ b/components/printing/common/print_messages.h
@@ -284,19 +284,14 @@ IPC_STRUCT_END() #if BUILDFLAG(ENABLE_PRINT_PREVIEW) -// Parameters to describe a rendered document. -IPC_STRUCT_BEGIN(PrintHostMsg_DidPreviewDocument_Params) - // Document's content including metafile data and subframe info. - IPC_STRUCT_MEMBER(PrintHostMsg_DidPrintContent_Params, content) +// Parameters to describe the to-be-rendered preview document. +IPC_STRUCT_BEGIN(PrintHostMsg_DidStartPreview_Params) + // Total page count for the rendered preview. (Not the number of pages the + // user selected to print.) + IPC_STRUCT_MEMBER(int, page_count) - // Cookie for the document to ensure correctness. - IPC_STRUCT_MEMBER(int, document_cookie) - - // Store the expected pages count. - IPC_STRUCT_MEMBER(int, expected_pages_count) - - // Whether the preview can be modified. - IPC_STRUCT_MEMBER(bool, modifiable) + // Scaling % to fit to page + IPC_STRUCT_MEMBER(int, fit_to_page_scaling) IPC_STRUCT_END() // Parameters to describe a rendered preview page. @@ -311,13 +306,19 @@ IPC_STRUCT_MEMBER(int, document_cookie) IPC_STRUCT_END() -// Parameters sent along with the page count. -IPC_STRUCT_BEGIN(PrintHostMsg_DidGetPreviewPageCount_Params) - // Total page count. - IPC_STRUCT_MEMBER(int, page_count) +// Parameters to describe the final rendered preview document. +IPC_STRUCT_BEGIN(PrintHostMsg_DidPreviewDocument_Params) + // Document's content including metafile data and subframe info. + IPC_STRUCT_MEMBER(PrintHostMsg_DidPrintContent_Params, content) - // Scaling % to fit to page - IPC_STRUCT_MEMBER(int, fit_to_page_scaling) + // Cookie for the document to ensure correctness. + IPC_STRUCT_MEMBER(int, document_cookie) + + // Store the expected pages count. + IPC_STRUCT_MEMBER(int, expected_pages_count) + + // Whether the preview can be modified. + IPC_STRUCT_MEMBER(bool, modifiable) IPC_STRUCT_END() #endif // BUILDFLAG(ENABLE_PRINT_PREVIEW) @@ -337,7 +338,6 @@ // The physical offsets of the printer in DPI. Used for PS printing. IPC_STRUCT_MEMBER(gfx::Point, physical_offsets) - IPC_STRUCT_END() // TODO(dgn) Rename *ScriptedPrint messages because they are not called only @@ -460,9 +460,9 @@ IPC_MESSAGE_ROUTED1(PrintHostMsg_RequestPrintPreview, PrintHostMsg_RequestPrintPreview_Params /* params */) -// Notify the browser the number of pages in the print preview document. -IPC_MESSAGE_ROUTED2(PrintHostMsg_DidGetPreviewPageCount, - PrintHostMsg_DidGetPreviewPageCount_Params /* params */, +// Notify the browser the about the to-be-rendered print preview document. +IPC_MESSAGE_ROUTED2(PrintHostMsg_DidStartPreview, + PrintHostMsg_DidStartPreview_Params /* params */, PrintHostMsg_PreviewIds /* ids */) // Notify the browser of the default page layout according to the currently
diff --git a/components/printing/renderer/print_render_frame_helper.cc b/components/printing/renderer/print_render_frame_helper.cc index b8c88487..efb0827 100644 --- a/components/printing/renderer/print_render_frame_helper.cc +++ b/components/printing/renderer/print_render_frame_helper.cc
@@ -1261,11 +1261,11 @@ routing_id(), default_page_layout, printable_area_in_points, has_page_size_style, ids)); - PrintHostMsg_DidGetPreviewPageCount_Params params; + PrintHostMsg_DidStartPreview_Params params; params.page_count = print_preview_context_.total_page_count(); params.fit_to_page_scaling = GetFitToPageScaleFactor(printable_area_in_points); - Send(new PrintHostMsg_DidGetPreviewPageCount(routing_id(), params, ids)); + Send(new PrintHostMsg_DidStartPreview(routing_id(), params, ids)); if (CheckForCancel()) return false;
diff --git a/components/printing/test/print_mock_render_thread.cc b/components/printing/test/print_mock_render_thread.cc index 548b99cb..3c6c6929 100644 --- a/components/printing/test/print_mock_render_thread.cc +++ b/components/printing/test/print_mock_render_thread.cc
@@ -61,8 +61,7 @@ OnDidGetPrintedPagesCount) IPC_MESSAGE_HANDLER(PrintHostMsg_DidPrintDocument, OnDidPrintDocument) #if BUILDFLAG(ENABLE_PRINT_PREVIEW) - IPC_MESSAGE_HANDLER(PrintHostMsg_DidGetPreviewPageCount, - OnDidGetPreviewPageCount) + IPC_MESSAGE_HANDLER(PrintHostMsg_DidStartPreview, OnDidStartPreview) IPC_MESSAGE_HANDLER(PrintHostMsg_DidPreviewPage, OnDidPreviewPage) IPC_MESSAGE_HANDLER(PrintHostMsg_CheckForCancel, OnCheckForCancel) #endif @@ -99,8 +98,8 @@ } #if BUILDFLAG(ENABLE_PRINT_PREVIEW) -void PrintMockRenderThread::OnDidGetPreviewPageCount( - const PrintHostMsg_DidGetPreviewPageCount_Params& params, +void PrintMockRenderThread::OnDidStartPreview( + const PrintHostMsg_DidStartPreview_Params& params, const PrintHostMsg_PreviewIds& ids) { print_preview_pages_remaining_ = params.page_count; }
diff --git a/components/printing/test/print_mock_render_thread.h b/components/printing/test/print_mock_render_thread.h index cb92370..52632c00 100644 --- a/components/printing/test/print_mock_render_thread.h +++ b/components/printing/test/print_mock_render_thread.h
@@ -22,7 +22,7 @@ } class MockPrinter; -struct PrintHostMsg_DidGetPreviewPageCount_Params; +struct PrintHostMsg_DidStartPreview_Params; struct PrintHostMsg_DidPreviewPage_Params; struct PrintHostMsg_DidPrintDocument_Params; struct PrintHostMsg_PreviewIds; @@ -78,9 +78,8 @@ void OnDidGetPrintedPagesCount(int cookie, int number_pages); void OnDidPrintDocument(const PrintHostMsg_DidPrintDocument_Params& params); #if BUILDFLAG(ENABLE_PRINT_PREVIEW) - void OnDidGetPreviewPageCount( - const PrintHostMsg_DidGetPreviewPageCount_Params& params, - const PrintHostMsg_PreviewIds& ids); + void OnDidStartPreview(const PrintHostMsg_DidStartPreview_Params& params, + const PrintHostMsg_PreviewIds& ids); void OnDidPreviewPage(const PrintHostMsg_DidPreviewPage_Params& params, const PrintHostMsg_PreviewIds& ids); void OnCheckForCancel(const PrintHostMsg_PreviewIds& ids, bool* cancel);
diff --git a/components/printing/test/print_render_frame_helper_browsertest.cc b/components/printing/test/print_render_frame_helper_browsertest.cc index 4f7981c5..943b259 100644 --- a/components/printing/test/print_render_frame_helper_browsertest.cc +++ b/components/printing/test/print_render_frame_helper_browsertest.cc
@@ -202,14 +202,13 @@ // according to the specified settings defined in the mock render thread. // Verify the page count is correct. void VerifyPreviewPageCount(int expected_count) { - const IPC::Message* page_cnt_msg = + const IPC::Message* preview_started_message = render_thread_->sink().GetUniqueMessageMatching( - PrintHostMsg_DidGetPreviewPageCount::ID); - ASSERT_TRUE(page_cnt_msg); - PrintHostMsg_DidGetPreviewPageCount::Param post_page_count_param; - PrintHostMsg_DidGetPreviewPageCount::Read(page_cnt_msg, - &post_page_count_param); - EXPECT_EQ(expected_count, std::get<0>(post_page_count_param).page_count); + PrintHostMsg_DidStartPreview::ID); + ASSERT_TRUE(preview_started_message); + PrintHostMsg_DidStartPreview::Param param; + PrintHostMsg_DidStartPreview::Read(preview_started_message, ¶m); + EXPECT_EQ(expected_count, std::get<0>(param).page_count); } #endif // BUILDFLAG(ENABLE_PRINT_PREVIEW)
diff --git a/components/resources/nux_google_apps.grdp b/components/resources/nux_google_apps.grdp index 58f9f8f..5e74f85 100644 --- a/components/resources/nux_google_apps.grdp +++ b/components/resources/nux_google_apps.grdp
@@ -1,21 +1,21 @@ <?xml version="1.0" encoding="utf-8"?> <grit-part> - <include name="IDR_NUX_GOOGLE_APPS_HTML" file="../nux_google_apps/resources/nux_google_apps.html" type="BINDATA" /> - <include name="IDR_NUX_GOOGLE_APPS_JS" file="../nux_google_apps/resources/nux_google_apps.js" type="BINDATA" /> - <include name="IDR_NUX_GOOGLE_APPS_PROXY_HTML" file="../nux_google_apps/resources/nux_google_apps_proxy.html" type="BINDATA" /> - <include name="IDR_NUX_GOOGLE_APPS_PROXY_JS" file="../nux_google_apps/resources/nux_google_apps_proxy.js" type="BINDATA" /> - <include name="IDR_NUX_GOOGLE_APPS_CHOOSER_HTML" file="../nux_google_apps/resources/apps_chooser.html" type="BINDATA" /> - <include name="IDR_NUX_GOOGLE_APPS_CHOOSER_JS" file="../nux_google_apps/resources/apps_chooser.js" type="BINDATA" /> - <include name="IDR_NUX_GOOGLE_APPS_CHROME_STORE_1X" file="../nux_google_apps/resources/chrome_store_24dp_1x.png" type="BINDATA" /> - <include name="IDR_NUX_GOOGLE_APPS_CHROME_STORE_2X" file="../nux_google_apps/resources/chrome_store_24dp_2x.png" type="BINDATA" /> - <include name="IDR_NUX_GOOGLE_APPS_GMAIL_1X" file="../nux_google_apps/resources/gmail_24dp_1x.png" type="BINDATA" /> - <include name="IDR_NUX_GOOGLE_APPS_GMAIL_2X" file="../nux_google_apps/resources/gmail_24dp_2x.png" type="BINDATA" /> - <include name="IDR_NUX_GOOGLE_APPS_MAPS_1X" file="../nux_google_apps/resources/maps_24dp_1x.png" type="BINDATA" /> - <include name="IDR_NUX_GOOGLE_APPS_MAPS_2X" file="../nux_google_apps/resources/maps_24dp_2x.png" type="BINDATA" /> - <include name="IDR_NUX_GOOGLE_APPS_NEWS_1X" file="../nux_google_apps/resources/news_24dp_1x.png" type="BINDATA" /> - <include name="IDR_NUX_GOOGLE_APPS_NEWS_2X" file="../nux_google_apps/resources/news_24dp_2x.png" type="BINDATA" /> - <include name="IDR_NUX_GOOGLE_APPS_TRANSLATE_1X" file="../nux_google_apps/resources/translate_24dp_1x.png" type="BINDATA" /> - <include name="IDR_NUX_GOOGLE_APPS_TRANSLATE_2X" file="../nux_google_apps/resources/translate_24dp_2x.png" type="BINDATA" /> - <include name="IDR_NUX_GOOGLE_APPS_YOUTUBE_1X" file="../nux_google_apps/resources/youtube_24dp_1x.png" type="BINDATA" /> - <include name="IDR_NUX_GOOGLE_APPS_YOUTUBE_2X" file="../nux_google_apps/resources/youtube_24dp_2x.png" type="BINDATA" /> + <include name="IDR_NUX_GOOGLE_APPS_HTML" file="../nux/google_apps/resources/nux_google_apps.html" type="BINDATA" /> + <include name="IDR_NUX_GOOGLE_APPS_JS" file="../nux/google_apps/resources/nux_google_apps.js" type="BINDATA" /> + <include name="IDR_NUX_GOOGLE_APPS_PROXY_HTML" file="../nux/google_apps/resources/nux_google_apps_proxy.html" type="BINDATA" /> + <include name="IDR_NUX_GOOGLE_APPS_PROXY_JS" file="../nux/google_apps/resources/nux_google_apps_proxy.js" type="BINDATA" /> + <include name="IDR_NUX_GOOGLE_APPS_CHOOSER_HTML" file="../nux/google_apps/resources/apps_chooser.html" type="BINDATA" /> + <include name="IDR_NUX_GOOGLE_APPS_CHOOSER_JS" file="../nux/google_apps/resources/apps_chooser.js" type="BINDATA" /> + <include name="IDR_NUX_GOOGLE_APPS_CHROME_STORE_1X" file="../nux/google_apps/resources/chrome_store_24dp_1x.png" type="BINDATA" /> + <include name="IDR_NUX_GOOGLE_APPS_CHROME_STORE_2X" file="../nux/google_apps/resources/chrome_store_24dp_2x.png" type="BINDATA" /> + <include name="IDR_NUX_GOOGLE_APPS_GMAIL_1X" file="../nux/google_apps/resources/gmail_24dp_1x.png" type="BINDATA" /> + <include name="IDR_NUX_GOOGLE_APPS_GMAIL_2X" file="../nux/google_apps/resources/gmail_24dp_2x.png" type="BINDATA" /> + <include name="IDR_NUX_GOOGLE_APPS_MAPS_1X" file="../nux/google_apps/resources/maps_24dp_1x.png" type="BINDATA" /> + <include name="IDR_NUX_GOOGLE_APPS_MAPS_2X" file="../nux/google_apps/resources/maps_24dp_2x.png" type="BINDATA" /> + <include name="IDR_NUX_GOOGLE_APPS_NEWS_1X" file="../nux/google_apps/resources/news_24dp_1x.png" type="BINDATA" /> + <include name="IDR_NUX_GOOGLE_APPS_NEWS_2X" file="../nux/google_apps/resources/news_24dp_2x.png" type="BINDATA" /> + <include name="IDR_NUX_GOOGLE_APPS_TRANSLATE_1X" file="../nux/google_apps/resources/translate_24dp_1x.png" type="BINDATA" /> + <include name="IDR_NUX_GOOGLE_APPS_TRANSLATE_2X" file="../nux/google_apps/resources/translate_24dp_2x.png" type="BINDATA" /> + <include name="IDR_NUX_GOOGLE_APPS_YOUTUBE_1X" file="../nux/google_apps/resources/youtube_24dp_1x.png" type="BINDATA" /> + <include name="IDR_NUX_GOOGLE_APPS_YOUTUBE_2X" file="../nux/google_apps/resources/youtube_24dp_2x.png" type="BINDATA" /> </grit-part>
diff --git a/components/test/data/autofill/automated_integration/action_recorder_extension/background/background.js b/components/test/data/autofill/automated_integration/action_recorder_extension/background/background.js index 7bccd7f7..5e2f678 100644 --- a/components/test/data/autofill/automated_integration/action_recorder_extension/background/background.js +++ b/components/test/data/autofill/automated_integration/action_recorder_extension/background/background.js
@@ -80,30 +80,28 @@ }); } - function performTransactionOnRecipeIndexedDB(transactionToPerform) { - return openRecipeIndexedDB() - .then((db) => { - return new Promise((resolve, reject) => { - const transaction = db.transaction([Indexed_DB_Vars.ATTRIBUTES, - Indexed_DB_Vars.ACTIONS], - 'readwrite'); - transaction.oncomplete = (event) => { - resolve(event); - }; - transaction.onerror = (event) => { - console.warn('Unable to complete indexedDB transaction.'); - reject(transaction.error); - }; - transactionToPerform(transaction); - }) - .catch((error) => { - console.error('Unable to perform transaction in the indexedDB ' + - 'Recipe database!', error); - }) - .finally(() => { - db.close(); - }); - }); + async function performTransactionOnRecipeIndexedDB(transactionToPerform) { + const db = await openRecipeIndexedDB(); + return await new Promise((resolve, reject) => { + const transaction = db.transaction([Indexed_DB_Vars.ATTRIBUTES, + Indexed_DB_Vars.ACTIONS], + 'readwrite'); + transaction.oncomplete = (event) => { + resolve(event); + }; + transaction.onerror = (event) => { + console.warn('Unable to complete indexedDB transaction.'); + reject(transaction.error); + }; + transactionToPerform(transaction); + }) + .catch((error) => { + console.error('Unable to perform transaction in the indexedDB ' + + 'Recipe database!', error); + }) + .finally(() => { + db.close(); + }); } function initializeRecipe(name, url) { @@ -115,37 +113,43 @@ }); } - function addActionToRecipe(action) { - return openRecipeIndexedDB() - .then((db) => { - return new Promise((resolve, reject) => { - const transaction = db.transaction([Indexed_DB_Vars.ACTIONS], - 'readwrite'); - const request = - transaction.objectStore(Indexed_DB_Vars.ACTIONS).add(action); - let completed = false; - let key; - request.onsuccess = (event) => { - key = event.target.result; - if (completed) { - resolve(key); - } - }; - transaction.oncomplete = (event) => { - completed = true; - if (key) { - resolve(key); - } - }; - transaction.onerror = (event) => { - console.warn('Unable to add action to the recipe!'); - reject(event.target.error); - }; - }) - .finally(() => { - db.close(); - }); - }); + async function addActionToRecipe(action, tabId) { + const db = await openRecipeIndexedDB(); + const key = await new Promise((resolve, reject) => { + const transaction = db.transaction([Indexed_DB_Vars.ACTIONS], + 'readwrite'); + const request = + transaction.objectStore(Indexed_DB_Vars.ACTIONS).add(action); + let completed = false; + let key; + request.onsuccess = (event) => { + key = event.target.result; + if (completed) { + resolve(key); + } + }; + transaction.oncomplete = (event) => { + completed = true; + if (key) { + resolve(key); + } + }; + transaction.onerror = (event) => { + console.warn('Unable to add action to the recipe!'); + reject(event.target.error); + }; + }) + .finally(() => { + db.close(); + }); + + // Update the recording UI with the new action. + const frameId = await getRecorderUiFrameId(); + action.action_index = key; + await sendMessageToTab( + tabId, + { type: RecorderUiMsgEnum.ADD_ACTION, action: action}, + { frameId: frameId }); } function removeActionFromRecipe(index) { @@ -154,41 +158,40 @@ }); } - function getRecipe() { - return openRecipeIndexedDB() - .then((db) => { - return new Promise((resolve, reject) => { - let recipe = {}; - const transaction = db.transaction([Indexed_DB_Vars.ATTRIBUTES, - Indexed_DB_Vars.ACTIONS], - 'readonly'); - transaction.oncomplete = (event) => { - resolve(recipe); - }; - transaction.onerror = (event) => { - console.error('Unable to read from indexedDB.'); - throw(transaction.error); - }; - const attributeStore = - transaction.objectStore(Indexed_DB_Vars.ATTRIBUTES); - const actionsStore = transaction.objectStore(Indexed_DB_Vars.ACTIONS); - const nameReq = attributeStore.get(Indexed_DB_Vars.NAME); - nameReq.onsuccess = (event) => { - recipe.name = nameReq.result; - }; - const urlReq = attributeStore.get(Indexed_DB_Vars.URL); - urlReq.onsuccess = (event) => { - recipe.startingURL = urlReq.result; - }; - const actionsReq = actionsStore.getAll(); - actionsReq.onsuccess = (event) => { - recipe.actions = actionsReq.result ? actionsReq.result : []; - }; - }) - .finally(() => { - db.close(); - }); - }); + async function getRecipe() { + const db = await openRecipeIndexedDB(); + let recipe = {}; + return await new Promise((resolve, reject) => { + let recipe = {}; + const transaction = db.transaction([Indexed_DB_Vars.ATTRIBUTES, + Indexed_DB_Vars.ACTIONS], + 'readonly'); + transaction.oncomplete = (event) => { + resolve(recipe); + }; + transaction.onerror = (event) => { + console.error('Unable to read from indexedDB.'); + throw(transaction.error); + }; + const attributeStore = + transaction.objectStore(Indexed_DB_Vars.ATTRIBUTES); + const actionsStore = transaction.objectStore(Indexed_DB_Vars.ACTIONS); + const nameReq = attributeStore.get(Indexed_DB_Vars.NAME); + nameReq.onsuccess = (event) => { + recipe.name = nameReq.result; + }; + const urlReq = attributeStore.get(Indexed_DB_Vars.URL); + urlReq.onsuccess = (event) => { + recipe.startingURL = urlReq.result; + }; + const actionsReq = actionsStore.getAll(); + actionsReq.onsuccess = (event) => { + recipe.actions = actionsReq.result ? actionsReq.result : []; + }; + }) + .finally(() => { + db.close(); + }); } function setBrowserActionUi(state, targetTabId) { @@ -217,47 +220,28 @@ } } - function getRecordingTabId() { - return new Promise((resolve, reject) => { - getChromeLocalStorageVariables([Local_Storage_Vars.RECORDING_TAB_ID]) - .then((items) => { - resolve(items[Local_Storage_Vars.RECORDING_TAB_ID]); - }) - .catch((message) => { - reject(message); - }); - }); + async function getRecordingTabId() { + const items = await getChromeLocalStorageVariables( + [Local_Storage_Vars.RECORDING_TAB_ID]); + return items[Local_Storage_Vars.RECORDING_TAB_ID]; } - function getRecordingState() { - return new Promise((resolve, reject) => { - getChromeLocalStorageVariables([Local_Storage_Vars.RECORDING_STATE]) - .then((items) => { - resolve(items[Local_Storage_Vars.RECORDING_STATE]); - }) - .catch((message) => { - reject(message); - }); - }); + async function getRecordingState() { + const items = await getChromeLocalStorageVariables( + [Local_Storage_Vars.RECORDING_STATE]); + return items[Local_Storage_Vars.RECORDING_STATE]; } - function getRecorderUiFrameId() { - return new Promise((resolve, reject) => { - getChromeLocalStorageVariables( - [Local_Storage_Vars.RECORDING_UI_FRAME_ID]) - .then((items) => { - resolve(items[Local_Storage_Vars.RECORDING_UI_FRAME_ID]); - }) - .catch((message) => { - reject(message); - }); - }); + async function getRecorderUiFrameId() { + const items = await getChromeLocalStorageVariables( + [Local_Storage_Vars.RECORDING_UI_FRAME_ID]); + return items[Local_Storage_Vars.RECORDING_UI_FRAME_ID]; } - function setRecorderUiFrameId(frameId) { + async function setRecorderUiFrameId(frameId) { let items = {}; items[Local_Storage_Vars.RECORDING_UI_FRAME_ID] = frameId; - return setChromeLocalStorageVariables(items); + await setChromeLocalStorageVariables(items); } function sendMessageToTab(tabId, message, options) { @@ -288,173 +272,161 @@ }); } - function getIframeContext(tabId, frameId) { - return new Promise((resolve, reject) => { - if (frameId === 0) { - resolve({ isIframe: false }); - } else { - let context = { isIframe: true }; - getAllFramesInTab(tabId) - .then((details) => { - let targetFrame; - for (let index = 0; index < details.length; index++) { - if (details[index].frameId === frameId) { - targetFrame = details[index]; - break; - } - } - // Send a message to the parent frame and see if the iframe has a - // 'name' attribute. - sendMessageToTab(tabId, { - type: RecorderMsgEnum.GET_IFRAME_NAME, - url: targetFrame.url - }, { - frameId: targetFrame.parentFrameId - }) - .then((frameName) => { - if (frameName !== '' && frameName !== undefined) { - context.browserTest = { name: frameName }; - resolve(context); - } else { - const targetFrameUrl = new URL(targetFrame.url); - // The frame does not have a 'name' attribute. Check if the - // frame has a unique combination of scheme, host and port. - // - // The Captured Site automation framework can identify an - // iframe by its scheme + host + port, provided this - // information combination is unique. Identifying an iframe - // through its scheme + host + port is more preferable than - // identifying an iframe through its URL. An URL will - // frequently contain parameters, and many websites use random - // number generator or date generator to create these - // parameters. For example, in the following URL - // - // https://payment.bhphotovideo.com/static/desktop/v2.0/ - // index.html - // #paypageId=aLGNuLSTJVwgEiCn&cartID=333334444 - // &receiverID=77777777-7777-4777-b777-777777888888 - // &uuid=77777777-7777-4777-b777-778888888888 - // - // The site created the parameters cartID, receiverID and uuid - // using random number generators. These parameters will have - // different values every time the browser loads the page. - // Therefore automation will not be able to identify an iframe - // that loads this URL. - let frameHostAndSchemeIsUnique = true; - for (let index = 0; index < details.length; index++) { - const url = new URL(details[index].url); - if (details[index].frameId !== targetFrame.frameId && - targetFrameUrl.protocol === url.protocol && - targetFrameUrl.host === url.host) { - frameHostAndSchemeIsUnique = false; - break; - } - } - if (frameHostAndSchemeIsUnique) { - context.browserTest = { - schemeAndHost: - `${targetFrameUrl.protocol}//${targetFrameUrl.host}` - }; - resolve(context); - } else { - context.browserTest = { url: targetFrame.url }; - resolve(context); - } - } - }); - }); - } - }); + async function getIframeContext(tabId, frameId) { + if (frameId === 0) { + return { isIframe: false }; + } + + let context = { isIframe: true }; + + const allFrames = await getAllFramesInTab(tabId); + let targetFrame; + for (const frame of allFrames) { + if (frame.frameId === frameId) { + targetFrame = frame; + break; + } + } + + // Send a message to the parent frame and see if the iframe has a + // 'name' attribute. + const frameName = await sendMessageToTab(tabId, + { type: RecorderMsgEnum.GET_IFRAME_NAME, + url: targetFrame.url}, + { frameId: targetFrame.parentFrameId}); + if (frameName) { + context.browserTest = { name: frameName }; + return context; + } + + const targetFrameUrl = new URL(targetFrame.url); + // The frame does not have a 'name' attribute. Check if the frame has + // a unique origin. + // + // The Captured Site automation framework can identify an iframe by its + // origin, provided the origin is unique. + // + // Identifying an iframe through its origin is more preferable than + // identifying an iframe through its URL. An URL will frequently + // contain parameters, and many websites use random number generator or + // date generator to create these parameters. For example, in the + // following URL + // + // https://payment.bhphotovideo.com/static/desktop/v2.0/ + // index.html + // #paypageId=aLGNuLSTJVwgEiCn&cartID=333334444 + // &receiverID=77777777-7777-4777-b777-777777888888 + // &uuid=77777777-7777-4777-b777-778888888888 + // + // The site created the parameters cartID, receiverID and uuid using + // random number generators. These parameters will have different + // values every time the browser loads the page. Therefore automation + // will not be able to identify an iframe that loads this URL. + let originIsUnique = true; + for (const frame of allFrames) { + const url = new URL(frame.url); + if (frame.frameId !== targetFrame.frameId && + url.origin === targetFrameUrl.origin) { + originIsUnique = false; + break; + } + } + + if (originIsUnique) { + context.browserTest = + { origin: `${targetFrameUrl.protocol}//${targetFrameUrl.host}` }; + return context; + } + + context.browserTest = { url: targetFrame.url }; + return context; } - function stopRecordingOnTab(tabId) { - const promise = - // Send a message to all the frames in the target tab to stop recording. - getAllFramesInTab(tabId) - .then((details) => { - let recordingStoppedOnMainFramePromise; - details.forEach((frame) => { - const promise = sendMessageToTab(tabId, - { type: RecorderMsgEnum.STOP }, - { frameId: frame.frameId }); - if (frame.frameId === 0) { - recordingStoppedOnMainFramePromise = promise; - } else { - promise.catch((error) => - console.warn( - `Unable to stop recording on '${frame.url}'`, error)); - } - }); - return recordingStoppedOnMainFramePromise; - }) - .then((response) => { - if (!response) { - return Promise.reject( - new Error('Unable to stop recording on the root frame!')); + async function stopRecordingOnTab(tabId) { + const allFrames = await getAllFramesInTab(tabId); + let stopRecordingOnMainFrameResponse; + + for (const frame of allFrames) { + try { + const response = await sendMessageToTab( + tabId, { type: RecorderMsgEnum.STOP }, { frameId: frame.frameId }); + if (frame.frameId === 0) { + stopRecordingOnMainFrameResponse = response; } - return sendMessageToTab( - tabId, { type: RecorderUiMsgEnum.DESTROY_UI }, { frameId: 0 }); - }) - .then((response) => { - if (!response) { - return Promise.reject( - new Error('Unable to destroy the recorder UI!')); - } - setBrowserActionUi(RecorderStateEnum.STOPPED); - return Promise.resolve(); - }); - return promise; + } catch (error) { + console.warn(`Unable to stop recording on '${frame.url}'`, error); + } + } + + if (!stopRecordingOnMainFrameResponse) { + return Promise.reject( + new Error('Unable to stop recording on the root frame!')); + } + + const destroyRecordingUiResponse = await sendMessageToTab( + tabId, { type: RecorderUiMsgEnum.DESTROY_UI }, { frameId: 0 }); + if (!destroyRecordingUiResponse) { + return Promise.reject(new Error('Unable to destroy the recorder UI!')); + } + setBrowserActionUi(RecorderStateEnum.STOPPED); } - function startRecordingOnTabAndFrame(tabId, frameId) { - const ret = - getIframeContext(tabId, frameId) - .then((context) => { - return sendMessageToTab(tabId, - { type: RecorderMsgEnum.START, - frameContext: context - }, - { frameId: frameId }); - }) - .then((response) => { - if (!response) { - return Promise.reject( - new Error(`Unable to start recording on ${tabId}, ${frameId}`)); + async function startRecording(tab) { + // By default, start recording on the current active tab. + await clearRecorderVariables(); + await initializeRecorderVariables(tab); + const allFrames = await getAllFramesInTab(tab.id); + for (const frame of allFrames) { + // The extension has no need and no permission to inject script + // into 'about:' pages, such as the 'about:blank' page. + if (!frame.url.startsWith('about:')) { + try { + const response = + await startRecordingOnTabAndFrame(tab.id, frame.frameId); + } catch (error) { + console.warn(`Unable to start recording for url ${tab.url}!\r\n`, + error); } - // If starting recording on the root frame, tell the root frame to - // create the recorder UI. - if (frameId === 0) { - return sendMessageToTab( - tabId, { type: RecorderUiMsgEnum.CREATE_UI }, { frameId: 0 }) - .then((response) => { - if (!response) { - return Promise.reject( - new Error('Unable to create the recorder UI!')); - } - let items = {}; - items[Local_Storage_Vars.RECORDING_STATE] = - RecorderStateEnum.SHOWN; - return setChromeLocalStorageVariables(items); - }) - .then(() => { - setBrowserActionUi(RecorderStateEnum.SHOWN, tabId); - return Promise.resolve(); - }); - } else { - return Promise.resolve(); - } - }); - return ret; + } + } + console.log(`Started recording for tab ${tab.id}`); } - function initializeRecorderVariables(tab) { + async function startRecordingOnTabAndFrame(tabId, frameId) { + const context = await getIframeContext(tabId, frameId); + const response = await sendMessageToTab( + tabId, + { type: RecorderMsgEnum.START, + frameContext: context}, + { frameId: frameId }); + if (!response) { + return Promise.reject( + new Error(`Unable to start recording on ${tabId}, ${frameId}`)); + } + + // If starting recording on the root frame, tell the root frame to + // create the recorder UI. + if (frameId === 0) { + const createUiResponse = await sendMessageToTab( + tabId, { type: RecorderUiMsgEnum.CREATE_UI }, { frameId: 0 }); + if (!response) { + return Promise.reject(new Error('Unable to create the recorder UI!')); + } + let items = {}; + items[Local_Storage_Vars.RECORDING_STATE] = RecorderStateEnum.SHOWN; + await setChromeLocalStorageVariables(items); + setBrowserActionUi(RecorderStateEnum.SHOWN, tabId); + } + } + + async function initializeRecorderVariables(tab) { let items = {}; // Initialize the target tab id in the local storage area. The // background script will use this id to communicate with the content // script on the actively recording tab. items[Local_Storage_Vars.RECORDING_TAB_ID] = tab.id; - return setChromeLocalStorageVariables(items) - .then(initializeRecipe(tab.title, tab.url)); + await setChromeLocalStorageVariables(items); + await initializeRecipe(tab.title, tab.url); } // Clean up local storage variables used for recording. @@ -466,92 +438,63 @@ } else { clearRecipeIndexedDB() .then(() => resolve()); - resolve(); } }); }); } - function stopRecording() { - return getRecordingTabId() - .then((tabId) => stopRecordingOnTab(tabId)) - .then(() => clearRecorderVariables()); + async function stopRecording() { + const tabId = await getRecordingTabId(); + await stopRecordingOnTab(tabId); + await clearRecorderVariables(); + await clearBrowserCache(); + console.log('Stopped Recording.') } - function downloadRecipe() { - return new Promise((resolve, reject) => { - getRecipe() - .then((recipe) => { - // Download the JSON-serialized recipe as a text file. - const recipeJsonString = JSON.stringify(recipe, null, 2); - const blob = new Blob([recipeJsonString], {type: 'text/plain'}); - chrome.downloads.download({ - filename: '_web_site_name.test', - saveAs: true, - url: window.URL.createObjectURL(blob) - }, (downloadId) => { - if (downloadId) { - resolve(); - } else { - reject('Download failed! Recording isn\'t stopped.'); - } - }); - }) - .catch((message) => { - reject(message); - }); - }); - } + async function downloadRecipe() { + const recipe = await getRecipe(); - function showContentScriptUi() { + // Download the JSON-serialized recipe as a text file. + const recipeJsonString = JSON.stringify(recipe, null, 2); + const blob = new Blob([recipeJsonString], {type: 'text/plain'}); return new Promise((resolve, reject) => { - getRecordingTabId() - .then((tabId) => { - return sendMessageToTab(tabId, { type: RecorderUiMsgEnum.SHOW_UI }, - { frameId: 0 }); - }) - .then(() => { - let items = {}; - items[Local_Storage_Vars.RECORDING_STATE] = RecorderStateEnum.SHOWN; - return setChromeLocalStorageVariables(items); - }) - .then(() => { - return getRecordingTabId(); - }) - .then((tabId) => { - setBrowserActionUi(RecorderStateEnum.SHOWN, tabId); + chrome.downloads.download({ + filename: '_web_site_name.test', + saveAs: true, + url: window.URL.createObjectURL(blob) + }, (downloadId) => { + if (downloadId) { resolve(); - }) - .catch((message) => { - reject(message); - }) + } else { + reject('Download failed! Recording isn\'t stopped.'); + } }); + }); } - function hideContentScriptUi() { - return new Promise((resolve, reject) => { - getRecordingTabId() - .then((tabId) => { - return sendMessageToTab(tabId, - { type: RecorderUiMsgEnum.HIDE_UI }, - { frameId: 0 }); - }) - .then(() => { - let items = {}; - items[Local_Storage_Vars.RECORDING_STATE] = RecorderStateEnum.HIDDEN; - return setChromeLocalStorageVariables(items); - }) - .then(() => { - return getRecordingTabId(); - }) - .then((tabId) => { - setBrowserActionUi(RecorderStateEnum.HIDDEN, tabId); - resolve(); - }) - .catch((message) => { - reject(message); - }) - }); + async function downloadRecipeAndStopRecording() { + await downloadRecipe(); + await stopRecording(); + } + + async function showContentScriptUi() { + const tabId = await getRecordingTabId(); + await sendMessageToTab(tabId, { type: RecorderUiMsgEnum.SHOW_UI }, + { frameId: 0 }); + let items = {}; + items[Local_Storage_Vars.RECORDING_STATE] = RecorderStateEnum.SHOWN; + await setChromeLocalStorageVariables(items); + setBrowserActionUi(RecorderStateEnum.SHOWN, tabId); + } + + async function hideContentScriptUi() { + const tabId = await getRecordingTabId(); + await sendMessageToTab(tabId, { type: RecorderUiMsgEnum.HIDE_UI }, + { frameId: 0 }); + let items = {}; + items[Local_Storage_Vars.RECORDING_STATE] = RecorderStateEnum.HIDDEN; + await setChromeLocalStorageVariables(items); + setBrowserActionUi(RecorderStateEnum.HIDDEN, tabId); } // Reset the action recorder state to a clean slate every time the background @@ -580,136 +523,122 @@ }); }); - chrome.browserAction.onClicked.addListener((tab) => { - getRecordingState() - .then((state) => { - switch(state) { - case RecorderStateEnum.SHOWN: - hideContentScriptUi() - .catch((error) => { - console.error('Unable to hide the recorder UI!\r\n', error); - displayUserErrorMessage('Unable to hide the recording UI!'); - }); - break; - case RecorderStateEnum.HIDDEN: + async function browserActionOnClickedHander(tab) { + const state = await getRecordingState(); + switch(state) { + case RecorderStateEnum.SHOWN: + try { + await hideContentScriptUi(); + } catch (error) { + console.error('Unable to hide the recorder UI!\r\n', error); + displayUserErrorMessage('Unable to hide the recording UI!'); + } + break; + case RecorderStateEnum.HIDDEN: + try { showContentScriptUi() - .catch((error) => { - console.error('Unable to show the recorder UI!\r\n', error); - displayUserErrorMessage('Unable to show the recording UI!'); - }); - break; - default: - // By default, start recording on the current active tab. - clearRecorderVariables() - .then(() => initializeRecorderVariables(tab)) - .then(() => getAllFramesInTab(tab.id)) - .then((details) => { - let recordingStartedOnRootFramePromise; - details.forEach((frame) => { - // The extension has no need and no permission to inject script - // into 'about:' pages, such as the 'about:blank' page. - if (!frame.url.startsWith('about:')) { - const promise = - startRecordingOnTabAndFrame(tab.id, frame.frameId); - if (frame.frameId === 0) { - recordingStartedOnRootFramePromise = promise; - } else { - promise.catch((error) => { - console.warn( - `Unable to start recording for url ${tab.url}!\r\n`, - error); - }); - } - } - }); - return recordingStartedOnRootFramePromise; - }) - .then(() => console.log(`Started recording for tab ${tab.id}`)) - .catch((error) => { - console.error('Unable to start recording!\r\n', error); - displayUserErrorMessage('Unable to start recording!'); - stopRecording().catch((error) => { - console.warn('Unable to clean up recording!', error); - displayUserErrorMessage('Unable to clean up recording!'); - }); - }); - break; - } - }); + } catch(error) { + console.error('Unable to show the recorder UI!\r\n', error); + displayUserErrorMessage('Unable to show the recording UI!'); + } + break; + default: + // By default, start recording on the current active tab. + try { + await startRecording(tab); + } catch(startRecordingError) { + console.error('Unable to start recording!\r\n', startRecordingError); + displayUserErrorMessage('Unable to start recording!'); + try { + await stopRecording(); + } catch(stopRecordingError) { + console.warn('Unable to clean up recording!', stopRecordingError); + displayUserErrorMessage('Unable to clean up recording!'); + } + } + } + } + + chrome.browserAction.onClicked.addListener((tab) => { + browserActionOnClickedHander(tab); }); + async function tabsOnRemovedHandler(tabId) { + const recordingTabId = await getRecordingTabId(); + if (recordingTabId == tabId) { + try { + await downloadRecipe(); + await clearRecorderVariables(); + } catch (error) { + console.error( + `Unable to stop recording on the closing tab ${tabId}!\r\n`, + error); + } finally { + setBrowserActionUi(RecorderStateEnum.STOPPED); + } + } + } + chrome.tabs.onRemoved.addListener((tabId, removeInfo) => { - getRecordingTabId() - .then((recordingTabId) => { - if (recordingTabId == tabId) { - downloadRecipe() - .then(() => clearRecorderVariables()) - .finally(() => setBrowserActionUi(RecorderStateEnum.STOPPED)) - .catch((error) => { - console.error('Unable to stop recording on the closing tab ' + - `${tabId}!\r\n`, error); - }); - } - }); + tabsOnRemovedHandler(tabId); }); - chrome.webNavigation.onCompleted.addListener((details) => { - getRecordingTabId().then((tabId) => { - if (details.tabId === tabId && - // Skip recording on 'about:' pages. No meaningful user interaction - // occur on 'about:'' pages such as the blank page. Plus, this - // extension has no permission to access 'about:' pages. - !details.url.startsWith('about:')) { + async function webNavigationOnCompletedHander(details) { + const tabId = await getRecordingTabId(); + if (details.tabId === tabId && + // Skip recording on 'about:' pages. No meaningful user interaction + // occur on 'about:'' pages such as the blank page. Plus, this + // extension has no permission to access 'about:' pages. + !details.url.startsWith('about:')) { + try { + await startRecordingOnTabAndFrame(tabId, details.frameId); + console.log(`Resumed recording on tab ${tabId}`); + + if (details.frameId !== 0) { + return; + } // If the tab's root frame loaded a new page, log the page's url. // An engineer can truncate a test recipe generated for captured sites // using the 'loadPage' actions. If the Web Page Replay (WPR) tool can // serve a 'loadPage' action url, then the engineer can delete all the // actions that precedes the 'loadPage' action. - if (details.frameId === 0) { - addActionToRecipe({ - url: details.url, - context: { 'isIframe': false }, - type: 'loadPage' - }); - } + addActionToRecipe({ + url: details.url, + context: { 'isIframe': false }, + type: 'loadPage' + }); - startRecordingOnTabAndFrame(tabId, details.frameId) - .then(() => getRecordingState()) - .then((state) => { - console.log(`Resumed recording on tab ${tabId}`); - if (state === RecorderStateEnum.HIDDEN) { - setBrowserActionUi(RecorderStateEnum.SHOWN, tabId); - } - }) - .catch((error) => { - if (details.frameId === 0) { - console.error('Unable to resume recording!', error); - stopRecordingOnTab(tabId); - } + const state = await getRecordingState(); + if (state === RecorderStateEnum.HIDDEN) { + setBrowserActionUi(RecorderStateEnum.SHOWN, tabId); + } + } catch (error) { + if (details.frameId === 0) { + console.error('Unable to resume recording!', error); + await stopRecordingOnTab(tabId); + } else { console.warn('Unable to resume recording on the recording ' + `tab ${tabId}, frame ${details.frameId}, ` + `url '${details.url}'!`, error); - }); + } } - }); + } + } + + chrome.webNavigation.onCompleted.addListener((details) => { + webNavigationOnCompletedHander(details); }) chrome.runtime.onMessage.addListener((request, sender, sendResponse) => { if (!request) return false; switch (request.type) { - // Tab commands. case RecorderMsgEnum.SAVE: downloadRecipe() .then(() => sendResponse(true)); return true; case RecorderMsgEnum.STOP: - downloadRecipe() - .then(() => { - return stopRecording(); - }) - .then(() => clearBrowserCache()) - .then(() => console.log('Stopped Recording.')) + downloadRecipeAndStopRecording() .catch((error) => { console.error('Unable to stop recording!\r\n', error); displayUserErrorMessage('Unable to stop recording!'); @@ -718,8 +647,6 @@ break; case RecorderMsgEnum.CANCEL: stopRecording() - .then(() => clearBrowserCache()) - .then(() => console.log('Stopped Recording.')) .catch((error) => { console.error('Unable to stop recording!\r\n', error); displayUserErrorMessage('Unable to stop recording!'); @@ -727,18 +654,8 @@ sendResponse(true); break; case RecorderMsgEnum.ADD_ACTION: - addActionToRecipe(request.action) - .then((key) => { - sendResponse(true); - return getRecorderUiFrameId() - .then((frameId) => { - request.action.action_index = key; - return sendMessageToTab( - sender.tab.id, - { type: RecorderUiMsgEnum.ADD_ACTION, - action: request.action}, { frameId: frameId }); - }); - }) + addActionToRecipe(request.action, sender.tab.id) + .then(() => { return sendResponse(true); }) .catch((error) => { console.error( `Unable to add the ${request.action.type} action for ` +
diff --git a/components/test/data/autofill/automated_integration/action_recorder_extension/content/action_handler.js b/components/test/data/autofill/automated_integration/action_recorder_extension/content/action_handler.js index 26b7576..3fbe320 100644 --- a/components/test/data/autofill/automated_integration/action_recorder_extension/content/action_handler.js +++ b/components/test/data/autofill/automated_integration/action_recorder_extension/content/action_handler.js
@@ -523,7 +523,7 @@ if (iframe.name) { return Promise.resolve(iframe.name); } else { - return Promise.resolve(''); + return Promise.resolve(false); } }
diff --git a/content/browser/devtools/protocol/tracing_handler.cc b/content/browser/devtools/protocol/tracing_handler.cc index 4fbe6ed..2a67bcc 100644 --- a/content/browser/devtools/protocol/tracing_handler.cc +++ b/content/browser/devtools/protocol/tracing_handler.cc
@@ -34,6 +34,7 @@ #include "content/browser/frame_host/frame_tree_node.h" #include "content/browser/frame_host/navigation_handle_impl.h" #include "content/browser/frame_host/render_frame_host_impl.h" +#include "content/browser/gpu/gpu_process_host.h" #include "content/browser/renderer_host/render_widget_host_impl.h" #include "content/browser/tracing/tracing_controller_impl.h" #include "content/public/browser/browser_thread.h" @@ -404,7 +405,28 @@ options.fromMaybe("")); } - SetupProcessFilter(nullptr); + // GPU process id can only be retrieved on IO thread. Do some thread hopping. + BrowserThread::PostTaskAndReplyWithResult( + BrowserThread::IO, FROM_HERE, base::BindOnce([]() { + GpuProcessHost* gpu_process_host = GpuProcessHost::Get(); + return gpu_process_host ? gpu_process_host->GetProcessId() + : base::kNullProcessId; + }), + base::BindOnce(&TracingHandler::StartTracingWithGpuPid, + weak_factory_.GetWeakPtr(), std::move(callback))); +} + +void TracingHandler::StartTracingWithGpuPid( + std::unique_ptr<StartCallback> callback, + base::ProcessId gpu_pid) { + // Check if tracing was stopped in mid-air. + if (!did_initiate_recording_) { + callback->sendFailure(Response::Error( + "Tracing was stopped before start has been completed.")); + return; + } + + SetupProcessFilter(gpu_pid, nullptr); TracingController::GetInstance()->StartTracing( trace_config_, base::BindRepeating(&TracingHandler::OnRecordingEnabled, @@ -413,14 +435,20 @@ } void TracingHandler::SetupProcessFilter( + base::ProcessId gpu_pid, RenderFrameHost* new_render_frame_host) { if (!frame_tree_node_) return; base::ProcessId browser_pid = base::Process::Current().Pid(); std::unordered_set<base::ProcessId> included_process_ids({browser_pid}); + + if (gpu_pid != base::kNullProcessId) + included_process_ids.insert(gpu_pid); + if (new_render_frame_host) AppendProcessId(new_render_frame_host, &included_process_ids); + for (FrameTreeNode* node : frame_tree_node_->frame_tree()->SubtreeNodes(frame_tree_node_)) { RenderFrameHost* frame_host = node->current_frame_host(); @@ -495,8 +523,13 @@ void TracingHandler::OnRecordingEnabled( std::unique_ptr<StartCallback> callback) { - EmitFrameTree(); + if (!did_initiate_recording_) { + callback->sendFailure(Response::Error( + "Tracing was stopped before start has been completed.")); + return; + } + EmitFrameTree(); callback->sendSuccess(); bool screenshot_enabled; @@ -646,7 +679,8 @@ "FrameCommittedInBrowser", TRACE_EVENT_SCOPE_THREAD, "data", std::move(data)); - SetupProcessFilter(navigation_handle->GetRenderFrameHost()); + SetupProcessFilter(base::kNullProcessId, + navigation_handle->GetRenderFrameHost()); TracingController::GetInstance()->StartTracing( trace_config_, base::RepeatingCallback<void()>()); }
diff --git a/content/browser/devtools/protocol/tracing_handler.h b/content/browser/devtools/protocol/tracing_handler.h index fc3336a..97ba228 100644 --- a/content/browser/devtools/protocol/tracing_handler.h +++ b/content/browser/devtools/protocol/tracing_handler.h
@@ -116,7 +116,9 @@ CONTENT_EXPORT static base::trace_event::TraceConfig GetTraceConfigFromDevToolsConfig( const base::DictionaryValue& devtools_config); - void SetupProcessFilter(RenderFrameHost*); + void SetupProcessFilter(base::ProcessId gpu_pid, RenderFrameHost*); + void StartTracingWithGpuPid(std::unique_ptr<StartCallback>, + base::ProcessId gpu_pid); void AppendProcessId(RenderFrameHost*, std::unordered_set<base::ProcessId>* process_set); void OnProcessReady(RenderProcessHost*);
diff --git a/content/browser/gpu/gpu_process_host.cc b/content/browser/gpu/gpu_process_host.cc index 0d8c115..11f7f15 100644 --- a/content/browser/gpu/gpu_process_host.cc +++ b/content/browser/gpu/gpu_process_host.cc
@@ -677,6 +677,10 @@ return nullptr; } +base::ProcessId GpuProcessHost::GetProcessId() const { + return initialized_ ? process_->GetProcess().Pid() : base::kNullProcessId; +} + // static int GpuProcessHost::GetGpuCrashCount() { return static_cast<int>(base::subtle::NoBarrier_Load(&gpu_crash_count_));
diff --git a/content/browser/gpu/gpu_process_host.h b/content/browser/gpu/gpu_process_host.h index 33ad6bd..c549b68 100644 --- a/content/browser/gpu/gpu_process_host.h +++ b/content/browser/gpu/gpu_process_host.h
@@ -118,6 +118,7 @@ // null if the process no longer exists. static GpuProcessHost* FromID(int host_id); int host_id() const { return host_id_; } + base::ProcessId GetProcessId() const; // IPC::Sender implementation. bool Send(IPC::Message* msg) override;
diff --git a/content/browser/loader/merkle_integrity_source_stream.cc b/content/browser/loader/merkle_integrity_source_stream.cc index 94c532f..7749766 100644 --- a/content/browser/loader/merkle_integrity_source_stream.cc +++ b/content/browser/loader/merkle_integrity_source_stream.cc
@@ -6,7 +6,7 @@ #include <string.h> -#include "base/base64url.h" +#include "base/base64.h" #include "base/big_endian.h" #include "base/numerics/safe_conversions.h" #include "net/base/io_buffer.h" @@ -19,7 +19,7 @@ // maximum record size in TLS and the default maximum frame size in HTTP/2. constexpr uint64_t kMaxRecordSize = 16 * 1024; -constexpr char kMiSha256Header[] = "mi-sha256-draft2="; +constexpr char kMiSha256Header[] = "mi-sha256-03="; constexpr size_t kMiSha256HeaderLength = sizeof(kMiSha256Header) - 1; // Copies as many bytes from |input| as will fit in |output| and advances both. @@ -34,16 +34,14 @@ } // namespace MerkleIntegritySourceStream::MerkleIntegritySourceStream( - base::StringPiece mi_header_value, + base::StringPiece digest_header_value, std::unique_ptr<SourceStream> upstream) // TODO(ksakamoto): Use appropriate SourceType. : net::FilterSourceStream(SourceStream::TYPE_NONE, std::move(upstream)) { - // TODO(ksakamoto): Support quoted parameter value. std::string next_proof; - if (!mi_header_value.starts_with(kMiSha256Header) || - !base::Base64UrlDecode(mi_header_value.substr(kMiSha256HeaderLength), - base::Base64UrlDecodePolicy::DISALLOW_PADDING, - &next_proof) || + if (!digest_header_value.starts_with(kMiSha256Header) || + !base::Base64Decode(digest_header_value.substr(kMiSha256HeaderLength), + &next_proof) || next_proof.size() != SHA256_DIGEST_LENGTH) { failed_ = true; } else { @@ -91,7 +89,17 @@ if (record_size_ == 0) { base::span<const char> bytes; if (!ConsumeBytes(input, 8, &bytes, &storage)) { - return !upstream_eof_reached; + if (!upstream_eof_reached) { + return true; // Wait for more data later. + } + if (partial_input_.empty()) { + // As a special case, the encoding of an empty payload is itself an + // empty message (i.e. it omits the initial record size), and its + // integrity proof is SHA-256("\0"). + final_record_done_ = true; + return ProcessRecord({}, final_record_done_, output); + } + return false; } uint64_t record_size; base::ReadBigEndian(bytes.data(), &record_size); @@ -124,14 +132,8 @@ } // The final record is shorter and does not contain a hash. Process all - // remaining input the final record. - // - // TODO(davidben): This matches the previous implementation in that it - // allows empty final records, but this does not match the specification - // and means some inputs have two valid encodings. However, the - // specification's version cannot represent the empty string. Update this - // when https://github.com/martinthomson/http-mice/issues/3 is resolved. - if (partial_input_.size() > record_size_) { + // remaining input as the final record. + if (partial_input_.empty() || partial_input_.size() > record_size_) { return false; } record = partial_input_;
diff --git a/content/browser/loader/merkle_integrity_source_stream.h b/content/browser/loader/merkle_integrity_source_stream.h index d255437..7fe7e4f 100644 --- a/content/browser/loader/merkle_integrity_source_stream.h +++ b/content/browser/loader/merkle_integrity_source_stream.h
@@ -19,12 +19,12 @@ // MerkleIntegritySourceStream decodes and validates content encoded with the // "mi-sha256" content encoding -// (https://tools.ietf.org/html/draft-thomson-http-mice-02). +// (https://tools.ietf.org/html/draft-thomson-http-mice-03). // TODO(ksakamoto): This class should eventually live in src/net/filter/. class CONTENT_EXPORT MerkleIntegritySourceStream : public net::FilterSourceStream { public: - MerkleIntegritySourceStream(base::StringPiece mi_header_value, + MerkleIntegritySourceStream(base::StringPiece digest_header_value, std::unique_ptr<SourceStream> upstream); ~MerkleIntegritySourceStream() override;
diff --git a/content/browser/loader/merkle_integrity_source_stream_unittest.cc b/content/browser/loader/merkle_integrity_source_stream_unittest.cc index 61c61692..8765b844a 100644 --- a/content/browser/loader/merkle_integrity_source_stream_unittest.cc +++ b/content/browser/loader/merkle_integrity_source_stream_unittest.cc
@@ -3,7 +3,7 @@ // found in the LICENSE file. #include "content/browser/loader/merkle_integrity_source_stream.h" -#include "base/base64url.h" +#include "base/base64.h" #include "net/base/io_buffer.h" #include "net/base/test_completion_callback.h" #include "net/filter/mock_source_stream.h" @@ -17,13 +17,13 @@ const int kSmallBufferSize = 1; const char kMIEmptyBody[] = - "mi-sha256-draft2=bjQLnP-zepicpUTmu3gKLHiQHT-zNzh2hRGjBhevoB0"; + "mi-sha256-03=bjQLnP+zepicpUTmu3gKLHiQHT+zNzh2hRGjBhevoB0="; const char kMISingleRecord[] = - "mi-sha256-draft2=dcRDgR2GM35DluAV13PzgnG6-pvQwPywfFvAu1UeFrs"; + "mi-sha256-03=dcRDgR2GM35DluAV13PzgnG6+pvQwPywfFvAu1UeFrs="; const char kMIMultipleRecords[] = - "mi-sha256-draft2=IVa9shfs0nyKEhHqtB3WVNANJ2Njm5KjQLjRtnbkYJ4"; + "mi-sha256-03=IVa9shfs0nyKEhHqtB3WVNANJ2Njm5KjQLjRtnbkYJ4="; const char kMIWholeNumberOfRecords[] = - "mi-sha256-draft2=L2vdwBplKvIr0ZPkcuskWZfEVDgVdHa6aD363UpKuZs"; + "mi-sha256-03=L2vdwBplKvIr0ZPkcuskWZfEVDgVdHa6aD363UpKuZs="; enum class ReadResultType { // Each call to AddReadResult is a separate read from the lower layer @@ -112,8 +112,7 @@ std::string Base64Decode(const char* hash) { std::string out; - EXPECT_TRUE(base::Base64UrlDecode( - hash, base::Base64UrlDecodePolicy::DISALLOW_PADDING, &out)); + EXPECT_TRUE(base::Base64Decode(hash, &out)); EXPECT_EQ(32u, out.size()); return out; } @@ -160,6 +159,14 @@ source()->AddReadResult(nullptr, 0, net::OK, GetParam().mode); std::string actual_output; int result = ReadStream(&actual_output); + EXPECT_EQ(net::OK, result); +} + +TEST_P(MerkleIntegritySourceStreamTest, EmptyStreamWrongHash) { + Init(kMISingleRecord); + source()->AddReadResult(nullptr, 0, net::OK, GetParam().mode); + std::string actual_output; + int result = ReadStream(&actual_output); EXPECT_EQ(net::ERR_CONTENT_DECODING_FAILED, result); } @@ -180,7 +187,7 @@ } TEST_P(MerkleIntegritySourceStreamTest, WrongMIAttributeName) { - Init("mi-sha256-draft1=bjQLnP-zepicpUTmu3gKLHiQHT-zNzh2hRGjBhevoB0"); + Init("mi-sha256-01=bjQLnP+zepicpUTmu3gKLHiQHT+zNzh2hRGjBhevoB0="); source()->AddReadResult(nullptr, 0, net::OK, GetParam().mode); std::string actual_output; int result = ReadStream(&actual_output); @@ -188,7 +195,7 @@ } TEST_P(MerkleIntegritySourceStreamTest, HashTooShort) { - Init("mi-sha256-draft2=bjQLnP-zepicpUTmu3gKLHiQHT-zNzh2hRGjBhevoA"); + Init("mi-sha256-03=bjQLnP+zepicpUTmu3gKLHiQHT+zNzh2hRGjBhevoA=="); source()->AddReadResult(nullptr, 0, net::OK, GetParam().mode); std::string actual_output; int result = ReadStream(&actual_output); @@ -196,7 +203,7 @@ } TEST_P(MerkleIntegritySourceStreamTest, HashTooLong) { - Init("mi-sha256-draft2=bjQLnP-zepicpUTmu3gKLHiQHT-zNzh2hRGjBhevoB0A"); + Init("mi-sha256-03=bjQLnP+zepicpUTmu3gKLHiQHT+zNzh2hRGjBhevoB0A"); source()->AddReadResult(nullptr, 0, net::OK, GetParam().mode); std::string actual_output; int result = ReadStream(&actual_output); @@ -211,7 +218,7 @@ source()->AddReadResult(nullptr, 0, net::OK, GetParam().mode); std::string actual_output; int result = ReadStream(&actual_output); - EXPECT_EQ(net::OK, result); + EXPECT_EQ(net::ERR_CONTENT_DECODING_FAILED, result); } TEST_P(MerkleIntegritySourceStreamTest, TruncatedRecordSize) { @@ -329,11 +336,11 @@ sizeof(kRecordSize), net::OK, GetParam().mode); source()->AddReadResult(kMessage.data(), 16, net::OK, GetParam().mode); std::string hash1 = - Base64Decode("OElbplJlPK-Rv6JNK6p5_515IaoPoZo-2elWL7OQ60A"); + Base64Decode("OElbplJlPK+Rv6JNK6p5/515IaoPoZo+2elWL7OQ60A="); source()->AddReadResult(hash1.data(), 32, net::OK, GetParam().mode); source()->AddReadResult(kMessage.data() + 16, 16, net::OK, GetParam().mode); std::string hash2 = - Base64Decode("iPMpmgExHPrbEX3_RvwP4d16fWlK4l--p75PUu_KyN0"); + Base64Decode("iPMpmgExHPrbEX3/RvwP4d16fWlK4l++p75PUu/KyN0="); source()->AddReadResult(hash2.data(), 32, net::OK, GetParam().mode); source()->AddReadResult(kMessage.data() + 32, kMessage.size() - 32, net::OK, GetParam().mode); @@ -353,9 +360,9 @@ std::string body(reinterpret_cast<const char*>(kRecordSize), sizeof(kRecordSize)); body += kMessage.substr(0, 16); - body += Base64Decode("OElbplJlPK-Rv6JNK6p5_515IaoPoZo-2elWL7OQ60A"); + body += Base64Decode("OElbplJlPK+Rv6JNK6p5/515IaoPoZo+2elWL7OQ60A="); body += kMessage.substr(16, 16); - body += Base64Decode("iPMpmgExHPrbEX3_RvwP4d16fWlK4l--p75PUu_KyN0"); + body += Base64Decode("iPMpmgExHPrbEX3/RvwP4d16fWlK4l++p75PUu/KyN0="); body += kMessage.substr(32); source()->AddReadResult(body.data(), body.size(), net::OK, GetParam().mode); @@ -375,11 +382,11 @@ sizeof(kRecordSize), net::OK, GetParam().mode); source()->AddReadResult(kMessage.data(), 16, net::OK, GetParam().mode); std::string hash1 = - Base64Decode("OElbplJlPK-Rv6JNK6p5_515IaoPoZo-2elWL7OQ60A"); + Base64Decode("OElbplJlPK+Rv6JNK6p5/515IaoPoZo+2elWL7OQ60A="); source()->AddReadResult(hash1.data(), 32, net::OK, GetParam().mode); source()->AddReadResult(kMessage.data() + 16, 16, net::OK, GetParam().mode); std::string hash2 = - Base64Decode("iPMpmgExHPrbEX3_RvwP4d16fWlK4l--p75PUu_KyN0"); + Base64Decode("iPMpmgExHPrbEX3/RvwP4d16fWlK4l++p75PUu/KyN0="); source()->AddReadResult(hash2.data(), 32, net::OK, GetParam().mode); source()->AddReadResult(kMessage.data() + 32, kMessage.size() - 32, net::OK, GetParam().mode); @@ -400,7 +407,7 @@ sizeof(kRecordSize), net::OK, GetParam().mode); source()->AddReadResult(kMessage.data(), 16, net::OK, GetParam().mode); std::string hash1 = - Base64Decode("OElbplJlPK-Rv6JNK6p5_515IaoPoZo-2elWL7OQ60A"); + Base64Decode("OElbplJlPK+Rv6JNK6p5/515IaoPoZo+2elWL7OQ60A="); source()->AddReadResult(hash1.data(), 32, net::OK, GetParam().mode); std::string actual_output; @@ -418,11 +425,11 @@ sizeof(kRecordSize), net::OK, GetParam().mode); source()->AddReadResult(kMessage.data(), 16, net::OK, GetParam().mode); std::string hash1 = - Base64Decode("OElbplJlPK-Rv6JNK6p5_515IaoPoZo-2elWL7OQ60A"); + Base64Decode("OElbplJlPK+Rv6JNK6p5/515IaoPoZo+2elWL7OQ60A="); source()->AddReadResult(hash1.data(), 32, net::OK, GetParam().mode); source()->AddReadResult(kMessage.data() + 16, 16, net::OK, GetParam().mode); std::string hash2 = - Base64Decode("iPMpmgExHPrbEX3_RvwP4d16fWlK4l--p75PUu_KyN0"); + Base64Decode("iPMpmgExHPrbEX3/RvwP4d16fWlK4l++p75PUu/KyN0="); source()->AddReadResult(hash2.data(), 32, net::OK, GetParam().mode); source()->AddReadResult(kMessage.data() + 32, kMessage.size() - 32, net::OK, GetParam().mode); @@ -447,11 +454,11 @@ sizeof(kRecordSize), net::OK, GetParam().mode); source()->AddReadResult(kMessage.data(), 16, net::OK, GetParam().mode); std::string hash1 = - Base64Decode("OElbplJlPK-Rv6JNK6p5_515IaoPoZo-2elWL7OQ60A"); + Base64Decode("OElbplJlPK+Rv6JNK6p5/515IaoPoZo+2elWL7OQ60A="); source()->AddReadResult(hash1.data(), 32, net::OK, GetParam().mode); source()->AddReadResult(kMessage.data() + 16, 16, net::OK, GetParam().mode); std::string hash2 = - Base64Decode("iPMpmgExHPrbEX3_RvwP4d16fWlK4l--p75PUu_KyN0"); + Base64Decode("iPMpmgExHPrbEX3/RvwP4d16fWlK4l++p75PUu/KyN0="); source()->AddReadResult(hash2.data(), 32, net::OK, GetParam().mode); // |hash2| is the hash of "atermelon", but this stream ends early. Decoding // thus should fail. @@ -463,14 +470,9 @@ EXPECT_EQ(kMessage, actual_output); } -// Test that the final record is allowed to be empty. -// -// TODO(davidben): This does not match the specification and means some inputs -// have two valid encodings. However, the specification's version cannot -// represent the empty string. Update the code and possibly this test depending -// on how https://github.com/martinthomson/http-mice/issues/3 is resolved. +// Test that the final record is not allowed to be empty. TEST_P(MerkleIntegritySourceStreamTest, EmptyFinalRecord) { - Init("mi-sha256-draft2=JJnIuaOEc2247K9V88VQAQy1GJuQ6ylaVM7mG69QkE4"); + Init("mi-sha256-03=JJnIuaOEc2247K9V88VQAQy1GJuQ6ylaVM7mG69QkE4="); const uint8_t kRecordSize[] = {0, 0, 0, 0, 0, 0, 0, 16}; const std::string kMessage( "When I grow up, I want to be a watermelon!! \xf0\x9f\x8d\x89"); @@ -479,21 +481,21 @@ sizeof(kRecordSize), net::OK, GetParam().mode); source()->AddReadResult(kMessage.data(), 16, net::OK, GetParam().mode); std::string hash1 = - Base64Decode("hhJEKpkbuZoWUjzBPAZxMUN2DXdJ6epkS0McZh77IXo"); + Base64Decode("hhJEKpkbuZoWUjzBPAZxMUN2DXdJ6epkS0McZh77IXo="); source()->AddReadResult(hash1.data(), 32, net::OK, GetParam().mode); source()->AddReadResult(kMessage.data() + 16, 16, net::OK, GetParam().mode); std::string hash2 = - Base64Decode("RKTTVSMiH3bkxUQKreVATPL1KUd5eqRdmDgRQcZq_80"); + Base64Decode("RKTTVSMiH3bkxUQKreVATPL1KUd5eqRdmDgRQcZq/80="); source()->AddReadResult(hash2.data(), 32, net::OK, GetParam().mode); source()->AddReadResult(kMessage.data() + 32, 16, net::OK, GetParam().mode); std::string hash3 = - Base64Decode("bjQLnP-zepicpUTmu3gKLHiQHT-zNzh2hRGjBhevoB0"); + Base64Decode("bjQLnP+zepicpUTmu3gKLHiQHT+zNzh2hRGjBhevoB0="); source()->AddReadResult(hash3.data(), 32, net::OK, GetParam().mode); source()->AddReadResult(nullptr, 0, net::OK, GetParam().mode); std::string actual_output; int rv = ReadStream(&actual_output); - EXPECT_EQ(static_cast<int>(kMessage.size()), rv); + EXPECT_EQ(net::ERR_CONTENT_DECODING_FAILED, rv); EXPECT_EQ(kMessage, actual_output); } @@ -507,11 +509,11 @@ sizeof(kRecordSize), net::OK, GetParam().mode); source()->AddReadResult(kMessage.data(), 16, net::OK, GetParam().mode); std::string hash1 = - Base64Decode("2s-MNG6NrTt556s__HYnQTjG3WOktEcXZ61O8mzG9f4"); + Base64Decode("2s+MNG6NrTt556s//HYnQTjG3WOktEcXZ61O8mzG9f4="); source()->AddReadResult(hash1.data(), 32, net::OK, GetParam().mode); source()->AddReadResult(kMessage.data() + 16, 16, net::OK, GetParam().mode); std::string hash2 = - Base64Decode("qa_cQSMjFyZsm0cnYG4H6LqwOM_hzMSclK6I8iVoZYQ"); + Base64Decode("qa/cQSMjFyZsm0cnYG4H6LqwOM/hzMSclK6I8iVoZYQ="); source()->AddReadResult(hash2.data(), 32, net::OK, GetParam().mode); source()->AddReadResult(kMessage.data() + 32, 16, net::OK, GetParam().mode); @@ -530,9 +532,9 @@ std::string body(reinterpret_cast<const char*>(kRecordSize), sizeof(kRecordSize)); body += kMessage.substr(0, 16); - body += Base64Decode("2s-MNG6NrTt556s__HYnQTjG3WOktEcXZ61O8mzG9f4"); + body += Base64Decode("2s+MNG6NrTt556s//HYnQTjG3WOktEcXZ61O8mzG9f4="); body += kMessage.substr(16, 16); - body += Base64Decode("qa_cQSMjFyZsm0cnYG4H6LqwOM_hzMSclK6I8iVoZYQ"); + body += Base64Decode("qa/cQSMjFyZsm0cnYG4H6LqwOM/hzMSclK6I8iVoZYQ="); body += kMessage.substr(32, 16); source()->AddReadResult(body.data(), body.size(), net::OK, GetParam().mode);
diff --git a/content/browser/loader/navigation_url_loader_impl.cc b/content/browser/loader/navigation_url_loader_impl.cc index ddfab263..8c557f2e 100644 --- a/content/browser/loader/navigation_url_loader_impl.cc +++ b/content/browser/loader/navigation_url_loader_impl.cc
@@ -380,6 +380,10 @@ static uint32_t GetURLLoaderOptions(bool is_main_frame) { uint32_t options = network::mojom::kURLLoadOptionNone; + + // Ensure that Mime sniffing works. + options |= network::mojom::kURLLoadOptionSniffMimeType; + if (is_main_frame) { // SSLInfo is not needed on subframe responses because users can inspect // only the certificate for the main frame when using the info bubble. @@ -387,9 +391,7 @@ options |= network::mojom::kURLLoadOptionSendSSLInfoForCertificateError; } - if (base::FeatureList::IsEnabled(network::features::kNetworkService)) { - options |= network::mojom::kURLLoadOptionSniffMimeType; - } else { + if (!base::FeatureList::IsEnabled(network::features::kNetworkService)) { // TODO(arthursonzogni): This is a temporary option. Remove this as soon // as the InterceptingResourceHandler is removed. // See https://crbug.com/791049.
diff --git a/content/browser/loader/resource_dispatcher_host_impl.cc b/content/browser/loader/resource_dispatcher_host_impl.cc index b595348..2ed617d 100644 --- a/content/browser/loader/resource_dispatcher_host_impl.cc +++ b/content/browser/loader/resource_dispatcher_host_impl.cc
@@ -1079,8 +1079,8 @@ request, static_cast<ResourceType>(request_data.resource_type), resource_context, request_data.fetch_request_mode, static_cast<RequestContextType>(request_data.fetch_request_context_type), - requester_info->appcache_service(), child_id, route_id, - std::move(handler)); + url_loader_options, requester_info->appcache_service(), child_id, + route_id, std::move(handler)); } std::unique_ptr<ResourceHandler> @@ -1090,6 +1090,7 @@ ResourceContext* resource_context, network::mojom::FetchRequestMode fetch_request_mode, RequestContextType fetch_request_context_type, + uint32_t url_loader_options, AppCacheService* appcache_service, int child_id, int route_id, @@ -1158,9 +1159,11 @@ // Note: all ResourceHandler following the MimeSniffingResourceHandler // should expect OnWillRead to be called *before* OnResponseStarted as // part of the mime sniffing process. - handler.reset(new MimeSniffingResourceHandler( - std::move(handler), this, plugin_service, intercepting_handler, request, - fetch_request_context_type)); + if (url_loader_options & network::mojom::kURLLoadOptionSniffMimeType) { + handler.reset(new MimeSniffingResourceHandler( + std::move(handler), this, plugin_service, intercepting_handler, request, + fetch_request_context_type)); + } // Add the pre mime sniffing throttles. handler.reset(new ThrottlingResourceHandler( @@ -1612,7 +1615,7 @@ handler = AddStandardHandlers( new_request.get(), resource_type, resource_context, network::mojom::FetchRequestMode::kNoCORS, - info.begin_params->request_context_type, + info.begin_params->request_context_type, url_loader_options, appcache_handle_core ? appcache_handle_core->GetAppCacheService() : nullptr, -1, // child_id
diff --git a/content/browser/loader/resource_dispatcher_host_impl.h b/content/browser/loader/resource_dispatcher_host_impl.h index d39156a..fe1365c 100644 --- a/content/browser/loader/resource_dispatcher_host_impl.h +++ b/content/browser/loader/resource_dispatcher_host_impl.h
@@ -597,6 +597,7 @@ ResourceContext* resource_context, network::mojom::FetchRequestMode fetch_request_mode, RequestContextType fetch_request_context_type, + uint32_t url_loader_options, AppCacheService* appcache_service, int child_id, int route_id,
diff --git a/content/browser/loader/resource_dispatcher_host_unittest.cc b/content/browser/loader/resource_dispatcher_host_unittest.cc index 891d4fa5..38053a77 100644 --- a/content/browser/loader/resource_dispatcher_host_unittest.cc +++ b/content/browser/loader/resource_dispatcher_host_unittest.cc
@@ -899,7 +899,7 @@ request.render_frame_id = render_frame_id; filter_->CreateLoaderAndStart( std::move(loader_request), render_view_id, request_id, - network::mojom::kURLLoadOptionNone, request, std::move(client), + network::mojom::kURLLoadOptionSniffMimeType, request, std::move(client), net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS)); } @@ -914,7 +914,7 @@ network::ResourceRequest request = CreateResourceRequest("GET", type, url); filter->CreateLoaderAndStart( std::move(loader_request), render_view_id, request_id, - network::mojom::kURLLoadOptionNone, request, std::move(client), + network::mojom::kURLLoadOptionSniffMimeType, request, std::move(client), net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS)); }
diff --git a/content/browser/loader/url_loader_factory_impl_unittest.cc b/content/browser/loader/url_loader_factory_impl_unittest.cc index 9385955b..168eed74 100644 --- a/content/browser/loader/url_loader_factory_impl_unittest.cc +++ b/content/browser/loader/url_loader_factory_impl_unittest.cc
@@ -149,7 +149,8 @@ request.request_initiator = url::Origin::Create(request.url); factory_->CreateLoaderAndStart( mojo::MakeRequest(&loader), kRoutingId, kRequestId, - network::mojom::kURLLoadOptionNone, request, client.CreateInterfacePtr(), + network::mojom::kURLLoadOptionSniffMimeType, request, + client.CreateInterfacePtr(), net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS)); ASSERT_FALSE(client.has_received_response()); @@ -224,8 +225,9 @@ // Need to set same-site |request_initiator| for non main frame type request. request.request_initiator = url::Origin::Create(request.url); factory_->CreateLoaderAndStart( - mojo::MakeRequest(&loader), 2, 1, network::mojom::kURLLoadOptionNone, - request, client.CreateInterfacePtr(), + mojo::MakeRequest(&loader), 2, 1, + network::mojom::kURLLoadOptionSniffMimeType, request, + client.CreateInterfacePtr(), net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS)); client.RunUntilComplete(); @@ -253,8 +255,9 @@ // Need to set same-site |request_initiator| for non main frame type request. request.request_initiator = url::Origin::Create(request.url); factory_->CreateLoaderAndStart( - mojo::MakeRequest(&loader), 2, 1, network::mojom::kURLLoadOptionNone, - request, client.CreateInterfacePtr(), + mojo::MakeRequest(&loader), 2, 1, + network::mojom::kURLLoadOptionSniffMimeType, request, + client.CreateInterfacePtr(), net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS)); client.RunUntilComplete(); @@ -281,8 +284,9 @@ request.request_initiator = url::Origin::Create(request.url); ASSERT_FALSE(request.url.is_valid()); factory_->CreateLoaderAndStart( - mojo::MakeRequest(&loader), 2, 1, network::mojom::kURLLoadOptionNone, - request, client.CreateInterfacePtr(), + mojo::MakeRequest(&loader), 2, 1, + network::mojom::kURLLoadOptionSniffMimeType, request, + client.CreateInterfacePtr(), net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS)); client.RunUntilComplete(); @@ -310,8 +314,9 @@ // Need to set same-site |request_initiator| for non main frame type request. request.request_initiator = url::Origin::Create(request.url); factory_->CreateLoaderAndStart( - mojo::MakeRequest(&loader), 2, 1, network::mojom::kURLLoadOptionNone, - request, client.CreateInterfacePtr(), + mojo::MakeRequest(&loader), 2, 1, + network::mojom::kURLLoadOptionSniffMimeType, request, + client.CreateInterfacePtr(), net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS)); client.RunUntilComplete(); @@ -343,7 +348,8 @@ request.report_raw_headers = true; factory_->CreateLoaderAndStart( mojo::MakeRequest(&loader), kRoutingId, kRequestId, - network::mojom::kURLLoadOptionNone, request, client.CreateInterfacePtr(), + network::mojom::kURLLoadOptionSniffMimeType, request, + client.CreateInterfacePtr(), net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS)); client.RunUntilComplete(); @@ -403,7 +409,8 @@ request.request_initiator = url::Origin::Create(request.url); factory_->CreateLoaderAndStart( mojo::MakeRequest(&loader), kRoutingId, kRequestId, - network::mojom::kURLLoadOptionNone, request, client.CreateInterfacePtr(), + network::mojom::kURLLoadOptionSniffMimeType, request, + client.CreateInterfacePtr(), net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS)); base::RunLoop().RunUntilIdle();
diff --git a/content/browser/media/capture/desktop_capture_device.cc b/content/browser/media/capture/desktop_capture_device.cc index 01954292..50510bd 100644 --- a/content/browser/media/capture/desktop_capture_device.cc +++ b/content/browser/media/capture/desktop_capture_device.cc
@@ -313,7 +313,9 @@ IncrementDesktopCaptureCounter(WINDOW_CAPTURER_PERMANENT_ERROR); } } - client_->OnError(FROM_HERE, "The desktop capturer has failed."); + client_->OnError(media::VideoCaptureError:: + kDesktopCaptureDeviceWebrtcDesktopCapturerHasFailed, + FROM_HERE, "The desktop capturer has failed."); } return; }
diff --git a/content/browser/media/capture/desktop_capture_device_unittest.cc b/content/browser/media/capture/desktop_capture_device_unittest.cc index bfbb57d1..636f20a 100644 --- a/content/browser/media/capture/desktop_capture_device_unittest.cc +++ b/content/browser/media/capture/desktop_capture_device_unittest.cc
@@ -271,7 +271,7 @@ std::unique_ptr<media::MockVideoCaptureDeviceClient> client( CreateMockVideoCaptureDeviceClient()); - EXPECT_CALL(*client, OnError(_, _)).Times(0); + EXPECT_CALL(*client, OnError(_, _, _)).Times(0); EXPECT_CALL(*client, OnStarted()); EXPECT_CALL(*client, OnIncomingCapturedData(_, _, _, _, _, _, _)) .WillRepeatedly( @@ -310,7 +310,7 @@ std::unique_ptr<media::MockVideoCaptureDeviceClient> client( CreateMockVideoCaptureDeviceClient()); - EXPECT_CALL(*client, OnError(_, _)).Times(0); + EXPECT_CALL(*client, OnError(_, _, _)).Times(0); EXPECT_CALL(*client, OnStarted()); EXPECT_CALL(*client, OnIncomingCapturedData(_, _, _, _, _, _, _)) .WillRepeatedly( @@ -356,7 +356,7 @@ std::unique_ptr<media::MockVideoCaptureDeviceClient> client( CreateMockVideoCaptureDeviceClient()); - EXPECT_CALL(*client, OnError(_,_)).Times(0); + EXPECT_CALL(*client, OnError(_, _, _)).Times(0); EXPECT_CALL(*client, OnStarted()); EXPECT_CALL(*client, OnIncomingCapturedData(_, _, _, _, _, _, _)) .WillRepeatedly( @@ -406,7 +406,7 @@ std::unique_ptr<media::MockVideoCaptureDeviceClient> client( CreateMockVideoCaptureDeviceClient()); - EXPECT_CALL(*client, OnError(_,_)).Times(0); + EXPECT_CALL(*client, OnError(_, _, _)).Times(0); EXPECT_CALL(*client, OnStarted()); EXPECT_CALL(*client, OnIncomingCapturedData(_, _, _, _, _, _, _)) .WillRepeatedly( @@ -458,7 +458,7 @@ std::unique_ptr<media::MockVideoCaptureDeviceClient> client( CreateMockVideoCaptureDeviceClient()); - EXPECT_CALL(*client, OnError(_,_)).Times(0); + EXPECT_CALL(*client, OnError(_, _, _)).Times(0); EXPECT_CALL(*client, OnStarted()); EXPECT_CALL(*client, OnIncomingCapturedData(_, _, _, _, _, _, _)) .WillRepeatedly( @@ -507,7 +507,7 @@ std::unique_ptr<media::MockVideoCaptureDeviceClient> client( CreateMockVideoCaptureDeviceClient()); - EXPECT_CALL(*client, OnError(_,_)).Times(0); + EXPECT_CALL(*client, OnError(_, _, _)).Times(0); EXPECT_CALL(*client, OnStarted()); EXPECT_CALL(*client, OnIncomingCapturedData(_, _, _, _, _, _, _)) .WillRepeatedly( @@ -563,7 +563,7 @@ std::unique_ptr<media::MockVideoCaptureDeviceClient> client( CreateMockVideoCaptureDeviceClient()); - EXPECT_CALL(*client, OnError(_, _)).Times(0); + EXPECT_CALL(*client, OnError(_, _, _)).Times(0); // On started is called from the capture thread. EXPECT_CALL(*client, OnStarted()) .WillOnce(InvokeWithoutArgs([this, &task_runner] {
diff --git a/content/browser/media/capture/fake_video_capture_stack.cc b/content/browser/media/capture/fake_video_capture_stack.cc index 8bd1c9c1..cb5c27e5 100644 --- a/content/browser/media/capture/fake_video_capture_stack.cc +++ b/content/browser/media/capture/fake_video_capture_stack.cc
@@ -86,7 +86,9 @@ buffers_.erase(it); } - void OnError() final { capture_stack_->error_occurred_ = true; } + void OnError(media::VideoCaptureError) final { + capture_stack_->error_occurred_ = true; + } void OnLog(const std::string& message) final { capture_stack_->log_messages_.push_back(message);
diff --git a/content/browser/media/capture/frame_sink_video_capture_device.cc b/content/browser/media/capture/frame_sink_video_capture_device.cc index 08e7063..d6b5e31 100644 --- a/content/browser/media/capture/frame_sink_video_capture_device.cc +++ b/content/browser/media/capture/frame_sink_video_capture_device.cc
@@ -74,7 +74,8 @@ // If the device has already ended on a fatal error, abort immediately. if (fatal_error_message_) { receiver->OnLog(*fatal_error_message_); - receiver->OnError(); + receiver->OnError(media::VideoCaptureError:: + kFrameSinkVideoCaptureDeviceAleradyEndedOnFatalError); return; } @@ -332,7 +333,8 @@ fatal_error_message_ = std::move(message); if (receiver_) { receiver_->OnLog(*fatal_error_message_); - receiver_->OnError(); + receiver_->OnError(media::VideoCaptureError:: + kFrameSinkVideoCaptureDeviceEncounteredFatalError); } StopAndDeAllocate();
diff --git a/content/browser/media/capture/frame_sink_video_capture_device_unittest.cc b/content/browser/media/capture/frame_sink_video_capture_device_unittest.cc index 51982c2c..d76d6409 100644 --- a/content/browser/media/capture/frame_sink_video_capture_device_unittest.cc +++ b/content/browser/media/capture/frame_sink_video_capture_device_unittest.cc
@@ -184,7 +184,7 @@ Buffer::ScopedAccessPermission* buffer_read_permission, const media::mojom::VideoFrameInfo* frame_info)); MOCK_METHOD1(OnBufferRetired, void(int buffer_id)); - MOCK_METHOD0(OnError, void()); + MOCK_METHOD1(OnError, void(media::VideoCaptureError error)); MOCK_METHOD1(OnLog, void(const std::string& message)); MOCK_METHOD0(OnStarted, void()); void OnStartedUsingGpuDecode() final { NOTREACHED(); } @@ -416,7 +416,7 @@ auto receiver_ptr = std::make_unique<MockVideoFrameReceiver>(); auto* const receiver = receiver_ptr.get(); EXPECT_CALL(*receiver, OnStarted()); - EXPECT_CALL(*receiver, OnError()).Times(0); + EXPECT_CALL(*receiver, OnError(_)).Times(0); AllocateAndStartSynchronouslyWithExpectations(std::move(receiver_ptr)); // From this point, there is no reason the capturer should be re-started. @@ -555,7 +555,7 @@ Sequence sequence; EXPECT_CALL(*receiver, OnStarted()).InSequence(sequence); EXPECT_CALL(*receiver, OnLog(StrNe(""))).InSequence(sequence); - EXPECT_CALL(*receiver, OnError()).InSequence(sequence); + EXPECT_CALL(*receiver, OnError(_)).InSequence(sequence); AllocateAndStartSynchronouslyWithExpectations(std::move(receiver_ptr)); @@ -581,7 +581,7 @@ { EXPECT_CALL(*receiver, OnStarted()).Times(0); EXPECT_CALL(*receiver, OnLog(StrNe(""))); - EXPECT_CALL(*receiver, OnError()); + EXPECT_CALL(*receiver, OnError(_)); EXPECT_CALL(capturer_, MockStart(_)).Times(0); POST_DEVICE_METHOD_CALL(AllocateAndStartWithReceiver, GetCaptureParams(),
diff --git a/content/browser/media/capture/screen_capture_device_android.cc b/content/browser/media/capture/screen_capture_device_android.cc index 9d5cf89..d97c36be 100644 --- a/content/browser/media/capture/screen_capture_device_android.cc +++ b/content/browser/media/capture/screen_capture_device_android.cc
@@ -25,8 +25,10 @@ if (params.requested_format.pixel_format != media::PIXEL_FORMAT_I420) { client->OnError( - FROM_HERE, "unsupported format: " + media::VideoCaptureFormat::ToString( - params.requested_format)); + media::VideoCaptureError::kAndroidScreenCaptureUnsupportedFormat, + FROM_HERE, + "unsupported format: " + + media::VideoCaptureFormat::ToString(params.requested_format)); return; } @@ -34,7 +36,10 @@ oracle_proxy_ = new media::ThreadSafeCaptureOracle(std::move(client), params); if (!capture_machine_.Start(oracle_proxy_, params)) { - oracle_proxy_->ReportError(FROM_HERE, "Failed to start capture machine."); + oracle_proxy_->ReportError( + media::VideoCaptureError:: + kAndroidScreenCaptureFailedToStartCaptureMachine, + FROM_HERE, "Failed to start capture machine."); StopAndDeAllocate(); } else { // The |capture_machine_| will later report to the |oracle_proxy_| whether
diff --git a/content/browser/media/capture/screen_capture_device_android_unittest.cc b/content/browser/media/capture/screen_capture_device_android_unittest.cc index dda49dc..9e1030c1 100644 --- a/content/browser/media/capture/screen_capture_device_android_unittest.cc +++ b/content/browser/media/capture/screen_capture_device_android_unittest.cc
@@ -36,8 +36,9 @@ MOCK_METHOD0(DoOnIncomingCapturedBuffer, void(void)); MOCK_METHOD0(DoOnIncomingCapturedVideoFrame, void(void)); MOCK_METHOD0(DoResurrectLastOutputBuffer, void(void)); - MOCK_METHOD2(OnError, - void(const base::Location& from_here, + MOCK_METHOD3(OnError, + void(media::VideoCaptureError error, + const base::Location& from_here, const std::string& reason)); MOCK_CONST_METHOD0(GetBufferPoolUtilization, double(void)); MOCK_METHOD0(OnStarted, void(void)); @@ -95,7 +96,7 @@ ASSERT_TRUE(capture_device); std::unique_ptr<MockDeviceClient> client(new MockDeviceClient()); - EXPECT_CALL(*client, OnError(_, _)).Times(0); + EXPECT_CALL(*client, OnError(_, _, _)).Times(0); // |STARTED| is reported asynchronously, which may not be received if capture // is stopped immediately. EXPECT_CALL(*client, OnStarted()).Times(AtMost(1));
diff --git a/content/browser/renderer_host/media/in_process_video_capture_device_launcher.cc b/content/browser/renderer_host/media/in_process_video_capture_device_launcher.cc index 49c32ae3..ffa3e8c 100644 --- a/content/browser/renderer_host/media/in_process_video_capture_device_launcher.cc +++ b/content/browser/renderer_host/media/in_process_video_capture_device_launcher.cc
@@ -261,7 +261,9 @@ if (!device) { switch (state_copy) { case State::DEVICE_START_IN_PROGRESS: - callbacks->OnDeviceLaunchFailed(); + callbacks->OnDeviceLaunchFailed( + media::VideoCaptureError:: + kInProcessDeviceLauncherFailedToCreateDeviceInstance); base::ResetAndReturn(&done_cb).Run(); return; case State::DEVICE_START_ABORTING:
diff --git a/content/browser/renderer_host/media/service_video_capture_device_launcher.cc b/content/browser/renderer_host/media/service_video_capture_device_launcher.cc index c2bf65e7..07e01aaa 100644 --- a/content/browser/renderer_host/media/service_video_capture_device_launcher.cc +++ b/content/browser/renderer_host/media/service_video_capture_device_launcher.cc
@@ -38,6 +38,7 @@ void ConcludeLaunchDeviceWithFailure( bool abort_requested, + media::VideoCaptureError error, std::unique_ptr<VideoCaptureFactoryDelegate> device_factory, VideoCaptureDeviceLauncher::Callbacks* callbacks, base::OnceClosure done_cb) { @@ -45,7 +46,7 @@ if (abort_requested) callbacks->OnDeviceLaunchAborted(); else - callbacks->OnDeviceLaunchFailed(); + callbacks->OnDeviceLaunchFailed(error); base::ResetAndReturn(&done_cb).Run(); } @@ -84,8 +85,11 @@ // This can happen when the ServiceVideoCaptureProvider owning // |device_factory_| loses connection to the service process and resets // |device_factory_|. - ConcludeLaunchDeviceWithFailure(false, std::move(device_factory_), - callbacks, std::move(done_cb)); + ConcludeLaunchDeviceWithFailure( + false, + media::VideoCaptureError:: + kServiceDeviceLauncherLostConnectionToDeviceFactoryDuringDeviceStart, + std::move(device_factory_), callbacks, std::move(done_cb)); return; } @@ -157,9 +161,11 @@ return; case video_capture::mojom::DeviceAccessResultCode::ERROR_DEVICE_NOT_FOUND: case video_capture::mojom::DeviceAccessResultCode::NOT_INITIALIZED: - ConcludeLaunchDeviceWithFailure(abort_requested, - std::move(device_factory_), callbacks, - std::move(done_cb_)); + ConcludeLaunchDeviceWithFailure( + abort_requested, + media::VideoCaptureError:: + kServiceDeviceLauncherServiceRespondedWithDeviceNotFound, + std::move(device_factory_), callbacks, std::move(done_cb_)); return; } } @@ -172,8 +178,11 @@ state_ = State::READY_TO_LAUNCH; Callbacks* callbacks = callbacks_; callbacks_ = nullptr; - ConcludeLaunchDeviceWithFailure(abort_requested, std::move(device_factory_), - callbacks, std::move(done_cb_)); + ConcludeLaunchDeviceWithFailure( + abort_requested, + media::VideoCaptureError:: + kServiceDeviceLauncherConnectionLostWhileWaitingForCallback, + std::move(device_factory_), callbacks, std::move(done_cb_)); } } // namespace content
diff --git a/content/browser/renderer_host/media/service_video_capture_device_launcher_unittest.cc b/content/browser/renderer_host/media/service_video_capture_device_launcher_unittest.cc index 2c04a18..37c7326 100644 --- a/content/browser/renderer_host/media/service_video_capture_device_launcher_unittest.cc +++ b/content/browser/renderer_host/media/service_video_capture_device_launcher_unittest.cc
@@ -74,7 +74,7 @@ MOCK_METHOD1(DoOnDeviceLaunched, void(std::unique_ptr<LaunchedVideoCaptureDevice>* device)); - MOCK_METHOD0(OnDeviceLaunchFailed, void()); + MOCK_METHOD1(OnDeviceLaunchFailed, void(media::VideoCaptureError error)); MOCK_METHOD0(OnDeviceLaunchAborted, void()); }; @@ -157,7 +157,7 @@ EXPECT_CALL(mock_callbacks_, DoOnDeviceLaunched(_)).Times(1); EXPECT_CALL(mock_callbacks_, OnDeviceLaunchAborted()).Times(0); - EXPECT_CALL(mock_callbacks_, OnDeviceLaunchFailed()).Times(0); + EXPECT_CALL(mock_callbacks_, OnDeviceLaunchFailed(_)).Times(0); EXPECT_CALL(connection_lost_cb_, Run()).Times(0); base::RunLoop wait_for_done_cb; EXPECT_CALL(done_cb_, Run()) @@ -224,7 +224,7 @@ })); EXPECT_CALL(mock_callbacks_, DoOnDeviceLaunched(_)).Times(0); EXPECT_CALL(mock_callbacks_, OnDeviceLaunchAborted()).Times(1); - EXPECT_CALL(mock_callbacks_, OnDeviceLaunchFailed()).Times(0); + EXPECT_CALL(mock_callbacks_, OnDeviceLaunchFailed(_)).Times(0); EXPECT_CALL(connection_lost_cb_, Run()).Times(0); EXPECT_CALL(done_cb_, Run()).WillOnce(InvokeWithoutArgs([&step_2_run_loop]() { step_2_run_loop.Quit(); @@ -272,7 +272,11 @@ })); EXPECT_CALL(mock_callbacks_, DoOnDeviceLaunched(_)).Times(0); EXPECT_CALL(mock_callbacks_, OnDeviceLaunchAborted()).Times(0); - EXPECT_CALL(mock_callbacks_, OnDeviceLaunchFailed()).Times(1); + EXPECT_CALL(mock_callbacks_, + OnDeviceLaunchFailed( + media::VideoCaptureError:: + kServiceDeviceLauncherServiceRespondedWithDeviceNotFound)) + .Times(1); EXPECT_CALL(connection_lost_cb_, Run()).Times(0); EXPECT_CALL(done_cb_, Run()).WillOnce(InvokeWithoutArgs([&run_loop]() { run_loop.Quit(); @@ -292,7 +296,7 @@ EXPECT_CALL(mock_callbacks_, DoOnDeviceLaunched(_)).Times(0); EXPECT_CALL(mock_callbacks_, OnDeviceLaunchAborted()).Times(0); - EXPECT_CALL(mock_callbacks_, OnDeviceLaunchFailed()).Times(1); + EXPECT_CALL(mock_callbacks_, OnDeviceLaunchFailed(_)).Times(1); EXPECT_CALL(connection_lost_cb_, Run()).Times(0); EXPECT_CALL(done_cb_, Run()).WillOnce(InvokeWithoutArgs([&run_loop]() { run_loop.Quit(); @@ -327,7 +331,7 @@ })); EXPECT_CALL(mock_callbacks_, DoOnDeviceLaunched(_)).Times(0); EXPECT_CALL(mock_callbacks_, OnDeviceLaunchAborted()).Times(0); - EXPECT_CALL(mock_callbacks_, OnDeviceLaunchFailed()).Times(1); + EXPECT_CALL(mock_callbacks_, OnDeviceLaunchFailed(_)).Times(1); // Note: |connection_lost_cb_| is only meant to be called when the connection // to a successfully-launched device is lost, which is not the case here. EXPECT_CALL(connection_lost_cb_, Run()).Times(0);
diff --git a/content/browser/renderer_host/media/service_video_capture_provider_unittest.cc b/content/browser/renderer_host/media/service_video_capture_provider_unittest.cc index b080b096..0b5aecf 100644 --- a/content/browser/renderer_host/media/service_video_capture_provider_unittest.cc +++ b/content/browser/renderer_host/media/service_video_capture_provider_unittest.cc
@@ -103,7 +103,7 @@ MOCK_METHOD1(DoOnDeviceLaunched, void(std::unique_ptr<LaunchedVideoCaptureDevice>* device)); - MOCK_METHOD0(OnDeviceLaunchFailed, void()); + MOCK_METHOD1(OnDeviceLaunchFailed, void(media::VideoCaptureError error)); MOCK_METHOD0(OnDeviceLaunchAborted, void()); };
diff --git a/content/browser/renderer_host/media/video_capture_browsertest.cc b/content/browser/renderer_host/media/video_capture_browsertest.cc index ee5dd193..7306b1e 100644 --- a/content/browser/renderer_host/media/video_capture_browsertest.cc +++ b/content/browser/renderer_host/media/video_capture_browsertest.cc
@@ -48,7 +48,8 @@ const media::mojom::VideoFrameInfoPtr& frame_info)); MOCK_METHOD1(OnStarted, void(VideoCaptureControllerID)); MOCK_METHOD1(OnEnded, void(VideoCaptureControllerID)); - MOCK_METHOD1(OnError, void(VideoCaptureControllerID)); + MOCK_METHOD2(OnError, + void(VideoCaptureControllerID, media::VideoCaptureError)); MOCK_METHOD1(OnStartedUsingGpuDecode, void(VideoCaptureControllerID)); MOCK_METHOD1(OnStoppedUsingGpuDecode, void(VideoCaptureControllerID)); @@ -148,7 +149,7 @@ video_capture_manager_->DisconnectClient(controller_.get(), stub_client_id_, &mock_controller_event_handler_, - false); + media::VideoCaptureError::kNone); EXPECT_CALL(mock_stream_provider_listener_, Closed(_, _)) .WillOnce(InvokeWithoutArgs([continuation]() { continuation.Run(); }));
diff --git a/content/browser/renderer_host/media/video_capture_controller.cc b/content/browser/renderer_host/media/video_capture_controller.cc index 3b006ff..af010ab 100644 --- a/content/browser/renderer_host/media/video_capture_controller.cc +++ b/content/browser/renderer_host/media/video_capture_controller.cc
@@ -47,9 +47,10 @@ base::UmaHistogramSparse( \ name, (height) ? ((width)*100) / (height) : kInfiniteRatio); -void CallOnError(VideoCaptureControllerEventHandler* client, +void CallOnError(media::VideoCaptureError error, + VideoCaptureControllerEventHandler* client, VideoCaptureControllerID id) { - client->OnError(id); + client->OnError(id, error); } void CallOnStarted(VideoCaptureControllerEventHandler* client, @@ -233,7 +234,10 @@ // invalid or unsupported parameters. LOG(DFATAL) << "Invalid or unsupported video capture parameters requested: " << media::VideoCaptureFormat::ToString(params.requested_format); - event_handler->OnError(id); + event_handler->OnError( + id, + media::VideoCaptureError:: + kVideoCaptureControllerInvalidOrUnsupportedVideoCaptureParametersRequested); return; } @@ -243,7 +247,9 @@ // Signal error in case device is already in error state. if (state_ == VIDEO_CAPTURE_STATE_ERROR) { - event_handler->OnError(id); + event_handler->OnError( + id, + media::VideoCaptureError::kVideoCaptureControllerIsAlreadyInErrorState); return; } @@ -498,10 +504,10 @@ buffer_context_iter->set_is_retired(); } -void VideoCaptureController::OnError() { +void VideoCaptureController::OnError(media::VideoCaptureError error) { DCHECK_CURRENTLY_ON(BrowserThread::IO); state_ = VIDEO_CAPTURE_STATE_ERROR; - PerformForClientsWithOpenSession(base::Bind(&CallOnError)); + PerformForClientsWithOpenSession(base::BindRepeating(&CallOnError, error)); } void VideoCaptureController::OnLog(const std::string& message) { @@ -512,13 +518,14 @@ void VideoCaptureController::OnStarted() { DCHECK_CURRENTLY_ON(BrowserThread::IO); state_ = VIDEO_CAPTURE_STATE_STARTED; - PerformForClientsWithOpenSession(base::Bind(&CallOnStarted)); + PerformForClientsWithOpenSession(base::BindRepeating(&CallOnStarted)); } void VideoCaptureController::OnStartedUsingGpuDecode() { DCHECK_CURRENTLY_ON(BrowserThread::IO); OnLog("StartedUsingGpuDecode"); - PerformForClientsWithOpenSession(base::Bind(&CallOnStartedUsingGpuDecode)); + PerformForClientsWithOpenSession( + base::BindRepeating(&CallOnStartedUsingGpuDecode)); } void VideoCaptureController::OnDeviceLaunched( @@ -532,10 +539,11 @@ } } -void VideoCaptureController::OnDeviceLaunchFailed() { +void VideoCaptureController::OnDeviceLaunchFailed( + media::VideoCaptureError error) { DCHECK_CURRENTLY_ON(BrowserThread::IO); if (device_launch_observer_) { - device_launch_observer_->OnDeviceLaunchFailed(this); + device_launch_observer_->OnDeviceLaunchFailed(this, error); device_launch_observer_ = nullptr; } }
diff --git a/content/browser/renderer_host/media/video_capture_controller.h b/content/browser/renderer_host/media/video_capture_controller.h index 62c39fa..b16c243 100644 --- a/content/browser/renderer_host/media/video_capture_controller.h +++ b/content/browser/renderer_host/media/video_capture_controller.h
@@ -109,7 +109,7 @@ buffer_read_permission, media::mojom::VideoFrameInfoPtr frame_info) override; void OnBufferRetired(int buffer_id) override; - void OnError() override; + void OnError(media::VideoCaptureError error) override; void OnLog(const std::string& message) override; void OnStarted() override; void OnStartedUsingGpuDecode() override; @@ -117,7 +117,7 @@ // Implementation of VideoCaptureDeviceLauncher::Callbacks interface: void OnDeviceLaunched( std::unique_ptr<LaunchedVideoCaptureDevice> device) override; - void OnDeviceLaunchFailed() override; + void OnDeviceLaunchFailed(media::VideoCaptureError error) override; void OnDeviceLaunchAborted() override; void OnDeviceConnectionLost(); @@ -219,8 +219,8 @@ const std::vector<BufferContext>::iterator& buffer_state_iter); using EventHandlerAction = - base::Callback<void(VideoCaptureControllerEventHandler* client, - VideoCaptureControllerID id)>; + base::RepeatingCallback<void(VideoCaptureControllerEventHandler* client, + VideoCaptureControllerID id)>; void PerformForClientsWithOpenSession(EventHandlerAction action); void EmitLogMessage(const std::string& message, int verbose_log_level);
diff --git a/content/browser/renderer_host/media/video_capture_controller_event_handler.h b/content/browser/renderer_host/media/video_capture_controller_event_handler.h index 4cac4888..a2564af 100644 --- a/content/browser/renderer_host/media/video_capture_controller_event_handler.h +++ b/content/browser/renderer_host/media/video_capture_controller_event_handler.h
@@ -33,7 +33,8 @@ class CONTENT_EXPORT VideoCaptureControllerEventHandler { public: // An Error has occurred in the VideoCaptureDevice. - virtual void OnError(VideoCaptureControllerID id) = 0; + virtual void OnError(VideoCaptureControllerID id, + media::VideoCaptureError error) = 0; virtual void OnNewBuffer(VideoCaptureControllerID id, media::mojom::VideoBufferHandlePtr buffer_handle,
diff --git a/content/browser/renderer_host/media/video_capture_controller_unittest.cc b/content/browser/renderer_host/media/video_capture_controller_unittest.cc index a9ae1331..bfce672 100644 --- a/content/browser/renderer_host/media/video_capture_controller_unittest.cc +++ b/content/browser/renderer_host/media/video_capture_controller_unittest.cc
@@ -62,11 +62,15 @@ void(VideoCaptureControllerID, int buffer_id)); MOCK_METHOD2(DoBufferReady, void(VideoCaptureControllerID, const gfx::Size&)); MOCK_METHOD1(DoEnded, void(VideoCaptureControllerID)); - MOCK_METHOD1(DoError, void(VideoCaptureControllerID)); + MOCK_METHOD2(DoError, + void(VideoCaptureControllerID, media::VideoCaptureError)); MOCK_METHOD1(OnStarted, void(VideoCaptureControllerID)); MOCK_METHOD1(OnStartedUsingGpuDecode, void(VideoCaptureControllerID)); - void OnError(VideoCaptureControllerID id) override { DoError(id); } + void OnError(VideoCaptureControllerID id, + media::VideoCaptureError error) override { + DoError(id, error); + } void OnNewBuffer(VideoCaptureControllerID id, media::mojom::VideoBufferHandlePtr buffer_handle, int length, @@ -513,14 +517,24 @@ // Start with one client. controller_->AddClient(route_id, client_a_.get(), 100, session_100); - device_client_->OnError(FROM_HERE, "Test Error"); - EXPECT_CALL(*client_a_, DoError(route_id)).Times(1); + device_client_->OnError( + media::VideoCaptureError::kIntentionalErrorRaisedByUnitTest, FROM_HERE, + "Test Error"); + EXPECT_CALL( + *client_a_, + DoError(route_id, + media::VideoCaptureError::kIntentionalErrorRaisedByUnitTest)) + .Times(1); base::RunLoop().RunUntilIdle(); Mock::VerifyAndClearExpectations(client_a_.get()); // Second client connects after the error state. It also should get told of // the error. - EXPECT_CALL(*client_b_, DoError(route_id)).Times(1); + EXPECT_CALL( + *client_b_, + DoError(route_id, media::VideoCaptureError:: + kVideoCaptureControllerIsAlreadyInErrorState)) + .Times(1); controller_->AddClient(route_id, client_b_.get(), 200, session_200); base::RunLoop().RunUntilIdle(); Mock::VerifyAndClearExpectations(client_b_.get()); @@ -568,18 +582,28 @@ arbitrary_frame_feedback_id); ASSERT_TRUE(buffer.is_valid()); - device_client_->OnError(FROM_HERE, "Test Error"); + device_client_->OnError( + media::VideoCaptureError::kIntentionalErrorRaisedByUnitTest, FROM_HERE, + "Test Error"); device_client_->OnIncomingCapturedBuffer(std::move(buffer), device_format, arbitrary_reference_time_, arbitrary_timestamp_); - EXPECT_CALL(*client_a_, DoError(route_id)).Times(1); + EXPECT_CALL( + *client_a_, + DoError(route_id, + media::VideoCaptureError::kIntentionalErrorRaisedByUnitTest)) + .Times(1); base::RunLoop().RunUntilIdle(); Mock::VerifyAndClearExpectations(client_a_.get()); // Second client connects after the error state. It also should get told of // the error. - EXPECT_CALL(*client_b_, DoError(route_id)).Times(1); + EXPECT_CALL( + *client_b_, + DoError(route_id, media::VideoCaptureError:: + kVideoCaptureControllerIsAlreadyInErrorState)) + .Times(1); controller_->AddClient(route_id, client_b_.get(), 200, session_200); Mock::VerifyAndClearExpectations(client_b_.get()); }
diff --git a/content/browser/renderer_host/media/video_capture_device_launch_observer.h b/content/browser/renderer_host/media/video_capture_device_launch_observer.h index 33e4b1b..a0f4929 100644 --- a/content/browser/renderer_host/media/video_capture_device_launch_observer.h +++ b/content/browser/renderer_host/media/video_capture_device_launch_observer.h
@@ -6,6 +6,7 @@ #define CONTENT_BROWSER_RENDERER_HOST_MEDIA_VIDEO_CAPTURE_DEVICE_LAUNCH_OBSERVER_H_ #include "content/common/content_export.h" +#include "media/capture/video_capture_types.h" namespace content { @@ -15,7 +16,8 @@ public: virtual ~VideoCaptureDeviceLaunchObserver() {} virtual void OnDeviceLaunched(VideoCaptureController* controller) = 0; - virtual void OnDeviceLaunchFailed(VideoCaptureController* controller) = 0; + virtual void OnDeviceLaunchFailed(VideoCaptureController* controller, + media::VideoCaptureError error) = 0; virtual void OnDeviceLaunchAborted() = 0; virtual void OnDeviceConnectionLost(VideoCaptureController* controller) = 0; };
diff --git a/content/browser/renderer_host/media/video_capture_host.cc b/content/browser/renderer_host/media/video_capture_host.cc index 209d64c8..d35e6a28 100644 --- a/content/browser/renderer_host/media/video_capture_host.cc +++ b/content/browser/renderer_host/media/video_capture_host.cc
@@ -89,7 +89,8 @@ if (controller) { const VideoCaptureControllerID controller_id(it->first); media_stream_manager_->video_capture_manager()->DisconnectClient( - controller.get(), controller_id, this, false); + controller.get(), controller_id, this, + media::VideoCaptureError::kNone); ++it; } else { // Remove the entry for this controller_id so that when the controller @@ -104,13 +105,14 @@ render_process_host_delegate_.release()); } -void VideoCaptureHost::OnError(VideoCaptureControllerID controller_id) { +void VideoCaptureHost::OnError(VideoCaptureControllerID controller_id, + media::VideoCaptureError error) { DVLOG(1) << __func__; DCHECK_CURRENTLY_ON(BrowserThread::IO); BrowserThread::PostTask( BrowserThread::IO, FROM_HERE, base::BindOnce(&VideoCaptureHost::DoError, weak_factory_.GetWeakPtr(), - controller_id)); + controller_id, error)); } void VideoCaptureHost::OnNewBuffer( @@ -216,7 +218,7 @@ } device_id_to_observer_map_.erase(controller_id); - DeleteVideoCaptureController(controller_id, false); + DeleteVideoCaptureController(controller_id, media::VideoCaptureError::kNone); NotifyStreamRemoved(); } @@ -316,7 +318,8 @@ std::move(callback).Run(formats_in_use); } -void VideoCaptureHost::DoError(VideoCaptureControllerID controller_id) { +void VideoCaptureHost::DoError(VideoCaptureControllerID controller_id, + media::VideoCaptureError error) { DVLOG(1) << __func__; DCHECK_CURRENTLY_ON(BrowserThread::IO); if (controllers_.find(controller_id) == controllers_.end()) @@ -327,7 +330,7 @@ media::mojom::VideoCaptureState::FAILED); } - DeleteVideoCaptureController(controller_id, true); + DeleteVideoCaptureController(controller_id, error); NotifyStreamRemoved(); } @@ -342,7 +345,7 @@ media::mojom::VideoCaptureState::ENDED); } - DeleteVideoCaptureController(controller_id, false); + DeleteVideoCaptureController(controller_id, media::VideoCaptureError::kNone); NotifyStreamRemoved(); } @@ -355,7 +358,8 @@ if (it == controllers_.end()) { if (controller) { media_stream_manager_->video_capture_manager()->DisconnectClient( - controller.get(), controller_id, this, false); + controller.get(), controller_id, this, + media::VideoCaptureError::kNone); } return; } @@ -374,7 +378,8 @@ } void VideoCaptureHost::DeleteVideoCaptureController( - VideoCaptureControllerID controller_id, bool on_error) { + VideoCaptureControllerID controller_id, + media::VideoCaptureError error) { DCHECK_CURRENTLY_ON(BrowserThread::IO); auto it = controllers_.find(controller_id); @@ -387,7 +392,7 @@ return; media_stream_manager_->video_capture_manager()->DisconnectClient( - controller.get(), controller_id, this, on_error); + controller.get(), controller_id, this, error); } void VideoCaptureHost::NotifyStreamAdded() {
diff --git a/content/browser/renderer_host/media/video_capture_host.h b/content/browser/renderer_host/media/video_capture_host.h index d19c4ad..5fdecfe6c 100644 --- a/content/browser/renderer_host/media/video_capture_host.h +++ b/content/browser/renderer_host/media/video_capture_host.h
@@ -53,7 +53,8 @@ FRIEND_TEST_ALL_PREFIXES(VideoCaptureTest, IncrementMatchesDecrementCalls); // VideoCaptureControllerEventHandler implementation. - void OnError(VideoCaptureControllerID id) override; + void OnError(VideoCaptureControllerID id, + media::VideoCaptureError error) override; void OnNewBuffer(VideoCaptureControllerID id, media::mojom::VideoBufferHandlePtr buffer_handle, int length, @@ -90,7 +91,7 @@ int32_t session_id, GetDeviceFormatsInUseCallback callback) override; - void DoError(VideoCaptureControllerID id); + void DoError(VideoCaptureControllerID id, media::VideoCaptureError error); void DoEnded(VideoCaptureControllerID id); // Bound as callback for VideoCaptureManager::StartCaptureForClient(). @@ -102,7 +103,7 @@ // to StopCaptureForClient(). |on_error| is true if this is triggered by // VideoCaptureControllerEventHandler::OnError. void DeleteVideoCaptureController(VideoCaptureControllerID controller_id, - bool on_error); + media::VideoCaptureError error); void NotifyStreamAdded(); void NotifyStreamRemoved();
diff --git a/content/browser/renderer_host/media/video_capture_manager.cc b/content/browser/renderer_host/media/video_capture_manager.cc index e0654b6e..12e9dc7 100644 --- a/content/browser/renderer_host/media/video_capture_manager.cc +++ b/content/browser/renderer_host/media/video_capture_manager.cc
@@ -49,6 +49,12 @@ NUM_VIDEO_CAPTURE_EVENT); } +void LogVideoCaptureError(media::VideoCaptureError error) { + UMA_HISTOGRAM_ENUMERATION( + "Media.VideoCapture.Error", error, + static_cast<int>(media::VideoCaptureError::kMaxValue) + 1); +} + const media::VideoCaptureSessionId kFakeSessionId = -1; } // namespace @@ -263,7 +269,10 @@ const media::VideoCaptureDeviceInfo* device_info = GetDeviceInfoById(controller->device_id()); if (!device_info) { - OnDeviceLaunchFailed(controller); + OnDeviceLaunchFailed( + controller, + media::VideoCaptureError:: + kVideoCaptureManagerProcessDeviceStartQueueDeviceInfoNotFound); return; } for (auto& observer : capture_observers_) @@ -318,12 +327,13 @@ } void VideoCaptureManager::OnDeviceLaunchFailed( - VideoCaptureController* controller) { + VideoCaptureController* controller, + media::VideoCaptureError error) { std::ostringstream string_stream; string_stream << "Launching device has failed. device_id = " << controller->device_id(); EmitLogMessage(string_stream.str(), 1); - controller->OnError(); + controller->OnError(error); device_start_request_queue_.pop_front(); ProcessDeviceStartRequestQueue(); @@ -341,7 +351,8 @@ string_stream << "Lost connection to device. device_id = " << controller->device_id(); EmitLogMessage(string_stream.str(), 1); - controller->OnError(); + controller->OnError( + media::VideoCaptureError::kVideoCaptureManagerDeviceConnectionLost); } void VideoCaptureManager::ConnectClient( @@ -387,7 +398,7 @@ VideoCaptureController* controller, VideoCaptureControllerID client_id, VideoCaptureControllerEventHandler* client_handler, - bool aborted_due_to_error) { + media::VideoCaptureError error) { DCHECK_CURRENTLY_ON(BrowserThread::IO); DCHECK(controller); DCHECK(client_handler); @@ -396,7 +407,7 @@ NOTREACHED(); return; } - if (!aborted_due_to_error) { + if (error == media::VideoCaptureError::kNone) { if (controller->has_received_frames()) { LogVideoCaptureEvent(VIDEO_CAPTURE_STOP_CAPTURE_OK); } else if (controller->stream_type() == MEDIA_DEVICE_VIDEO_CAPTURE) { @@ -408,6 +419,11 @@ } } else { LogVideoCaptureEvent(VIDEO_CAPTURE_STOP_CAPTURE_DUE_TO_ERROR); + LogVideoCaptureError(error); + std::ostringstream string_stream; + string_stream << "Video capture session stopped with error code " + << static_cast<int>(error); + EmitLogMessage(string_stream.str(), 1); for (auto it : sessions_) { if (it.second.type == controller->stream_type() && it.second.id == controller->device_id()) {
diff --git a/content/browser/renderer_host/media/video_capture_manager.h b/content/browser/renderer_host/media/video_capture_manager.h index 93fd4c1..a32d287 100644 --- a/content/browser/renderer_host/media/video_capture_manager.h +++ b/content/browser/renderer_host/media/video_capture_manager.h
@@ -97,7 +97,7 @@ void DisconnectClient(VideoCaptureController* controller, VideoCaptureControllerID client_id, VideoCaptureControllerEventHandler* client_handler, - bool aborted_due_to_error); + media::VideoCaptureError error); // Called by VideoCaptureHost to pause to update video buffer specified by // |client_id| and |client_handler|. If all clients of |controller| are @@ -179,7 +179,8 @@ // VideoCaptureDeviceLaunchObserver implementation: void OnDeviceLaunched(VideoCaptureController* controller) override; - void OnDeviceLaunchFailed(VideoCaptureController* controller) override; + void OnDeviceLaunchFailed(VideoCaptureController* controller, + media::VideoCaptureError error) override; void OnDeviceLaunchAborted() override; void OnDeviceConnectionLost(VideoCaptureController* controller) override;
diff --git a/content/browser/renderer_host/media/video_capture_manager_unittest.cc b/content/browser/renderer_host/media/video_capture_manager_unittest.cc index 5816d1b..ce592438 100644 --- a/content/browser/renderer_host/media/video_capture_manager_unittest.cc +++ b/content/browser/renderer_host/media/video_capture_manager_unittest.cc
@@ -152,7 +152,9 @@ // Needed as an input argument to ConnectClient(). class MockFrameObserver : public VideoCaptureControllerEventHandler { public: - MOCK_METHOD1(OnError, void(VideoCaptureControllerID id)); + MOCK_METHOD2(OnError, + void(VideoCaptureControllerID id, + media::VideoCaptureError error)); MOCK_METHOD1(OnStarted, void(VideoCaptureControllerID id)); MOCK_METHOD1(OnStartedUsingGpuDecode, void(VideoCaptureControllerID id)); @@ -258,7 +260,8 @@ void StopClient(VideoCaptureControllerID client_id) { ASSERT_TRUE(1 == controllers_.count(client_id)); vcm_->DisconnectClient(controllers_[client_id], client_id, - frame_observer_.get(), false); + frame_observer_.get(), + media::VideoCaptureError::kNone); controllers_.erase(client_id); } @@ -355,8 +358,9 @@ // Wait for device opened. base::RunLoop().RunUntilIdle(); - vcm_->DisconnectClient(controllers_[client_id], client_id, - frame_observer_.get(), true); + vcm_->DisconnectClient( + controllers_[client_id], client_id, frame_observer_.get(), + media::VideoCaptureError::kIntentionalErrorRaisedByUnitTest); // Wait to check callbacks before removing the listener. base::RunLoop().RunUntilIdle(); @@ -666,7 +670,7 @@ // Try open a non-existing device. TEST_F(VideoCaptureManagerTest, OpenNotExisting) { InSequence s; - EXPECT_CALL(*frame_observer_, OnError(_)); + EXPECT_CALL(*frame_observer_, OnError(_, _)); EXPECT_CALL(*listener_, Opened(MEDIA_DEVICE_VIDEO_CAPTURE, _)); EXPECT_CALL(*listener_, Closed(MEDIA_DEVICE_VIDEO_CAPTURE, _));
diff --git a/content/browser/renderer_host/media/video_capture_unittest.cc b/content/browser/renderer_host/media/video_capture_unittest.cc index fbcef86..13c7226 100644 --- a/content/browser/renderer_host/media/video_capture_unittest.cc +++ b/content/browser/renderer_host/media/video_capture_unittest.cc
@@ -277,7 +277,8 @@ void SimulateError() { EXPECT_CALL(*this, OnStateChanged(media::mojom::VideoCaptureState::FAILED)); VideoCaptureControllerID id(kDeviceId); - host_->OnError(id); + host_->OnError(id, + media::VideoCaptureError::kIntentionalErrorRaisedByUnitTest); base::RunLoop().RunUntilIdle(); }
diff --git a/content/browser/renderer_host/render_message_filter.cc b/content/browser/renderer_host/render_message_filter.cc index fc443f0..5b35700 100644 --- a/content/browser/renderer_host/render_message_filter.cc +++ b/content/browser/renderer_host/render_message_filter.cc
@@ -92,6 +92,26 @@ void NoOpCacheStorageErrorCallback(CacheStorageCacheHandle cache_handle, CacheStorageError error) {} +base::Optional<url::Origin> GetRendererOrigin(const GURL& url, + int render_process_id) { + GURL requesting_url = + ChildProcessSecurityPolicyImpl::GetInstance()->GetOriginLock( + render_process_id); + + if (!requesting_url.is_valid() || !url.is_valid()) + return base::nullopt; + + url::Origin origin = url::Origin::Create(requesting_url); + + // Don't cache the code corresponding to unique origins. The same-origin + // checks should always fail for unique origins but the serialized value of + // unique origins does not ensure this. + if (origin.unique()) + return base::nullopt; + + return origin; +} + } // namespace RenderMessageFilter::RenderMessageFilter( @@ -237,45 +257,35 @@ cache->WriteMetadata(url, kPriority, expected_response_time, buf.get(), data.size()); } else { - GURL requesting_url = - ChildProcessSecurityPolicyImpl::GetInstance()->GetOriginLock( - render_process_id_); - // If the origin_url isn't valid then render process might not be locked to - // an origin yet so we don't allow any writes to the disk. - if (!requesting_url.is_valid() || !url.is_valid()) + if (!generated_code_cache_context_->generated_code_cache()) return; - url::Origin requesting_origin = url::Origin::Create(requesting_url); - // Don't cache the code corresponding to unique origins. The same-origin - // checks should always fail for unique origins but the serialized value of - // unique origins does not ensure this. - if (requesting_origin.unique()) + base::Optional<url::Origin> requesting_origin = + GetRendererOrigin(url, render_process_id_); + if (!requesting_origin) return; generated_code_cache_context_->generated_code_cache()->WriteData( - url, requesting_origin, expected_response_time, data); + url, *requesting_origin, expected_response_time, data); } } void RenderMessageFilter::FetchCachedCode(const GURL& url, FetchCachedCodeCallback callback) { - GURL requesting_url = - ChildProcessSecurityPolicyImpl::GetInstance()->GetOriginLock( - render_process_id_); - // If the url isn't valid then render process may not be locked to an origin - // yet so we don't allow fetches from code cache. - if (!requesting_url.is_valid() || !url.is_valid()) { - std::move(callback).Run(base::Time(), std::vector<uint8_t>()); + if (!generated_code_cache_context_->generated_code_cache()) return; - } - url::Origin requesting_origin = url::Origin::Create(requesting_url); + base::Optional<url::Origin> requesting_origin = + GetRendererOrigin(url, render_process_id_); + if (!requesting_origin) + return; + base::RepeatingCallback<void(const base::Time&, const std::vector<uint8_t>&)> read_callback = base::BindRepeating( &RenderMessageFilter::OnReceiveCachedCode, weak_ptr_factory_.GetWeakPtr(), base::Passed(&callback)); generated_code_cache_context_->generated_code_cache()->FetchEntry( - url, requesting_origin, read_callback); + url, *requesting_origin, read_callback); } void RenderMessageFilter::OnReceiveCachedCode( @@ -287,6 +297,19 @@ std::move(callback).Run(response_time, data); } +void RenderMessageFilter::ClearCodeCacheEntry(const GURL& url) { + if (!generated_code_cache_context_->generated_code_cache()) + return; + + base::Optional<url::Origin> requesting_origin = + GetRendererOrigin(url, render_process_id_); + if (!requesting_origin) + return; + + generated_code_cache_context_->generated_code_cache()->DeleteEntry( + url, *requesting_origin); +} + void RenderMessageFilter::DidGenerateCacheableMetadataInCacheStorage( const GURL& url, base::Time expected_response_time,
diff --git a/content/browser/renderer_host/render_message_filter.h b/content/browser/renderer_host/render_message_filter.h index bcbd85b..ec2febc5 100644 --- a/content/browser/renderer_host/render_message_filter.h +++ b/content/browser/renderer_host/render_message_filter.h
@@ -106,6 +106,7 @@ base::Time expected_response_time, const std::vector<uint8_t>& data) override; void FetchCachedCode(const GURL& url, FetchCachedCodeCallback) override; + void ClearCodeCacheEntry(const GURL& url) override; void DidGenerateCacheableMetadataInCacheStorage( const GURL& url, base::Time expected_response_time,
diff --git a/content/browser/renderer_host/render_widget_host_view_child_frame_unittest.cc b/content/browser/renderer_host/render_widget_host_view_child_frame_unittest.cc index 3ad3321..4eff713 100644 --- a/content/browser/renderer_host/render_widget_host_view_child_frame_unittest.cc +++ b/content/browser/renderer_host/render_widget_host_view_child_frame_unittest.cc
@@ -282,7 +282,7 @@ constexpr gfx::Size compositor_viewport_pixel_size(100, 100); constexpr gfx::Rect screen_space_rect(compositor_viewport_pixel_size); viz::ParentLocalSurfaceIdAllocator allocator; - viz::LocalSurfaceId local_surface_id = allocator.GenerateId(); + viz::LocalSurfaceId local_surface_id = allocator.GetCurrentLocalSurfaceId(); constexpr viz::FrameSinkId frame_sink_id(1, 1); const viz::SurfaceId surface_id(frame_sink_id, local_surface_id);
diff --git a/content/browser/web_package/signed_exchange_envelope_unittest.cc b/content/browser/web_package/signed_exchange_envelope_unittest.cc index 021d7fe..3b7dbe2 100644 --- a/content/browser/web_package/signed_exchange_envelope_unittest.cc +++ b/content/browser/web_package/signed_exchange_envelope_unittest.cc
@@ -92,7 +92,7 @@ EXPECT_EQ(envelope->response_code(), static_cast<net::HttpStatusCode>(200u)); EXPECT_EQ(envelope->response_headers().size(), 3u); EXPECT_EQ(envelope->response_headers().find("content-encoding")->second, - "mi-sha256-draft2"); + "mi-sha256-03"); } TEST(SignedExchangeEnvelopeTest, ValidHeader) {
diff --git a/content/browser/web_package/signed_exchange_handler.cc b/content/browser/web_package/signed_exchange_handler.cc index 4bcc645b..4ea01c23 100644 --- a/content/browser/web_package/signed_exchange_handler.cc +++ b/content/browser/web_package/signed_exchange_handler.cc
@@ -47,7 +47,7 @@ namespace { -constexpr char kMiHeader[] = "MI-Draft2"; +constexpr char kDigestHeader[] = "Digest"; net::CertVerifier* g_cert_verifier_for_testing = nullptr; @@ -520,16 +520,16 @@ response_head.load_timing.send_end = now; response_head.load_timing.receive_headers_end = now; - std::string mi_header_value; - if (!response_head.headers->EnumerateHeader(nullptr, kMiHeader, - &mi_header_value)) { + std::string digest_header_value; + if (!response_head.headers->EnumerateHeader(nullptr, kDigestHeader, + &digest_header_value)) { signed_exchange_utils::ReportErrorAndTraceEvent( - devtools_proxy_.get(), "Signed exchange has no MI-Draft2: header"); + devtools_proxy_.get(), "Signed exchange has no Digest: header"); RunErrorCallback(net::ERR_INVALID_SIGNED_EXCHANGE); return; } auto mi_stream = std::make_unique<MerkleIntegritySourceStream>( - mi_header_value, std::move(source_)); + digest_header_value, std::move(source_)); net::SSLInfo ssl_info; ssl_info.cert = cert_verify_result_.verified_cert;
diff --git a/content/browser/web_package/signed_exchange_signature_verifier.cc b/content/browser/web_package/signed_exchange_signature_verifier.cc index e29e5c8c..3a7cdf72 100644 --- a/content/browser/web_package/signed_exchange_signature_verifier.cc +++ b/content/browser/web_package/signed_exchange_signature_verifier.cc
@@ -347,10 +347,11 @@ } if (!base::EqualsCaseInsensitiveASCII(envelope.signature().integrity, - "mi-draft2")) { + "digest/mi-sha256-03")) { signed_exchange_utils::ReportErrorAndTraceEvent( devtools_proxy, - "The current implemention only supports \"mi\" integrity scheme."); + "The current implemention only supports \"digest/mi-sha256-03\" " + "integrity scheme."); return Result::kErrInvalidSignatureIntegrity; } return Result::kSuccess;
diff --git a/content/browser/web_package/signed_exchange_signature_verifier_unittest.cc b/content/browser/web_package/signed_exchange_signature_verifier_unittest.cc index 9dbab4e6..5c8722d 100644 --- a/content/browser/web_package/signed_exchange_signature_verifier_unittest.cc +++ b/content/browser/web_package/signed_exchange_signature_verifier_unittest.cc
@@ -20,7 +20,7 @@ envelope.set_request_url(GURL("https://example.com/index.html")); envelope.set_response_code(net::HTTP_OK); envelope.AddResponseHeader("content-type", "text/html; charset=utf-8"); - envelope.AddResponseHeader("content-encoding", "mi-sha256-draft2"); + envelope.AddResponseHeader("content-encoding", "mi-sha256-03"); base::Optional<std::vector<uint8_t>> encoded = SignedExchangeSignatureVerifier::EncodeCanonicalExchangeHeaders(envelope); @@ -51,9 +51,9 @@ 0x50, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x2d, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, // bytes "content-encoding" - 0x50, 0x6d, 0x69, 0x2d, 0x73, 0x68, 0x61, 0x32, 0x35, 0x36, 0x2d, - 0x64, 0x72, 0x61, 0x66, 0x74, 0x32 - // bytes "mi-sha256-draft2" + 0x4c, 0x6d, 0x69, 0x2d, 0x73, 0x68, 0x61, 0x32, 0x35, 0x36, 0x2d, + 0x30, 0x33 + // bytes "mi-sha256-03" // clang-format on }; EXPECT_THAT(*encoded, @@ -65,9 +65,9 @@ // See content/testdata/sxg/README on how to generate these data. // clang-format off -constexpr char kSignatureHeaderRSA[] = R"(label; sig=*yYFb09i7VXuqsGBxc3RuJzGL4XMD9bZ20kXWSv1JObEf7KIG0MznSE1nu1fE+7DrgWQxH7FQfSWjyseOAvxsBOfkptmCCi/Ffklz3N1UU8LfwfaLWj80oBqDeofiIYwevSSpsaRKBYie7KjiVOjslFLOGe82MmHyF2utFRKY/i6UAHgMrg2FGfbwBaJsxEgtpPcN8/QnFKgt1la+JjwvYbMHpJhHTedDqx9GCxJOzbJjKRL1E2tIBvhDfK2m3eJv/nqvgWkK3MOd/Xp4FkndciS3eNyZZjwvJ6IL/3x4e0AZ36KvglpS092ZftiE4lKQWnHmVeDRmEHW6qOyv1Q3+w==*; validity-url="https://example.com/resource.validity.msg"; integrity="mi-draft2"; cert-url="https://example.com/cert.msg"; cert-sha256=*tJGJP8ej7KCEW8VnVK3bKwpBza/oLrtWA75z5ZPptuc=*; date=1517892341; expires=1517895941)"; -constexpr char kSignatureHeaderECDSAP256[] = R"(label; sig=*MEQCIA0w6auOuWGT6//MO/h43/xkXBchJUOp53GU5dmA8U+/AiAe0FggCblVxzosT2Ow9rrC2Q8zO0DZPLSNbcu29xYP6g==*; validity-url="https://example.com/resource.validity.msg"; integrity="mi-draft2"; cert-url="https://example.com/cert.msg"; cert-sha256=*KX+BYLSMgDOON8Ju65RoId39Qvajxa12HO+WnD4HpS0=*; date=1517892341; expires=1517895941)"; -constexpr char kSignatureHeaderECDSAP384[] = R"(label; sig=*MGYCMQC/P8m0ZnPrIMlI3I412MixcK9cQSirIECUNR7pOIlTiLaH95L72KXqq2aL+lxxKIICMQDU3s/BhoWtR61eKG9SqgGHd0ZtUJVY24xaJ2yHiYWxZU/QhOr5ZArSj3x1khivpRg=*; validity-url="https://example.com/resource.validity.msg"; integrity="mi-draft2"; cert-url="https://example.com/cert.msg"; cert-sha256=*8X8y8nj8vDJHSSa0cxn+TCu+8zGpIJfbdzAnd5cW+jA=*; date=1517892341; expires=1517895941)"; +constexpr char kSignatureHeaderRSA[] = R"(label; sig=*HrNLDfn6oHUmfx3YvP7dTseyZdmnQQB7jR8yea0FezZmy7IwJVtcZ/tGpXJ6fe8druTsGeFArdCeeLBapmPLq8BP6k6Uk2ClKUWNbM3is/HHaWWsfpLBF2fETKEBXvvUI9G8nJqDLJ9RS3AAZMEG+OrCybR1kEFDhc+Cp34isj8aUn7OG1ugq8ADt1DkP8xwSLn4MA2E6tHdG1dNNs+GpWE5pUbqe49DdQaQp/DcvOpixeDi3iID2VHDeASfyCVQvxNfEPRLKQ5fOELlGerTVY5XTXeegUfUuzTRHDsOBTPQ4iihCK2+/8vRwx92sExXnMH163ZL/YIM55FoU2KuRQ==*; validity-url="https://example.com/resource.validity.msg"; integrity="digest/mi-sha256-03"; cert-url="https://example.com/cert.msg"; cert-sha256=*tJGJP8ej7KCEW8VnVK3bKwpBza/oLrtWA75z5ZPptuc=*; date=1517892341; expires=1517895941)"; +constexpr char kSignatureHeaderECDSAP256[] = R"(label; sig=*MEYCIQD0rF/pJqqYa9WEE6eZcGzrVKv8yx+78tLAATxfLlyoWgIhAPJoiWcYAC+vDrZ1m5qE++y1TLdYUenwV84vpAaV3wTG*; validity-url="https://example.com/resource.validity.msg"; integrity="digest/mi-sha256-03"; cert-url="https://example.com/cert.msg"; cert-sha256=*KX+BYLSMgDOON8Ju65RoId39Qvajxa12HO+WnD4HpS0=*; date=1517892341; expires=1517895941)"; +constexpr char kSignatureHeaderECDSAP384[] = R"(label; sig=*MGUCMDkTn0MhRiG0OfbAbnyXRgM8XSV8vjm5w0olX5qoL94LEiJ7zS4ZmdxvSNHp5luK5QIxAPlQRvcIBq8vvKgkzQCjsbZ/jEAKh1Gx2JKSyj4HRfLWRar4KbGbMm+GbyU7N/SZYQ==*; validity-url="https://example.com/resource.validity.msg"; integrity="digest/mi-sha256-03"; cert-url="https://example.com/cert.msg"; cert-sha256=*8X8y8nj8vDJHSSa0cxn+TCu+8zGpIJfbdzAnd5cW+jA=*; date=1517892341; expires=1517895941)"; // clang-format on // |expires| (1518497142) is more than 7 days (604800 seconds) after |date| @@ -255,10 +255,9 @@ envelope.set_request_url(GURL("https://test.example.org/test/")); envelope.set_response_code(net::HTTP_OK); envelope.AddResponseHeader("content-type", "text/html; charset=utf-8"); - envelope.AddResponseHeader("content-encoding", "mi-sha256-draft2"); + envelope.AddResponseHeader("content-encoding", "mi-sha256-03"); envelope.AddResponseHeader( - "mi-draft2", - "mi-sha256-draft2=wmp4dRMYgxP3tSMCwV_I0CWOCiHZpAihKZk19bsN9RI"); + "digest", "mi-sha256-03=wmp4dRMYgxP3tSMCwV/I0CWOCiHZpAihKZk19bsN9RI="); envelope.SetSignatureForTesting((*signature)[0]); EXPECT_EQ(SignedExchangeSignatureVerifier::Result::kErrUnsupportedCertType, @@ -284,10 +283,9 @@ envelope.set_request_url(GURL("https://test.example.org/test/")); envelope.set_response_code(net::HTTP_OK); envelope.AddResponseHeader("content-type", "text/html; charset=utf-8"); - envelope.AddResponseHeader("content-encoding", "mi-sha256-draft2"); + envelope.AddResponseHeader("content-encoding", "mi-sha256-03"); envelope.AddResponseHeader( - "mi-draft2", - "mi-sha256-draft2=wmp4dRMYgxP3tSMCwV_I0CWOCiHZpAihKZk19bsN9RI"); + "digest", "mi-sha256-03=wmp4dRMYgxP3tSMCwV/I0CWOCiHZpAihKZk19bsN9RI="); envelope.SetSignatureForTesting((*signature)[0]); @@ -311,10 +309,9 @@ envelope.set_request_url(GURL("https://test.example.org/test/")); envelope.set_response_code(net::HTTP_OK); envelope.AddResponseHeader("content-type", "text/html; charset=utf-8"); - envelope.AddResponseHeader("content-encoding", "mi-sha256-draft2"); + envelope.AddResponseHeader("content-encoding", "mi-sha256-03"); envelope.AddResponseHeader( - "mi-draft2", - "mi-sha256-draft2=wmp4dRMYgxP3tSMCwV_I0CWOCiHZpAihKZk19bsN9RIG"); + "digest", "mi-sha256-03=wmp4dRMYgxP3tSMCwV/I0CWOCiHZpAihKZk19bsN9RIG="); envelope.SetSignatureForTesting((*signature)[0]);
diff --git a/content/child/runtime_features.cc b/content/child/runtime_features.cc index f0de3c0..9fbd8bb 100644 --- a/content/child/runtime_features.cc +++ b/content/child/runtime_features.cc
@@ -15,6 +15,7 @@ #include "content/common/content_switches_internal.h" #include "content/public/common/content_features.h" #include "content/public/common/content_switches.h" +#include "gpu/config/gpu_switches.h" #include "media/base/media_switches.h" #include "services/device/public/cpp/device_features.h" #include "services/network/public/cpp/features.h" @@ -24,6 +25,10 @@ #include "ui/gl/gl_switches.h" #include "ui/native_theme/native_theme_features.h" +#if defined(OS_WIN) +#include "base/win/windows_version.h" +#endif + using blink::WebRuntimeFeatures; namespace content { @@ -68,11 +73,15 @@ WebRuntimeFeatures::EnableNetInfoDownlinkMax(false); #endif -// Web Bluetooth is shipped on Android, ChromeOS & MacOS, experimental -// otherwise. +// Web Bluetooth is shipped on Android, ChromeOS, MacOS and Windows 10, +// experimental otherwise. #if defined(OS_CHROMEOS) || defined(OS_ANDROID) || defined(OS_MACOSX) WebRuntimeFeatures::EnableWebBluetooth(true); #endif +#if defined(OS_WIN) + if (base::win::GetVersion() >= base::win::VERSION_WIN10) + WebRuntimeFeatures::EnableWebBluetooth(true); +#endif #if defined(OS_CHROMEOS) WebRuntimeFeatures::EnableForceTallerSelectPopup(true);
diff --git a/content/common/render_message_filter.mojom b/content/common/render_message_filter.mojom index 20872ed..e78a32d 100644 --- a/content/common/render_message_filter.mojom +++ b/content/common/render_message_filter.mojom
@@ -37,6 +37,8 @@ FetchCachedCode(url.mojom.Url url) => (mojo_base.mojom.Time response_time, array<uint8> data); + ClearCodeCacheEntry(url.mojom.Url url); + // Requests that the browser cache |data| for the specified CacheStorage entry. DidGenerateCacheableMetadataInCacheStorage( url.mojom.Url url, mojo_base.mojom.Time expected_response_time,
diff --git a/content/public/android/java/res/OWNERS b/content/public/android/java/res/OWNERS index a1d76438..79dd0b0 100644 --- a/content/public/android/java/res/OWNERS +++ b/content/public/android/java/res/OWNERS
@@ -3,11 +3,7 @@ # we don't want them. set noparent -bauerb@chromium.org -dtrainor@chromium.org -tedchoc@chromium.org -twellington@chromium.org -yusufo@chromium.org +file://ui/android/java/res/OWNERS # COMPONENT: Content>Core # OS: Android
diff --git a/content/public/browser/video_capture_device_launcher.h b/content/public/browser/video_capture_device_launcher.h index d2a3f83..033c1c13 100644 --- a/content/public/browser/video_capture_device_launcher.h +++ b/content/public/browser/video_capture_device_launcher.h
@@ -29,7 +29,7 @@ virtual ~Callbacks() {} virtual void OnDeviceLaunched( std::unique_ptr<LaunchedVideoCaptureDevice> device) = 0; - virtual void OnDeviceLaunchFailed() = 0; + virtual void OnDeviceLaunchFailed(media::VideoCaptureError error) = 0; virtual void OnDeviceLaunchAborted() = 0; };
diff --git a/content/public/common/content_switches.cc b/content/public/common/content_switches.cc index 70e4e9cd..f7e5123 100644 --- a/content/public/common/content_switches.cc +++ b/content/public/common/content_switches.cc
@@ -429,9 +429,6 @@ // The filename to write the output of the test tracing to. const char kEnableTracingOutput[] = "enable-tracing-output"; -// Enables unsafe WebGPU support. -const char kEnableUnsafeWebGPU[] = "enable-unsafe-webgpu"; - // Enable screen capturing support for MediaStream API. const char kEnableUserMediaScreenCapturing[] = "enable-usermedia-screen-capturing";
diff --git a/content/public/common/content_switches.h b/content/public/common/content_switches.h index b9f3633..4da6151b 100644 --- a/content/public/common/content_switches.h +++ b/content/public/common/content_switches.h
@@ -135,7 +135,6 @@ CONTENT_EXPORT extern const char kEnableThreadedCompositing[]; CONTENT_EXPORT extern const char kEnableTracing[]; CONTENT_EXPORT extern const char kEnableTracingOutput[]; -CONTENT_EXPORT extern const char kEnableUnsafeWebGPU[]; CONTENT_EXPORT extern const char kEnableUserMediaScreenCapturing[]; CONTENT_EXPORT extern const char kEnableUseZoomForDSF[]; CONTENT_EXPORT extern const char kEnableViewport[];
diff --git a/content/public/test/mock_render_thread.cc b/content/public/test/mock_render_thread.cc index 2df105a..25d11842 100644 --- a/content/public/test/mock_render_thread.cc +++ b/content/public/test/mock_render_thread.cc
@@ -77,6 +77,8 @@ NOTREACHED(); } + void ClearCodeCacheEntry(const GURL& url) override { NOTREACHED(); } + void DidGenerateCacheableMetadataInCacheStorage( const GURL& url, base::Time expected_response_time,
diff --git a/content/renderer/loader/resource_dispatcher.cc b/content/renderer/loader/resource_dispatcher.cc index 4dc484ec..88dd2318 100644 --- a/content/renderer/loader/resource_dispatcher.cc +++ b/content/renderer/loader/resource_dispatcher.cc
@@ -752,11 +752,11 @@ uint32_t options = network::mojom::kURLLoadOptionNone; // TODO(jam): use this flag for ResourceDispatcherHost code path once // MojoLoading is the only IPC code path. - if (blink::ServiceWorkerUtils::IsServicificationEnabled() && - request->fetch_request_context_type != REQUEST_CONTEXT_TYPE_FETCH) { + if (request->fetch_request_context_type != REQUEST_CONTEXT_TYPE_FETCH) { // MIME sniffing should be disabled for a request initiated by fetch(). options |= network::mojom::kURLLoadOptionSniffMimeType; - throttles.push_back(std::make_unique<MimeSniffingThrottle>()); + if (blink::ServiceWorkerUtils::IsServicificationEnabled()) + throttles.push_back(std::make_unique<MimeSniffingThrottle>()); } if (is_sync) { options |= network::mojom::kURLLoadOptionSynchronous;
diff --git a/content/renderer/media/stream/webmediaplayer_ms.cc b/content/renderer/media/stream/webmediaplayer_ms.cc index d071c391..4fb501d7 100644 --- a/content/renderer/media/stream/webmediaplayer_ms.cc +++ b/content/renderer/media/stream/webmediaplayer_ms.cc
@@ -991,11 +991,49 @@ return false; context_3d = media::Context3D(provider->ContextGL(), provider->GrContext()); DCHECK(context_3d.gl); + return video_renderer_.CopyVideoFrameTexturesToGLTexture( context_3d, gl, video_frame.get(), target, texture, internal_format, format, type, level, premultiply_alpha, flip_y); } +bool WebMediaPlayerMS::CopyVideoYUVDataToPlatformTexture( + gpu::gles2::GLES2Interface* gl, + unsigned target, + unsigned int texture, + unsigned internal_format, + unsigned format, + unsigned type, + int level, + bool premultiply_alpha, + bool flip_y, + int already_uploaded_id, + VideoFrameUploadMetadata* out_metadata) { + TRACE_EVENT0("media", "copyVideoYUVDataToPlatformTexture"); + DCHECK(thread_checker_.CalledOnValidThread()); + + scoped_refptr<media::VideoFrame> video_frame = + compositor_->GetCurrentFrameWithoutUpdatingStatistics(); + + if (!video_frame) + return false; + if (video_frame->HasTextures()) + return false; + + media::Context3D context_3d; + auto* provider = + RenderThreadImpl::current()->SharedMainThreadContextProvider().get(); + // GPU Process crashed. + if (!provider) + return false; + context_3d = media::Context3D(provider->ContextGL(), provider->GrContext()); + DCHECK(context_3d.gl); + + return video_renderer_.CopyVideoFrameYUVDataToGLTexture( + context_3d, gl, video_frame.get(), target, texture, internal_format, + format, type, level, premultiply_alpha, flip_y); +} + bool WebMediaPlayerMS::TexImageImpl(TexImageFunctionID functionID, unsigned target, gpu::gles2::GLES2Interface* gl,
diff --git a/content/renderer/media/stream/webmediaplayer_ms.h b/content/renderer/media/stream/webmediaplayer_ms.h index 1857e62..8408a5d4 100644 --- a/content/renderer/media/stream/webmediaplayer_ms.h +++ b/content/renderer/media/stream/webmediaplayer_ms.h
@@ -198,6 +198,19 @@ int already_uploaded_id, VideoFrameUploadMetadata* out_metadata) override; + bool CopyVideoYUVDataToPlatformTexture( + gpu::gles2::GLES2Interface* gl, + unsigned target, + unsigned int texture, + unsigned internal_format, + unsigned format, + unsigned type, + int level, + bool premultiply_alpha, + bool flip_y, + int already_uploaded_id, + VideoFrameUploadMetadata* out_metadata) override; + bool TexImageImpl(TexImageFunctionID functionID, unsigned target, gpu::gles2::GLES2Interface* gl,
diff --git a/content/renderer/pepper/pepper_broker_unittest.cc b/content/renderer/pepper/pepper_broker_unittest.cc index 4012be98..af2f082 100644 --- a/content/renderer/pepper/pepper_broker_unittest.cc +++ b/content/renderer/pepper/pepper_broker_unittest.cc
@@ -3,13 +3,13 @@ // found in the LICENSE file. #include "content/renderer/pepper/pepper_broker.h" -#include "base/message_loop/message_loop.h" #if defined(OS_POSIX) #include <fcntl.h> #include <sys/socket.h> #endif // defined(OS_POSIX) +#include "base/test/scoped_task_environment.h" #include "build/build_config.h" #include "content/test/mock_render_process.h" #include "testing/gtest/include/gtest/gtest.h" @@ -18,7 +18,10 @@ class PepperBrokerTest : public ::testing::Test { protected: - base::MessageLoopForIO message_loop_; + PepperBrokerTest() + : task_environment_( + base::test::ScopedTaskEnvironment::MainThreadType::IO) {} + base::test::ScopedTaskEnvironment task_environment_; // We need a render process for ppapi::proxy::ProxyChannel to work. MockRenderProcess mock_process_; };
diff --git a/content/renderer/render_widget_browsertest.cc b/content/renderer/render_widget_browsertest.cc index f1732625..56fcf0c 100644 --- a/content/renderer/render_widget_browsertest.cc +++ b/content/renderer/render_widget_browsertest.cc
@@ -70,7 +70,8 @@ render_thread_->sink().ClearMessages(); viz::ParentLocalSurfaceIdAllocator local_surface_id_allocator; gfx::Size size(100, 100); - visual_properties.local_surface_id = local_surface_id_allocator.GenerateId(); + visual_properties.local_surface_id = + local_surface_id_allocator.GetCurrentLocalSurfaceId(); visual_properties.new_size = size; visual_properties.compositor_viewport_pixel_size = size; OnSynchronizeVisualProperties(visual_properties); @@ -98,23 +99,18 @@ } class RenderWidgetInitialSizeTest : public RenderWidgetTest { - public: - RenderWidgetInitialSizeTest() : RenderWidgetTest(), initial_size_(200, 100) { - local_surface_id_ = local_surface_id_allocator_.GenerateId(); - } - protected: std::unique_ptr<VisualProperties> InitialVisualProperties() override { std::unique_ptr<VisualProperties> initial_visual_properties( new VisualProperties()); initial_visual_properties->new_size = initial_size_; initial_visual_properties->compositor_viewport_pixel_size = initial_size_; - initial_visual_properties->local_surface_id = local_surface_id_; + initial_visual_properties->local_surface_id = + local_surface_id_allocator_.GetCurrentLocalSurfaceId(); return initial_visual_properties; } - gfx::Size initial_size_; - viz::LocalSurfaceId local_surface_id_; + gfx::Size initial_size_ = gfx::Size(200, 100); viz::ParentLocalSurfaceIdAllocator local_surface_id_allocator_; };
diff --git a/content/renderer/renderer_blink_platform_impl.cc b/content/renderer/renderer_blink_platform_impl.cc index b49f1f9..3832c6d0 100644 --- a/content/renderer/renderer_blink_platform_impl.cc +++ b/content/renderer/renderer_blink_platform_impl.cc
@@ -467,6 +467,11 @@ url, std::move(callback)); } +void RendererBlinkPlatformImpl::ClearCodeCacheEntry(const GURL& url) { + RenderThreadImpl::current()->render_message_filter()->ClearCodeCacheEntry( + url); +} + void RendererBlinkPlatformImpl::CacheMetadataInCacheStorage( const blink::WebURL& url, base::Time response_time,
diff --git a/content/renderer/renderer_blink_platform_impl.h b/content/renderer/renderer_blink_platform_impl.h index 22f38d2b..afdd949 100644 --- a/content/renderer/renderer_blink_platform_impl.h +++ b/content/renderer/renderer_blink_platform_impl.h
@@ -91,6 +91,7 @@ const blink::WebURL&, base::OnceCallback<void(base::Time, const std::vector<uint8_t>&)>) override; + void ClearCodeCacheEntry(const GURL&) override; void CacheMetadataInCacheStorage( const blink::WebURL&, base::Time,
diff --git a/content/test/data/sxg/test.example.com_invalid_test.sxg b/content/test/data/sxg/test.example.com_invalid_test.sxg index 8b0c965..8806861 100644 --- a/content/test/data/sxg/test.example.com_invalid_test.sxg +++ b/content/test/data/sxg/test.example.com_invalid_test.sxg Binary files differ
diff --git a/content/test/data/sxg/test.example.org_hello.txt.sxg b/content/test/data/sxg/test.example.org_hello.txt.sxg index f70e336..611ea70 100644 --- a/content/test/data/sxg/test.example.org_hello.txt.sxg +++ b/content/test/data/sxg/test.example.org_hello.txt.sxg Binary files differ
diff --git a/content/test/data/sxg/test.example.org_noext_test.sxg b/content/test/data/sxg/test.example.org_noext_test.sxg index e5494de6..6ad78193 100644 --- a/content/test/data/sxg/test.example.org_noext_test.sxg +++ b/content/test/data/sxg/test.example.org_noext_test.sxg Binary files differ
diff --git a/content/test/data/sxg/test.example.org_test.sxg b/content/test/data/sxg/test.example.org_test.sxg index f40e6c19..4d60e61 100644 --- a/content/test/data/sxg/test.example.org_test.sxg +++ b/content/test/data/sxg/test.example.org_test.sxg Binary files differ
diff --git a/content/test/gpu/gpu_tests/pixel_expectations.py b/content/test/gpu/gpu_tests/pixel_expectations.py index 465c2a4..5fdf725 100644 --- a/content/test/gpu/gpu_tests/pixel_expectations.py +++ b/content/test/gpu/gpu_tests/pixel_expectations.py
@@ -62,8 +62,15 @@ # TODO(kbr): flakily timing out on this configuration. self.Flaky('*', ['linux', 'intel', 'debug'], bug=648369) - self.Flaky('Pixel_Video_MP4', ['android', 'nvidia'], bug=716564) - self.Flaky('Pixel_Video_MP4', ['linux', 'nvidia'], bug=819635) + # TODO(sunnyps): re-enable after rebaselining + # self.Flaky('Pixel_Video_MP4', ['android', 'nvidia'], bug=716564) + # self.Flaky('Pixel_Video_MP4', ['linux', 'nvidia'], bug=819635) + + # TODO(sunnyps): temporarily disabling for rebaselining. + self.Fail('Pixel_Video_MP4', bug=869677) + self.Fail('Pixel_Video_VP9', bug=869677) + self.Fail('Pixel_DirectComposition_Video_MP4', bug=869677) + self.Fail('Pixel_DirectComposition_Video_VP9', bug=869677) # TODO(junov): rebaselining self.Fail('Pixel_OffscreenCanvasUnaccelerated2DGPUCompositing', @@ -86,10 +93,11 @@ ['android', ('qualcomm', 'Adreno (TM) 330')], bug=773293) # Failing on Mac Intel HighSierra - self.Fail('Pixel_Video_MP4', - ['highsierra', ('intel', 0xa2e)], bug=774809) - self.Fail('Pixel_Video_VP9', - ['highsierra', ('intel', 0xa2e)], bug=774809) + # TODO(sunnyps): re-enable after rebaselining. + # self.Fail('Pixel_Video_MP4', + # ['highsierra', ('intel', 0xa2e)], bug=774809) + # self.Fail('Pixel_Video_VP9', + # ['highsierra', ('intel', 0xa2e)], bug=774809) self.Fail('Pixel_WebGLGreenTriangle_NonChromiumImage_NoAA_NoAlpha', ['highsierra', ('intel', 0xa2e)], bug=774809) self.Flaky('Pixel_OffscreenCanvasTransferBeforeStyleResize', @@ -118,7 +126,8 @@ self.Fail('Pixel_WebGLSadCanvas', ['android'], bug=575305) # Flaky on Android: crbug.com/860548 - self.Flaky('Pixel_Video_VP9', ['android'], bug=860548) + # TODO(sunnyps): re-enable after rebaselining. + # self.Flaky('Pixel_Video_VP9', ['android'], bug=860548) self.Fail('Pixel_CanvasLowLatencyWebGL', ['android', 'nvidia'], bug=868596) self.Fail('Pixel_OffscreenCanvasWebGLPaintAfterResize',
diff --git a/content/test/gpu/gpu_tests/pixel_test_pages.py b/content/test/gpu/gpu_tests/pixel_test_pages.py index 0f523fa7..d119db6 100644 --- a/content/test/gpu/gpu_tests/pixel_test_pages.py +++ b/content/test/gpu/gpu_tests/pixel_test_pages.py
@@ -192,13 +192,13 @@ 'pixel_video_mp4.html', base_name + '_Video_MP4', test_rect=[0, 0, 300, 300], - revision=9), + revision=10), PixelTestPage( 'pixel_video_vp9.html', base_name + '_Video_VP9', test_rect=[0, 0, 300, 300], - revision=9), + revision=10), PixelTestPage( 'pixel_webgl_premultiplied_alpha_false.html', @@ -754,14 +754,14 @@ 'pixel_video_mp4.html', base_name + '_DirectComposition_Video_MP4', test_rect=[0, 0, 300, 300], - revision=7, + revision=8, browser_args=browser_args), PixelTestPage( 'pixel_video_vp9.html', base_name + '_DirectComposition_Video_VP9', test_rect=[0, 0, 300, 300], - revision=9, + revision=10, browser_args=browser_args), PixelTestPage(
diff --git a/device/vr/orientation/orientation_device.cc b/device/vr/orientation/orientation_device.cc index e8b2067..0d7fb6947 100644 --- a/device/vr/orientation/orientation_device.cc +++ b/device/vr/orientation/orientation_device.cc
@@ -142,8 +142,8 @@ mojom::XRRuntimeSessionOptionsPtr options, mojom::XRRuntime::RequestSessionCallback callback) { DCHECK(!options->immersive); - // TODO(offenwanger): Perform a check to see if sensors are available when - // RequestSession is called for non-immersive sessions. + // TODO(http://crbug.com/695937): Perform a check to see if sensors are + // available when RequestSession is called for non-immersive sessions. ReturnNonImmersiveSession(std::move(callback)); }
diff --git a/device/vr/vr_device_base.cc b/device/vr/vr_device_base.cc index 14cce08..8c7d18fc 100644 --- a/device/vr/vr_device_base.cc +++ b/device/vr/vr_device_base.cc
@@ -121,8 +121,8 @@ auto session = mojom::XRSession::New(); session->data_provider = data_provider.PassInterface(); - // TODO(offenwanger) Not all session will want the enviroment provider. This - // should be refactored so it's only passed when it's requested. + // TODO(http://crbug.com/876135) Not all sessions want the environment + // provider. This should be refactored to only be passed when requested. session->enviroment_provider = enviroment_provider.PassInterface(); if (display_info_) { session->display_info = display_info_.Clone();
diff --git a/device/vr/vr_display_impl.h b/device/vr/vr_display_impl.h index 980798e..555fde53 100644 --- a/device/vr/vr_display_impl.h +++ b/device/vr/vr_display_impl.h
@@ -23,7 +23,7 @@ // VR device process implementation of a XRFrameDataProvider within a WebVR // or WebXR site session. // VRDisplayImpl objects are owned by their respective XRRuntime instances. -// TODO(offenwanger): Rename this. +// TODO(http://crbug.com/842025): Rename this. class DEVICE_VR_EXPORT VRDisplayImpl : public mojom::XRFrameDataProvider, public mojom::XREnviromentIntegrationProvider,
diff --git a/extensions/BUILD.gn b/extensions/BUILD.gn index e7d9de91..e9d949f 100644 --- a/extensions/BUILD.gn +++ b/extensions/BUILD.gn
@@ -143,7 +143,6 @@ "//content/test:test_support", "//extensions/browser", "//extensions/browser:test_support", - "//extensions/browser/api:api_registration", "//extensions/common", "//extensions/common:core_api_provider", "//extensions/common/api",
diff --git a/extensions/browser/BUILD.gn b/extensions/browser/BUILD.gn index ebee53e..407ea25 100644 --- a/extensions/browser/BUILD.gn +++ b/extensions/browser/BUILD.gn
@@ -183,6 +183,7 @@ "extension_web_contents_observer.h", "extension_zoom_request_client.cc", "extension_zoom_request_client.h", + "extensions_browser_api_provider.h", "extensions_browser_client.cc", "extensions_browser_client.h", "external_install_info.cc", @@ -406,6 +407,21 @@ ] } +# NOTE: This is separate from ":browser" because it depends on +# //extensions/browser/api:api_registration, which in turn depends on +# :browser. +source_set("core_api_provider") { + sources = [ + "core_extensions_browser_api_provider.cc", + "core_extensions_browser_api_provider.h", + ] + + deps = [ + ":browser", + "//extensions/browser/api:api_registration", + ] +} + source_set("browser_tests") { testonly = true sources = [
diff --git a/extensions/browser/api/bluetooth_low_energy/bluetooth_low_energy_event_router.cc b/extensions/browser/api/bluetooth_low_energy/bluetooth_low_energy_event_router.cc index 896f001b..0725a85c 100644 --- a/extensions/browser/api/bluetooth_low_energy/bluetooth_low_energy_event_router.cc +++ b/extensions/browser/api/bluetooth_low_energy/bluetooth_low_energy_event_router.cc
@@ -12,7 +12,6 @@ #include "base/callback.h" #include "base/containers/hash_tables.h" #include "base/logging.h" -#include "base/memory/ptr_util.h" #include "base/strings/utf_string_conversions.h" #include "base/values.h" #include "content/public/browser/browser_context.h" @@ -1497,9 +1496,8 @@ continue; // Send the event. - std::unique_ptr<base::ListValue> args_copy(args->DeepCopy()); - std::unique_ptr<Event> event( - new Event(histogram_value, event_name, std::move(args_copy))); + auto event = std::make_unique<Event>(histogram_value, event_name, + args->CreateDeepCopy()); EventRouter::Get(browser_context_) ->DispatchEventToExtension(extension_id, std::move(event)); } @@ -1520,9 +1518,8 @@ return; // Send the event. - std::unique_ptr<base::ListValue> args_copy(args->DeepCopy()); - std::unique_ptr<Event> event( - new Event(histogram_value, event_name, std::move(args_copy))); + auto event = std::make_unique<Event>(histogram_value, event_name, + args->CreateDeepCopy()); EventRouter::Get(browser_context_) ->DispatchEventToExtension(extension_id, std::move(event)); } @@ -1891,8 +1888,7 @@ RequestIdToRequestMap* request_id_map = nullptr; const auto& iter = requests_.find(extension_id); if (iter == requests_.end()) { - std::unique_ptr<RequestIdToRequestMap> new_request_id_map = - base::WrapUnique(new RequestIdToRequestMap); + auto new_request_id_map = std::make_unique<RequestIdToRequestMap>(); request_id_map = new_request_id_map.get(); requests_[extension_id] = std::move(new_request_id_map); } else {
diff --git a/extensions/browser/api/networking_private/networking_private_chromeos.cc b/extensions/browser/api/networking_private/networking_private_chromeos.cc index 1879a3c9..6ec58e37 100644 --- a/extensions/browser/api/networking_private/networking_private_chromeos.cc +++ b/extensions/browser/api/networking_private/networking_private_chromeos.cc
@@ -851,7 +851,8 @@ const DictionaryCallback& callback, const std::string& service_path, const base::DictionaryValue& dictionary) { - std::unique_ptr<base::DictionaryValue> dictionary_copy(dictionary.DeepCopy()); + std::unique_ptr<base::DictionaryValue> dictionary_copy = + dictionary.CreateDeepCopy(); AppendThirdPartyProviderName(dictionary_copy.get()); if (managed) SetManagedActiveProxyValues(guid, dictionary_copy.get());
diff --git a/extensions/browser/api/networking_private/networking_private_linux.cc b/extensions/browser/api/networking_private/networking_private_linux.cc index 7ce947f5..61a87359 100644 --- a/extensions/browser/api/networking_private/networking_private_linux.cc +++ b/extensions/browser/api/networking_private/networking_private_linux.cc
@@ -79,7 +79,8 @@ // list then returns the list. std::unique_ptr<base::ListValue> CopyNetworkMapToList( const NetworkingPrivateLinux::NetworkMap& network_map) { - std::unique_ptr<base::ListValue> network_list(new base::ListValue); + auto network_list = std::make_unique<base::ListValue>(); + network_list->GetList().reserve(network_map.size()); for (const auto& network : network_map) { network_list->Append(network.second->CreateDeepCopy());
diff --git a/extensions/browser/api/storage/storage_api.cc b/extensions/browser/api/storage/storage_api.cc index bdfd811..89aa8a2 100644 --- a/extensions/browser/api/storage/storage_api.cc +++ b/extensions/browser/api/storage/storage_api.cc
@@ -11,7 +11,6 @@ #include <vector> #include "base/bind.h" -#include "base/memory/ptr_util.h" #include "base/strings/stringprintf.h" #include "base/values.h" #include "content/public/browser/browser_thread.h" @@ -173,10 +172,11 @@ return UseReadResult(std::move(result)); } - base::DictionaryValue* with_default_values = as_dict->DeepCopy(); + std::unique_ptr<base::DictionaryValue> with_default_values = + as_dict->CreateDeepCopy(); with_default_values->MergeDictionary(&result.settings()); return UseReadResult(ValueStore::ReadResult( - base::WrapUnique(with_default_values), result.PassStatus())); + std::move(with_default_values), result.PassStatus())); } default:
diff --git a/extensions/browser/core_extensions_browser_api_provider.cc b/extensions/browser/core_extensions_browser_api_provider.cc new file mode 100644 index 0000000..13211052 --- /dev/null +++ b/extensions/browser/core_extensions_browser_api_provider.cc
@@ -0,0 +1,19 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "extensions/browser/core_extensions_browser_api_provider.h" + +#include "extensions/browser/api/generated_api_registration.h" + +namespace extensions { + +CoreExtensionsBrowserAPIProvider::CoreExtensionsBrowserAPIProvider() = default; +CoreExtensionsBrowserAPIProvider::~CoreExtensionsBrowserAPIProvider() = default; + +void CoreExtensionsBrowserAPIProvider::RegisterExtensionFunctions( + ExtensionFunctionRegistry* registry) { + api::GeneratedFunctionRegistry::RegisterAll(registry); +} + +} // namespace extensions
diff --git a/extensions/browser/core_extensions_browser_api_provider.h b/extensions/browser/core_extensions_browser_api_provider.h new file mode 100644 index 0000000..201338d --- /dev/null +++ b/extensions/browser/core_extensions_browser_api_provider.h
@@ -0,0 +1,26 @@ +// 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 EXTENSIONS_BROWSER_CORE_EXTENSIONS_BROWSER_API_PROVIDER_H_ +#define EXTENSIONS_BROWSER_CORE_EXTENSIONS_BROWSER_API_PROVIDER_H_ + +#include "base/macros.h" +#include "extensions/browser/extensions_browser_api_provider.h" + +namespace extensions { + +class CoreExtensionsBrowserAPIProvider : public ExtensionsBrowserAPIProvider { + public: + CoreExtensionsBrowserAPIProvider(); + ~CoreExtensionsBrowserAPIProvider() override; + + void RegisterExtensionFunctions(ExtensionFunctionRegistry* registry) override; + + private: + DISALLOW_COPY_AND_ASSIGN(CoreExtensionsBrowserAPIProvider); +}; + +} // namespace extensions + +#endif // EXTENSIONS_BROWSER_CORE_EXTENSIONS_BROWSER_API_PROVIDER_H_
diff --git a/extensions/browser/event_router.cc b/extensions/browser/event_router.cc index 7c2d281..ea0b80f 100644 --- a/extensions/browser/event_router.cc +++ b/extensions/browser/event_router.cc
@@ -930,8 +930,7 @@ Event* Event::DeepCopy() const { Event* copy = new Event( - histogram_value, event_name, - std::unique_ptr<base::ListValue>(event_args->DeepCopy()), + histogram_value, event_name, event_args->CreateDeepCopy(), restrict_to_browser_context, event_url, user_gesture, filter_info); copy->will_dispatch_callback = will_dispatch_callback; return copy;
diff --git a/extensions/browser/extensions_browser_api_provider.h b/extensions/browser/extensions_browser_api_provider.h new file mode 100644 index 0000000..fc60fb23 --- /dev/null +++ b/extensions/browser/extensions_browser_api_provider.h
@@ -0,0 +1,31 @@ +// 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 EXTENSIONS_BROWSER_EXTENSIONS_BROWSER_API_PROVIDER_H_ +#define EXTENSIONS_BROWSER_EXTENSIONS_BROWSER_API_PROVIDER_H_ + +#include "base/macros.h" + +class ExtensionFunctionRegistry; +namespace extensions { + +// A class to provide browser-side, API-specific knowledge to the extensions +// system. This allows for composition of multiple providers, so that we can +// easily add or subtract features in different configurations. +class ExtensionsBrowserAPIProvider { + public: + ExtensionsBrowserAPIProvider() {} + virtual ~ExtensionsBrowserAPIProvider() {} + + // Registers any API functions in the given |registry|. + virtual void RegisterExtensionFunctions( + ExtensionFunctionRegistry* registry) = 0; + + private: + DISALLOW_COPY_AND_ASSIGN(ExtensionsBrowserAPIProvider); +}; + +} // namespace extensions + +#endif // EXTENSIONS_BROWSER_EXTENSIONS_BROWSER_API_PROVIDER_H_
diff --git a/extensions/browser/extensions_browser_client.cc b/extensions/browser/extensions_browser_client.cc index 882897c..4e6c04e0 100644 --- a/extensions/browser/extensions_browser_client.cc +++ b/extensions/browser/extensions_browser_client.cc
@@ -17,6 +17,28 @@ } // namespace +ExtensionsBrowserClient::ExtensionsBrowserClient() {} +ExtensionsBrowserClient::~ExtensionsBrowserClient() = default; + +ExtensionsBrowserClient* ExtensionsBrowserClient::Get() { + return g_extension_browser_client; +} + +void ExtensionsBrowserClient::Set(ExtensionsBrowserClient* client) { + g_extension_browser_client = client; +} + +void ExtensionsBrowserClient::RegisterExtensionFunctions( + ExtensionFunctionRegistry* registry) { + for (const auto& provider : providers_) + provider->RegisterExtensionFunctions(registry); +} + +void ExtensionsBrowserClient::AddAPIProvider( + std::unique_ptr<ExtensionsBrowserAPIProvider> provider) { + providers_.push_back(std::move(provider)); +} + scoped_refptr<update_client::UpdateClient> ExtensionsBrowserClient::CreateUpdateClient(content::BrowserContext* context) { return scoped_refptr<update_client::UpdateClient>(nullptr); @@ -71,12 +93,4 @@ return false; } -ExtensionsBrowserClient* ExtensionsBrowserClient::Get() { - return g_extension_browser_client; -} - -void ExtensionsBrowserClient::Set(ExtensionsBrowserClient* client) { - g_extension_browser_client = client; -} - } // namespace extensions
diff --git a/extensions/browser/extensions_browser_client.h b/extensions/browser/extensions_browser_client.h index bb45a8ac..522b64667 100644 --- a/extensions/browser/extensions_browser_client.h +++ b/extensions/browser/extensions_browser_client.h
@@ -15,6 +15,7 @@ #include "content/public/common/resource_type.h" #include "extensions/browser/extension_event_histogram_value.h" #include "extensions/browser/extension_prefs_observer.h" +#include "extensions/browser/extensions_browser_api_provider.h" #include "extensions/common/extension_id.h" #include "extensions/common/view_type.h" #include "services/network/public/mojom/url_loader.mojom.h" @@ -76,7 +77,23 @@ // they are only used in the browser process. class ExtensionsBrowserClient { public: - virtual ~ExtensionsBrowserClient() {} + ExtensionsBrowserClient(); + virtual ~ExtensionsBrowserClient(); + + // Returns the single instance of |this|. + static ExtensionsBrowserClient* Get(); + + // Sets and initializes the single instance. + static void Set(ExtensionsBrowserClient* client); + + // Registers all extension functions. + void RegisterExtensionFunctions(ExtensionFunctionRegistry* registry); + + // Adds a new API provider to the client. + void AddAPIProvider(std::unique_ptr<ExtensionsBrowserAPIProvider> provider); + + ///////////////////////////////////////////////////////////////////////////// + // Virtual Methods // Returns true if the embedder has started shutting down. virtual bool IsShuttingDown() = 0; @@ -218,10 +235,6 @@ // ExtensionSystem::Get. virtual ExtensionSystemProvider* GetExtensionSystemFactory() = 0; - // Registers extension functions not belonging to the core extensions APIs. - virtual void RegisterExtensionFunctions( - ExtensionFunctionRegistry* registry) const = 0; - // Registers additional interfaces to expose to a RenderFrame. virtual void RegisterExtensionInterfaces( service_manager::BinderRegistryWithArgs<content::RenderFrameHost*>* @@ -334,11 +347,10 @@ // code instead. virtual bool IsWebUIAllowedToMakeNetworkRequests(const url::Origin& origin); - // Returns the single instance of |this|. - static ExtensionsBrowserClient* Get(); + private: + std::vector<std::unique_ptr<ExtensionsBrowserAPIProvider>> providers_; - // Initialize the single instance. - static void Set(ExtensionsBrowserClient* client); + DISALLOW_COPY_AND_ASSIGN(ExtensionsBrowserClient); }; } // namespace extensions
diff --git a/extensions/browser/guest_view/app_view/app_view_guest.cc b/extensions/browser/guest_view/app_view/app_view_guest.cc index 731d420c..8a1ab79 100644 --- a/extensions/browser/guest_view/app_view/app_view_guest.cc +++ b/extensions/browser/guest_view/app_view/app_view_guest.cc
@@ -8,7 +8,6 @@ #include "base/command_line.h" #include "base/lazy_instance.h" -#include "base/memory/ptr_util.h" #include "components/guest_view/browser/guest_view_manager.h" #include "content/public/browser/render_process_host.h" #include "content/public/common/renderer_preferences.h" @@ -200,8 +199,7 @@ queue->AddPendingTask( browser_context(), guest_extension->id(), base::BindOnce(&AppViewGuest::LaunchAppAndFireEvent, - weak_ptr_factory_.GetWeakPtr(), - base::Passed(base::WrapUnique(data->DeepCopy())), + weak_ptr_factory_.GetWeakPtr(), data->CreateDeepCopy(), std::move(callback))); return; } @@ -210,8 +208,7 @@ ExtensionHost* host = process_manager->GetBackgroundHostForExtension(guest_extension->id()); DCHECK(host); - LaunchAppAndFireEvent(base::WrapUnique(data->DeepCopy()), std::move(callback), - host); + LaunchAppAndFireEvent(data->CreateDeepCopy(), std::move(callback), host); } void AppViewGuest::DidInitialize(const base::DictionaryValue& create_params) {
diff --git a/extensions/browser/guest_view/mime_handler_view/test_mime_handler_view_guest.cc b/extensions/browser/guest_view/mime_handler_view/test_mime_handler_view_guest.cc index 802cb0d..84eea25e 100644 --- a/extensions/browser/guest_view/mime_handler_view/test_mime_handler_view_guest.cc +++ b/extensions/browser/guest_view/mime_handler_view/test_mime_handler_view_guest.cc
@@ -42,14 +42,12 @@ WebContentsCreatedCallback callback) { // Delay the creation of the guest's WebContents if |delay_| is set. if (delay_) { - auto delta = base::TimeDelta::FromMilliseconds( - delay_); - std::unique_ptr<base::DictionaryValue> params(create_params.DeepCopy()); + auto delta = base::TimeDelta::FromMilliseconds(delay_); content::BrowserThread::PostDelayedTask( content::BrowserThread::UI, FROM_HERE, base::BindOnce(&TestMimeHandlerViewGuest::CallBaseCreateWebContents, - weak_ptr_factory_.GetWeakPtr(), base::Passed(¶ms), - std::move(callback)), + weak_ptr_factory_.GetWeakPtr(), + create_params.CreateDeepCopy(), std::move(callback)), delta); // Reset the delay for the next creation.
diff --git a/extensions/browser/sandboxed_unpacker.cc b/extensions/browser/sandboxed_unpacker.cc index 62569da..5d1926c 100644 --- a/extensions/browser/sandboxed_unpacker.cc +++ b/extensions/browser/sandboxed_unpacker.cc
@@ -940,7 +940,8 @@ // the original manifest. We do this to ensure the manifest doesn't contain an // exploitable bug that could be used to compromise the browser. DCHECK(!public_key_.empty()); - std::unique_ptr<base::DictionaryValue> final_manifest(manifest.DeepCopy()); + std::unique_ptr<base::DictionaryValue> final_manifest = + manifest.CreateDeepCopy(); final_manifest->SetString(manifest_keys::kPublicKey, public_key_); std::string manifest_json;
diff --git a/extensions/browser/test_extensions_browser_client.cc b/extensions/browser/test_extensions_browser_client.cc index 766f077..6a010a6 100644 --- a/extensions/browser/test_extensions_browser_client.cc +++ b/extensions/browser/test_extensions_browser_client.cc
@@ -210,9 +210,6 @@ return extension_system_factory_; } -void TestExtensionsBrowserClient::RegisterExtensionFunctions( - ExtensionFunctionRegistry* registry) const {} - void TestExtensionsBrowserClient::RegisterExtensionInterfaces( service_manager::BinderRegistryWithArgs<content::RenderFrameHost*>* registry,
diff --git a/extensions/browser/test_extensions_browser_client.h b/extensions/browser/test_extensions_browser_client.h index 5daf46d8..676762a21 100644 --- a/extensions/browser/test_extensions_browser_client.h +++ b/extensions/browser/test_extensions_browser_client.h
@@ -122,8 +122,6 @@ bool IsAppModeForcedForApp(const ExtensionId& extension_id) override; bool IsLoggedInAsPublicAccount() override; ExtensionSystemProvider* GetExtensionSystemFactory() override; - void RegisterExtensionFunctions( - ExtensionFunctionRegistry* registry) const override; void RegisterExtensionInterfaces(service_manager::BinderRegistryWithArgs< content::RenderFrameHost*>* registry, content::RenderFrameHost* render_frame_host,
diff --git a/extensions/common/core_extensions_api_provider.cc b/extensions/common/core_extensions_api_provider.cc index c476f05..e00c3f2c 100644 --- a/extensions/common/core_extensions_api_provider.cc +++ b/extensions/common/core_extensions_api_provider.cc
@@ -9,6 +9,7 @@ #include "extensions/common/api/generated_schemas.h" #include "extensions/common/api/manifest_features.h" #include "extensions/common/api/permission_features.h" +#include "extensions/common/common_manifest_handlers.h" #include "extensions/common/extensions_aliases.h" #include "extensions/common/features/json_feature_provider_source.h" #include "extensions/common/permissions/permissions_info.h" @@ -56,4 +57,8 @@ GetExtensionsPermissionAliases()); } +void CoreExtensionsAPIProvider::RegisterManifestHandlers() { + RegisterCommonManifestHandlers(); +} + } // namespace extensions
diff --git a/extensions/common/core_extensions_api_provider.h b/extensions/common/core_extensions_api_provider.h index 9b98eb9..fbcffd7 100644 --- a/extensions/common/core_extensions_api_provider.h +++ b/extensions/common/core_extensions_api_provider.h
@@ -25,6 +25,7 @@ bool IsAPISchemaGenerated(const std::string& name) override; base::StringPiece GetAPISchema(const std::string& name) override; void AddPermissionsProviders(PermissionsInfo* permissions_info) override; + void RegisterManifestHandlers() override; private: const ExtensionsAPIPermissions api_permissions_;
diff --git a/extensions/common/extension.cc b/extensions/common/extension.cc index c2aca3f..9bf511b 100644 --- a/extensions/common/extension.cc +++ b/extensions/common/extension.cc
@@ -157,8 +157,8 @@ base::ElapsedTimer timer; DCHECK(utf8_error); base::string16 error; - std::unique_ptr<extensions::Manifest> manifest(new extensions::Manifest( - location, std::unique_ptr<base::DictionaryValue>(value.DeepCopy()))); + std::unique_ptr<extensions::Manifest> manifest( + new extensions::Manifest(location, value.CreateDeepCopy())); if (!InitExtensionID(manifest.get(), path, explicit_id, flags, &error)) { *utf8_error = base::UTF16ToUTF8(error); @@ -786,7 +786,7 @@ extension_path(path), extension_location(location) { if (manifest) - extension_manifest.reset(manifest->DeepCopy()); + extension_manifest = manifest->CreateDeepCopy(); } ExtensionInfo::~ExtensionInfo() {}
diff --git a/extensions/common/extensions_api_provider.h b/extensions/common/extensions_api_provider.h index 2953a7e..013ca70 100644 --- a/extensions/common/extensions_api_provider.h +++ b/extensions/common/extensions_api_provider.h
@@ -43,6 +43,9 @@ // Adds any associated permissions. virtual void AddPermissionsProviders(PermissionsInfo* permissions_info) = 0; + // Registers manifest handlers for any associated API features. + virtual void RegisterManifestHandlers() = 0; + private: DISALLOW_COPY_AND_ASSIGN(ExtensionsAPIProvider); };
diff --git a/extensions/common/extensions_client.cc b/extensions/common/extensions_client.cc index d0659df..30b0295 100644 --- a/extensions/common/extensions_client.cc +++ b/extensions/common/extensions_client.cc
@@ -9,6 +9,7 @@ #include "extensions/common/extensions_api_provider.h" #include "extensions/common/features/feature_provider.h" #include "extensions/common/features/json_feature_provider_source.h" +#include "extensions/common/manifest_handler.h" #include "extensions/common/manifest_handlers/icons_handler.h" #include "extensions/common/permissions/permissions_info.h" @@ -109,9 +110,13 @@ void ExtensionsClient::DoInitialize() { initialize_called_ = true; + DCHECK(!ManifestHandler::IsRegistrationFinalized()); PermissionsInfo* permissions_info = PermissionsInfo::GetInstance(); - for (const auto& provider : api_providers_) + for (const auto& provider : api_providers_) { + provider->RegisterManifestHandlers(); provider->AddPermissionsProviders(permissions_info); + } + ManifestHandler::FinalizeRegistration(); Initialize(); }
diff --git a/extensions/common/manifest.cc b/extensions/common/manifest.cc index 15331fd..058b4f1 100644 --- a/extensions/common/manifest.cc +++ b/extensions/common/manifest.cc
@@ -246,9 +246,9 @@ return CanAccessPath(path) && value_->GetList(path, out_value); } -Manifest* Manifest::DeepCopy() const { - Manifest* manifest = new Manifest( - location_, std::unique_ptr<base::DictionaryValue>(value_->DeepCopy())); +std::unique_ptr<Manifest> Manifest::CreateDeepCopy() const { + auto manifest = + std::make_unique<Manifest>(location_, value_->CreateDeepCopy()); manifest->SetExtensionId(extension_id_); return manifest; }
diff --git a/extensions/common/manifest.h b/extensions/common/manifest.h index d89c245e..0596978 100644 --- a/extensions/common/manifest.h +++ b/extensions/common/manifest.h
@@ -193,9 +193,8 @@ bool GetList(const std::string& path, const base::ListValue** out_value) const; - // Returns a new Manifest equal to this one, passing ownership to - // the caller. - Manifest* DeepCopy() const; + // Returns a new Manifest equal to this one. + std::unique_ptr<Manifest> CreateDeepCopy() const; // Returns true if this equals the |other| manifest. bool Equals(const Manifest* other) const;
diff --git a/extensions/common/value_builder.cc b/extensions/common/value_builder.cc index 66f3bc3e..4010b85 100644 --- a/extensions/common/value_builder.cc +++ b/extensions/common/value_builder.cc
@@ -16,7 +16,7 @@ DictionaryBuilder::DictionaryBuilder() : dict_(new base::DictionaryValue) {} DictionaryBuilder::DictionaryBuilder(const base::DictionaryValue& init) - : dict_(init.DeepCopy()) {} + : dict_(init.CreateDeepCopy()) {} DictionaryBuilder::~DictionaryBuilder() {} @@ -30,8 +30,8 @@ // ListBuilder ListBuilder::ListBuilder() : list_(new base::ListValue) {} -ListBuilder::ListBuilder(const base::ListValue& init) : list_(init.DeepCopy()) { -} +ListBuilder::ListBuilder(const base::ListValue& init) + : list_(init.CreateDeepCopy()) {} ListBuilder::~ListBuilder() {} } // namespace extensions
diff --git a/extensions/shell/BUILD.gn b/extensions/shell/BUILD.gn index 75475a73..6eb3a9b 100644 --- a/extensions/shell/BUILD.gn +++ b/extensions/shell/BUILD.gn
@@ -58,7 +58,7 @@ "//extensions:extensions_resources", "//extensions:shell_and_test_pak", "//extensions/browser", - "//extensions/browser/api:api_registration", + "//extensions/browser:core_api_provider", "//extensions/browser/kiosk", "//extensions/common", "//extensions/common:core_api_provider", @@ -137,6 +137,8 @@ "browser/shell_extension_web_contents_observer.h", "browser/shell_extensions_api_client.cc", "browser/shell_extensions_api_client.h", + "browser/shell_extensions_browser_api_provider.cc", + "browser/shell_extensions_browser_api_provider.h", "browser/shell_extensions_browser_client.cc", "browser/shell_extensions_browser_client.h", "browser/shell_keep_alive_requester.cc",
diff --git a/extensions/shell/browser/shell_extensions_browser_api_provider.cc b/extensions/shell/browser/shell_extensions_browser_api_provider.cc new file mode 100644 index 0000000..9003d699 --- /dev/null +++ b/extensions/shell/browser/shell_extensions_browser_api_provider.cc
@@ -0,0 +1,21 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "extensions/shell/browser/shell_extensions_browser_api_provider.h" + +#include "extensions/shell/browser/api/generated_api_registration.h" + +namespace extensions { + +ShellExtensionsBrowserAPIProvider::ShellExtensionsBrowserAPIProvider() = + default; +ShellExtensionsBrowserAPIProvider::~ShellExtensionsBrowserAPIProvider() = + default; + +void ShellExtensionsBrowserAPIProvider::RegisterExtensionFunctions( + ExtensionFunctionRegistry* registry) { + shell::api::ShellGeneratedFunctionRegistry::RegisterAll(registry); +} + +} // namespace extensions
diff --git a/extensions/shell/browser/shell_extensions_browser_api_provider.h b/extensions/shell/browser/shell_extensions_browser_api_provider.h new file mode 100644 index 0000000..662d961b --- /dev/null +++ b/extensions/shell/browser/shell_extensions_browser_api_provider.h
@@ -0,0 +1,26 @@ +// 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 EXTENSIONS_SHELL_BROWSER_SHELL_EXTENSIONS_BROWSER_API_PROVIDER_H_ +#define EXTENSIONS_SHELL_BROWSER_SHELL_EXTENSIONS_BROWSER_API_PROVIDER_H_ + +#include "base/macros.h" +#include "extensions/browser/extensions_browser_api_provider.h" + +namespace extensions { + +class ShellExtensionsBrowserAPIProvider : public ExtensionsBrowserAPIProvider { + public: + ShellExtensionsBrowserAPIProvider(); + ~ShellExtensionsBrowserAPIProvider() override; + + void RegisterExtensionFunctions(ExtensionFunctionRegistry* registry) override; + + private: + DISALLOW_COPY_AND_ASSIGN(ShellExtensionsBrowserAPIProvider); +}; + +} // namespace extensions + +#endif // EXTENSIONS_SHELL_BROWSER_SHELL_EXTENSIONS_BROWSER_API_PROVIDER_H_
diff --git a/extensions/shell/browser/shell_extensions_browser_client.cc b/extensions/shell/browser/shell_extensions_browser_client.cc index 714773e..30f50e1b 100644 --- a/extensions/shell/browser/shell_extensions_browser_client.cc +++ b/extensions/shell/browser/shell_extensions_browser_client.cc
@@ -14,21 +14,20 @@ #include "content/public/browser/render_frame_host.h" #include "content/public/browser/resource_request_info.h" #include "extensions/browser/api/extensions_api_client.h" -#include "extensions/browser/api/generated_api_registration.h" +#include "extensions/browser/core_extensions_browser_api_provider.h" #include "extensions/browser/event_router.h" -#include "extensions/browser/extension_function_registry.h" #include "extensions/browser/mojo/interface_registration.h" #include "extensions/browser/null_app_sorting.h" #include "extensions/browser/updater/null_extension_cache.h" #include "extensions/browser/url_request_util.h" #include "extensions/common/features/feature_channel.h" -#include "extensions/shell/browser/api/generated_api_registration.h" #include "extensions/shell/browser/api/runtime/shell_runtime_api_delegate.h" #include "extensions/shell/browser/delegates/shell_kiosk_delegate.h" #include "extensions/shell/browser/shell_extension_host_delegate.h" #include "extensions/shell/browser/shell_extension_system_factory.h" #include "extensions/shell/browser/shell_extension_web_contents_observer.h" #include "extensions/shell/browser/shell_extensions_api_client.h" +#include "extensions/shell/browser/shell_extensions_browser_api_provider.h" #include "extensions/shell/browser/shell_navigation_ui_data.h" #if defined(OS_CHROMEOS) @@ -46,6 +45,9 @@ // app_shell does not have a concept of channel yet, so leave UNKNOWN to // enable all channel-dependent extension APIs. SetCurrentChannel(version_info::Channel::UNKNOWN); + + AddAPIProvider(std::make_unique<CoreExtensionsBrowserAPIProvider>()); + AddAPIProvider(std::make_unique<ShellExtensionsBrowserAPIProvider>()); } ShellExtensionsBrowserClient::~ShellExtensionsBrowserClient() { @@ -213,15 +215,6 @@ return ShellExtensionSystemFactory::GetInstance(); } -void ShellExtensionsBrowserClient::RegisterExtensionFunctions( - ExtensionFunctionRegistry* registry) const { - // Register core extension-system APIs. - api::GeneratedFunctionRegistry::RegisterAll(registry); - - // app_shell-only APIs. - shell::api::ShellGeneratedFunctionRegistry::RegisterAll(registry); -} - void ShellExtensionsBrowserClient::RegisterExtensionInterfaces( service_manager::BinderRegistryWithArgs<content::RenderFrameHost*>* registry,
diff --git a/extensions/shell/browser/shell_extensions_browser_client.h b/extensions/shell/browser/shell_extensions_browser_client.h index ac5576c..4f53fa1d 100644 --- a/extensions/shell/browser/shell_extensions_browser_client.h +++ b/extensions/shell/browser/shell_extensions_browser_client.h
@@ -93,8 +93,6 @@ bool IsAppModeForcedForApp(const ExtensionId& extension_id) override; bool IsLoggedInAsPublicAccount() override; ExtensionSystemProvider* GetExtensionSystemFactory() override; - void RegisterExtensionFunctions( - ExtensionFunctionRegistry* registry) const override; void RegisterExtensionInterfaces(service_manager::BinderRegistryWithArgs< content::RenderFrameHost*>* registry, content::RenderFrameHost* render_frame_host,
diff --git a/extensions/shell/common/shell_extensions_api_provider.cc b/extensions/shell/common/shell_extensions_api_provider.cc index 8379afe..3fa98699 100644 --- a/extensions/shell/common/shell_extensions_api_provider.cc +++ b/extensions/shell/common/shell_extensions_api_provider.cc
@@ -50,4 +50,6 @@ void ShellExtensionsAPIProvider::AddPermissionsProviders( PermissionsInfo* permissions_info) {} +void ShellExtensionsAPIProvider::RegisterManifestHandlers() {} + } // namespace extensions
diff --git a/extensions/shell/common/shell_extensions_api_provider.h b/extensions/shell/common/shell_extensions_api_provider.h index 71d84c7..2d0d3325 100644 --- a/extensions/shell/common/shell_extensions_api_provider.h +++ b/extensions/shell/common/shell_extensions_api_provider.h
@@ -24,6 +24,7 @@ bool IsAPISchemaGenerated(const std::string& name) override; base::StringPiece GetAPISchema(const std::string& name) override; void AddPermissionsProviders(PermissionsInfo* permissions_info) override; + void RegisterManifestHandlers() override; private: DISALLOW_COPY_AND_ASSIGN(ShellExtensionsAPIProvider);
diff --git a/extensions/shell/common/shell_extensions_client.cc b/extensions/shell/common/shell_extensions_client.cc index fb19c36a..916f901b 100644 --- a/extensions/shell/common/shell_extensions_client.cc +++ b/extensions/shell/common/shell_extensions_client.cc
@@ -12,11 +12,9 @@ #include "base/macros.h" #include "components/version_info/version_info.h" #include "content/public/common/user_agent.h" -#include "extensions/common/common_manifest_handlers.h" #include "extensions/common/core_extensions_api_provider.h" #include "extensions/common/extension_urls.h" #include "extensions/common/features/simple_feature.h" -#include "extensions/common/manifest_handler.h" #include "extensions/common/permissions/permission_message_provider.h" #include "extensions/common/permissions/permissions_provider.h" #include "extensions/common/url_pattern_set.h" @@ -73,8 +71,6 @@ } void ShellExtensionsClient::Initialize() { - RegisterCommonManifestHandlers(); - ManifestHandler::FinalizeRegistration(); // TODO(jamescook): Do we need to whitelist any extensions? }
diff --git a/extensions/test/test_extensions_client.cc b/extensions/test/test_extensions_client.cc index 3fbce7c..5591d8b 100644 --- a/extensions/test/test_extensions_client.cc +++ b/extensions/test/test_extensions_client.cc
@@ -11,10 +11,8 @@ #include "base/command_line.h" #include "base/files/file_path.h" #include "base/stl_util.h" -#include "extensions/common/common_manifest_handlers.h" #include "extensions/common/core_extensions_api_provider.h" #include "extensions/common/extension_urls.h" -#include "extensions/common/manifest_handler.h" #include "extensions/common/url_pattern_set.h" #include "extensions/grit/extensions_resources.h" #include "extensions/test/test_permission_message_provider.h" @@ -41,12 +39,6 @@ } void TestExtensionsClient::Initialize() { - // Registration could already be finalized in unit tests, where the utility - // thread runs in-process. - if (!ManifestHandler::IsRegistrationFinalized()) { - RegisterCommonManifestHandlers(); - ManifestHandler::FinalizeRegistration(); - } } void TestExtensionsClient::InitializeWebStoreUrls(
diff --git a/gpu/command_buffer/client/gles2_implementation.cc b/gpu/command_buffer/client/gles2_implementation.cc index 93f088e..6a18c79 100644 --- a/gpu/command_buffer/client/gles2_implementation.cc +++ b/gpu/command_buffer/client/gles2_implementation.cc
@@ -10,6 +10,7 @@ #include <GLES2/gl2ext.h> #include <GLES2/gl2extchromium.h> #include <GLES3/gl3.h> +#include <GLES3/gl31.h> #include <stddef.h> #include <stdint.h> #include <algorithm> @@ -199,10 +200,12 @@ bound_renderbuffer_(0), current_program_(0), bound_array_buffer_(0), + bound_atomic_counter_buffer_(0), bound_copy_read_buffer_(0), bound_copy_write_buffer_(0), bound_pixel_pack_buffer_(0), bound_pixel_unpack_buffer_(0), + bound_shader_storage_buffer_(0), bound_transform_feedback_buffer_(0), bound_uniform_buffer_(0), bound_pixel_pack_transfer_buffer_id_(0), @@ -1010,6 +1013,38 @@ case GL_VERTEX_ARRAY_BINDING: return false; default: + break; + } + + if (capabilities_.minor_version < 1) { + return false; + } + + // ES31 parameters. + switch (pname) { + case GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS: + *params = capabilities_.max_atomic_counter_buffer_bindings; + return true; + case GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS: + *params = capabilities_.max_shader_storage_buffer_bindings; + return true; + case GL_ATOMIC_COUNTER_BUFFER_BINDING: + *params = bound_atomic_counter_buffer_; + return true; + case GL_SHADER_STORAGE_BUFFER_BINDING: + *params = bound_shader_storage_buffer_; + return true; + case GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT: + *params = capabilities_.shader_storage_buffer_offset_alignment; + return true; + + // Non-cached ES31 parameters. + case GL_ATOMIC_COUNTER_BUFFER_SIZE: + case GL_ATOMIC_COUNTER_BUFFER_START: + case GL_SHADER_STORAGE_BUFFER_SIZE: + case GL_SHADER_STORAGE_BUFFER_START: + return false; + default: return false; } } @@ -4138,6 +4173,12 @@ changed = true; } break; + case GL_ATOMIC_COUNTER_BUFFER: + if (bound_atomic_counter_buffer_ != buffer_id) { + bound_atomic_counter_buffer_ = buffer_id; + changed = true; + } + break; case GL_COPY_READ_BUFFER: if (bound_copy_read_buffer_ != buffer_id) { bound_copy_read_buffer_ = buffer_id; @@ -4171,6 +4212,12 @@ case GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM: bound_pixel_unpack_transfer_buffer_id_ = buffer_id; break; + case GL_SHADER_STORAGE_BUFFER: + if (bound_shader_storage_buffer_ != buffer_id) { + bound_shader_storage_buffer_ = buffer_id; + changed = true; + } + break; case GL_TRANSFORM_FEEDBACK_BUFFER: if (bound_transform_feedback_buffer_ != buffer_id) { bound_transform_feedback_buffer_ = buffer_id; @@ -4206,6 +4253,14 @@ GLuint buffer_id, const char* function_name) { switch (target) { + case GL_ATOMIC_COUNTER_BUFFER: + if (index >= static_cast<GLuint>( + capabilities_.max_atomic_counter_buffer_bindings)) { + SetGLError(GL_INVALID_VALUE, function_name, "index out of range"); + return false; + } + bound_atomic_counter_buffer_ = buffer_id; + break; case GL_TRANSFORM_FEEDBACK_BUFFER: if (index >= static_cast<GLuint>( capabilities_.max_transform_feedback_separate_attribs)) { @@ -4214,6 +4269,14 @@ } bound_transform_feedback_buffer_ = buffer_id; break; + case GL_SHADER_STORAGE_BUFFER: + if (index >= static_cast<GLuint>( + capabilities_.max_shader_storage_buffer_bindings)) { + SetGLError(GL_INVALID_VALUE, function_name, "index out of range"); + return false; + } + bound_shader_storage_buffer_ = buffer_id; + break; case GL_UNIFORM_BUFFER: if (index >= static_cast<GLuint>(capabilities_.max_uniform_buffer_bindings)) { @@ -4437,6 +4500,9 @@ if (buffers[ii] == bound_array_buffer_) { bound_array_buffer_ = 0; } + if (buffers[ii] == bound_atomic_counter_buffer_) { + bound_atomic_counter_buffer_ = 0; + } if (buffers[ii] == bound_copy_read_buffer_) { bound_copy_read_buffer_ = 0; } @@ -4449,6 +4515,9 @@ if (buffers[ii] == bound_pixel_unpack_buffer_) { bound_pixel_unpack_buffer_ = 0; } + if (buffers[ii] == bound_shader_storage_buffer_) { + bound_shader_storage_buffer_ = 0; + } if (buffers[ii] == bound_transform_feedback_buffer_) { bound_transform_feedback_buffer_ = 0; } @@ -5184,11 +5253,13 @@ << GLES2Util::GetStringEnum(target) << ")"); switch (target) { case GL_ARRAY_BUFFER: + case GL_ATOMIC_COUNTER_BUFFER: case GL_ELEMENT_ARRAY_BUFFER: case GL_COPY_READ_BUFFER: case GL_COPY_WRITE_BUFFER: case GL_PIXEL_PACK_BUFFER: case GL_PIXEL_UNPACK_BUFFER: + case GL_SHADER_STORAGE_BUFFER: case GL_TRANSFORM_FEEDBACK_BUFFER: case GL_UNIFORM_BUFFER: break;
diff --git a/gpu/command_buffer/client/gles2_implementation.h b/gpu/command_buffer/client/gles2_implementation.h index 920276d..3f83d9e 100644 --- a/gpu/command_buffer/client/gles2_implementation.h +++ b/gpu/command_buffer/client/gles2_implementation.h
@@ -692,10 +692,12 @@ GLuint current_program_; GLuint bound_array_buffer_; + GLuint bound_atomic_counter_buffer_; GLuint bound_copy_read_buffer_; GLuint bound_copy_write_buffer_; GLuint bound_pixel_pack_buffer_; GLuint bound_pixel_unpack_buffer_; + GLuint bound_shader_storage_buffer_; GLuint bound_transform_feedback_buffer_; GLuint bound_uniform_buffer_; // We don't cache the currently bound transform feedback buffer, because
diff --git a/gpu/command_buffer/common/capabilities.h b/gpu/command_buffer/common/capabilities.h index fb8d96a..4b76d415 100644 --- a/gpu/command_buffer/common/capabilities.h +++ b/gpu/command_buffer/common/capabilities.h
@@ -112,6 +112,9 @@ int max_transform_feedback_separate_components = 0; int64_t max_uniform_block_size = 0; int max_uniform_buffer_bindings = 0; + int max_atomic_counter_buffer_bindings = 0; + int max_shader_storage_buffer_bindings = 0; + int shader_storage_buffer_offset_alignment = 1; int max_varying_components = 0; int max_vertex_output_components = 0; int max_vertex_uniform_blocks = 0;
diff --git a/gpu/command_buffer/common/gles2_cmd_utils.cc b/gpu/command_buffer/common/gles2_cmd_utils.cc index 67daf60..78ee2641 100644 --- a/gpu/command_buffer/common/gles2_cmd_utils.cc +++ b/gpu/command_buffer/common/gles2_cmd_utils.cc
@@ -11,6 +11,7 @@ #include <GLES2/gl2ext.h> #include <GLES2/gl2extchromium.h> #include <GLES3/gl3.h> +#include <GLES3/gl31.h> #include <sstream> @@ -281,6 +282,26 @@ case GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT: return 1; + // ES31 + case GL_ATOMIC_COUNTER_BUFFER_BINDING: + return 1; + case GL_ATOMIC_COUNTER_BUFFER_SIZE: + return 1; + case GL_ATOMIC_COUNTER_BUFFER_START: + return 1; + case GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS: + return 1; + case GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS: + return 1; + case GL_SHADER_STORAGE_BUFFER_BINDING: + return 1; + case GL_SHADER_STORAGE_BUFFER_SIZE: + return 1; + case GL_SHADER_STORAGE_BUFFER_START: + return 1; + case GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT: + return 1; + // -- glGetBooleanv, glGetFloatv, glGetIntergerv with // GL_CHROMIUM_framebuffer_multisample case GL_MAX_SAMPLES_EXT: @@ -1646,6 +1667,8 @@ switch (target) { case GL_ARRAY_BUFFER: return GL_ARRAY_BUFFER_BINDING; + case GL_ATOMIC_COUNTER_BUFFER: + return GL_ATOMIC_COUNTER_BUFFER_BINDING; case GL_COPY_READ_BUFFER: return GL_COPY_READ_BUFFER_BINDING; case GL_COPY_WRITE_BUFFER: @@ -1656,6 +1679,8 @@ return GL_PIXEL_PACK_BUFFER_BINDING; case GL_PIXEL_UNPACK_BUFFER: return GL_PIXEL_UNPACK_BUFFER_BINDING; + case GL_SHADER_STORAGE_BUFFER: + return GL_SHADER_STORAGE_BUFFER_BINDING; case GL_TRANSFORM_FEEDBACK_BUFFER: return GL_TRANSFORM_FEEDBACK_BUFFER_BINDING; case GL_UNIFORM_BUFFER:
diff --git a/gpu/command_buffer/service/gl_utils.cc b/gpu/command_buffer/service/gl_utils.cc index af2ac7e..b841a7e8 100644 --- a/gpu/command_buffer/service/gl_utils.cc +++ b/gpu/command_buffer/service/gl_utils.cc
@@ -267,6 +267,12 @@ &caps->uniform_buffer_offset_alignment); caps->major_version = 3; if (feature_info->IsWebGL2ComputeContext()) { + glGetIntegerv(GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS, + &caps->max_atomic_counter_buffer_bindings); + glGetIntegerv(GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, + &caps->max_shader_storage_buffer_bindings); + glGetIntegerv(GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT, + &caps->shader_storage_buffer_offset_alignment); caps->minor_version = 1; } else { caps->minor_version = 0;
diff --git a/gpu/command_buffer/service/service_utils.cc b/gpu/command_buffer/service/service_utils.cc index 468e145..af30aaa 100644 --- a/gpu/command_buffer/service/service_utils.cc +++ b/gpu/command_buffer/service/service_utils.cc
@@ -165,6 +165,8 @@ command_line->HasSwitch(switches::kDisableGpuDriverBugWorkarounds); gpu_preferences.ignore_gpu_blacklist = command_line->HasSwitch(switches::kIgnoreGpuBlacklist); + gpu_preferences.enable_webgpu = + command_line->HasSwitch(switches::kEnableUnsafeWebGPU); return gpu_preferences; }
diff --git a/gpu/config/gpu_preferences.h b/gpu/config/gpu_preferences.h index bf5e295f..8fc47a80 100644 --- a/gpu/config/gpu_preferences.h +++ b/gpu/config/gpu_preferences.h
@@ -209,6 +209,9 @@ // Enable the GPU benchmarking extension; used by tests only. bool enable_gpu_benchmarking_extension = false; + // Enable the WebGPU command buffer. + bool enable_webgpu = false; + // Please update gpu_preferences_unittest.cc when making additions or // changes to this struct. };
diff --git a/gpu/config/gpu_preferences_unittest.cc b/gpu/config/gpu_preferences_unittest.cc index 6ec40437..3647d83 100644 --- a/gpu/config/gpu_preferences_unittest.cc +++ b/gpu/config/gpu_preferences_unittest.cc
@@ -76,6 +76,7 @@ EXPECT_EQ(left.enable_vulkan, right.enable_vulkan); EXPECT_EQ(left.enable_gpu_benchmarking_extension, right.enable_gpu_benchmarking_extension); + EXPECT_EQ(left.enable_webgpu, right.enable_webgpu); } } // namespace @@ -154,6 +155,7 @@ GPU_PREFERENCES_FIELD(watchdog_starts_backgrounded, true) GPU_PREFERENCES_FIELD(enable_vulkan, true) GPU_PREFERENCES_FIELD(enable_gpu_benchmarking_extension, true) + GPU_PREFERENCES_FIELD(enable_webgpu, true) input_prefs.texture_target_exception_list.emplace_back( gfx::BufferUsage::SCANOUT, gfx::BufferFormat::RGBA_8888);
diff --git a/gpu/config/gpu_switches.cc b/gpu/config/gpu_switches.cc index fbab0aa..f754cd4f 100644 --- a/gpu/config/gpu_switches.cc +++ b/gpu/config/gpu_switches.cc
@@ -53,4 +53,6 @@ const char kDisableGpuProcessForDX12VulkanInfoCollection[] = "disable-gpu-process-for-dx12-vulkan-info-collection"; +const char kEnableUnsafeWebGPU[] = "enable-unsafe-webgpu"; + } // namespace switches
diff --git a/gpu/config/gpu_switches.h b/gpu/config/gpu_switches.h index c43bdcb..5017f5f2 100644 --- a/gpu/config/gpu_switches.h +++ b/gpu/config/gpu_switches.h
@@ -21,6 +21,7 @@ GPU_EXPORT extern const char kWebglAntialiasingMode[]; GPU_EXPORT extern const char kWebglMSAASampleCount[]; GPU_EXPORT extern const char kDisableGpuProcessForDX12VulkanInfoCollection[]; +GPU_EXPORT extern const char kEnableUnsafeWebGPU[]; } // namespace switches #endif // GPU_CONFIG_GPU_SWITCHES_H_
diff --git a/gpu/ipc/common/gpu_command_buffer_traits_multi.h b/gpu/ipc/common/gpu_command_buffer_traits_multi.h index b9a37a4..aed550f 100644 --- a/gpu/ipc/common/gpu_command_buffer_traits_multi.h +++ b/gpu/ipc/common/gpu_command_buffer_traits_multi.h
@@ -86,6 +86,9 @@ IPC_STRUCT_TRAITS_MEMBER(max_transform_feedback_separate_components) IPC_STRUCT_TRAITS_MEMBER(max_uniform_block_size) IPC_STRUCT_TRAITS_MEMBER(max_uniform_buffer_bindings) + IPC_STRUCT_TRAITS_MEMBER(max_atomic_counter_buffer_bindings) + IPC_STRUCT_TRAITS_MEMBER(max_shader_storage_buffer_bindings) + IPC_STRUCT_TRAITS_MEMBER(shader_storage_buffer_offset_alignment) IPC_STRUCT_TRAITS_MEMBER(max_varying_components) IPC_STRUCT_TRAITS_MEMBER(max_vertex_output_components) IPC_STRUCT_TRAITS_MEMBER(max_vertex_uniform_blocks)
diff --git a/gpu/ipc/common/gpu_preferences.mojom b/gpu/ipc/common/gpu_preferences.mojom index dabdd96..b2940ad 100644 --- a/gpu/ipc/common/gpu_preferences.mojom +++ b/gpu/ipc/common/gpu_preferences.mojom
@@ -65,4 +65,5 @@ bool watchdog_starts_backgrounded; bool enable_vulkan; bool enable_gpu_benchmarking_extension; + bool enable_webgpu; };
diff --git a/gpu/ipc/common/gpu_preferences_struct_traits.h b/gpu/ipc/common/gpu_preferences_struct_traits.h index 5db91ae..11340777 100644 --- a/gpu/ipc/common/gpu_preferences_struct_traits.h +++ b/gpu/ipc/common/gpu_preferences_struct_traits.h
@@ -122,6 +122,7 @@ out->enable_vulkan = prefs.enable_vulkan(); out->enable_gpu_benchmarking_extension = prefs.enable_gpu_benchmarking_extension(); + out->enable_webgpu = prefs.enable_webgpu(); return true; } @@ -265,6 +266,9 @@ const gpu::GpuPreferences& prefs) { return prefs.enable_gpu_benchmarking_extension; } + static bool enable_webgpu(const gpu::GpuPreferences& prefs) { + return prefs.enable_webgpu; + } }; } // namespace mojo
diff --git a/infra/config/global/cr-buildbucket.cfg b/infra/config/global/cr-buildbucket.cfg index 0c4570a..963be5b5 100644 --- a/infra/config/global/cr-buildbucket.cfg +++ b/infra/config/global/cr-buildbucket.cfg
@@ -176,6 +176,13 @@ } builder_mixins { + name: "android-gpu-manual-try" + mixins: "android-optional-gpu-try" + # Increase timeout to allow tryjobs against small number of phones. + mixins: "gpu-slow-bot" +} + +builder_mixins { name: "android-optional-gpu-try" dimensions: "os:Ubuntu-14.04" mixins: "gpu-optional-try" @@ -627,6 +634,8 @@ builders { name: "Android FYI Release (Nexus 5)" mixins: "android-gpu-fyi-ci" + # Increase timeout to allow tryjobs against small number of phones. + mixins: "gpu-slow-bot" } builders { @@ -637,21 +646,29 @@ builders { name: "Android FYI Release (Nexus 6)" mixins: "android-gpu-fyi-ci" + # Increase timeout to allow tryjobs against small number of phones. + mixins: "gpu-slow-bot" } builders { name: "Android FYI Release (Nexus 6P)" mixins: "android-gpu-fyi-ci" + # Increase timeout to allow tryjobs against small number of phones. + mixins: "gpu-slow-bot" } builders { name: "Android FYI Release (Nexus 9)" mixins: "android-gpu-fyi-ci" + # Increase timeout to allow tryjobs against small number of phones. + mixins: "gpu-slow-bot" } builders { name: "Android FYI Release (NVIDIA Shield TV)" mixins: "android-gpu-fyi-ci" + # Increase timeout to allow tryjobs against small number of phones. + mixins: "gpu-slow-bot" } builders { @@ -2430,11 +2447,41 @@ dimensions: "os:Ubuntu-14.04" } builders { - mixins: "android-optional-gpu-try" - # Increase timeout to allow tryjobs against small number of phones. - mixins: "gpu-slow-bot" + mixins: "android-gpu-manual-try" + name: "gpu-manual-try-android-l-nexus-5-32" + } + builders { + mixins: "android-gpu-manual-try" + name: "gpu-manual-try-android-l-nexus-6-32" + } + builders { + mixins: "android-gpu-manual-try" + name: "gpu-manual-try-android-m-nexus-6p-64" + } + builders { + mixins: "android-gpu-manual-try" + name: "gpu-manual-try-android-m-nexus-9-64" + } + builders { + mixins: "android-gpu-manual-try" + name: "gpu-manual-try-android-n-nvidia-shield-tv-64" + } + builders { + mixins: "android-gpu-manual-try" name: "gpu-manual-try-android-p-pixel-2-32" } + builders { + mixins: "android-gpu-manual-try" + name: "gpu-manual-try-android-p-pixel-2-32-deqp" + } + builders { + mixins: "android-gpu-manual-try" + name: "gpu-manual-try-android-p-pixel-2-64" + } + builders { + mixins: "android-gpu-manual-try" + name: "gpu-manual-try-android-p-pixel-2-64-deqp" + } builders { mixins: "chromeos-try" name: "chromeos-amd64-generic-rel" } builders { mixins: "chromeos-try" name: "chromeos-daisy-rel" }
diff --git a/infra/config/global/luci-milo.cfg b/infra/config/global/luci-milo.cfg index 77dfcb6..2ea8ae48 100644 --- a/infra/config/global/luci-milo.cfg +++ b/infra/config/global/luci-milo.cfg
@@ -3920,8 +3920,32 @@ name: "buildbucket/luci.chromium.try/android-kitkat-arm-rel" } builders { + name: "buildbucket/luci.chromium.try/gpu-manual-try-android-l-nexus-5-32" + } + builders { + name: "buildbucket/luci.chromium.try/gpu-manual-try-android-l-nexus-6-32" + } + builders { + name: "buildbucket/luci.chromium.try/gpu-manual-try-android-m-nexus-6p-64" + } + builders { + name: "buildbucket/luci.chromium.try/gpu-manual-try-android-m-nexus-9-64" + } + builders { + name: "buildbucket/luci.chromium.try/gpu-manual-try-android-n-nvidia-shield-tv-64" + } + builders { name: "buildbucket/luci.chromium.try/gpu-manual-try-android-p-pixel-2-32" } + builders { + name: "buildbucket/luci.chromium.try/gpu-manual-try-android-p-pixel-2-32-deqp" + } + builders { + name: "buildbucket/luci.chromium.try/gpu-manual-try-android-p-pixel-2-64" + } + builders { + name: "buildbucket/luci.chromium.try/gpu-manual-try-android-p-pixel-2-64-deqp" + } builder_view_only: true } @@ -4522,9 +4546,33 @@ name: "buildbucket/luci.chromium.try/fuchsia" } builders { + name: "buildbucket/luci.chromium.try/gpu-manual-try-android-l-nexus-5-32" + } + builders { + name: "buildbucket/luci.chromium.try/gpu-manual-try-android-l-nexus-6-32" + } + builders { + name: "buildbucket/luci.chromium.try/gpu-manual-try-android-m-nexus-6p-64" + } + builders { + name: "buildbucket/luci.chromium.try/gpu-manual-try-android-m-nexus-9-64" + } + builders { + name: "buildbucket/luci.chromium.try/gpu-manual-try-android-n-nvidia-shield-tv-64" + } + builders { name: "buildbucket/luci.chromium.try/gpu-manual-try-android-p-pixel-2-32" } builders { + name: "buildbucket/luci.chromium.try/gpu-manual-try-android-p-pixel-2-32-deqp" + } + builders { + name: "buildbucket/luci.chromium.try/gpu-manual-try-android-p-pixel-2-64" + } + builders { + name: "buildbucket/luci.chromium.try/gpu-manual-try-android-p-pixel-2-64-deqp" + } + builders { name: "buildbucket/luci.chromium.try/gpu_manual_try_win7_nvidia_rel" } builders {
diff --git a/ios/chrome/browser/passwords/password_controller.h b/ios/chrome/browser/passwords/password_controller.h index 727ec880..0d368507 100644 --- a/ios/chrome/browser/passwords/password_controller.h +++ b/ios/chrome/browser/passwords/password_controller.h
@@ -9,6 +9,7 @@ #include <memory> #import "components/autofill/ios/browser/form_suggestion_provider.h" +#import "components/password_manager/ios/password_controller_helper.h" #import "ios/chrome/browser/passwords/ios_chrome_password_manager_client.h" #import "ios/chrome/browser/passwords/ios_chrome_password_manager_driver.h" #import "ios/web/public/web_state/web_state_observer_bridge.h" @@ -21,7 +22,6 @@ namespace password_manager { class PasswordManagerClient; -class PasswordManagerDriver; } // namespace password_manager // Delegate for registering view controller and displaying its view. Used to @@ -41,7 +41,8 @@ // Per-tab password controller. Handles password autofill and saving. @interface PasswordController : NSObject<CRWWebStateObserver, PasswordManagerClientDelegate, - PasswordManagerDriverDelegate> + PasswordManagerDriverDelegate, + PasswordControllerHelperDelegate> // An object that can provide suggestions from this PasswordController. @property(nonatomic, readonly) id<FormSuggestionProvider> suggestionProvider;
diff --git a/ios/chrome/browser/passwords/password_controller.mm b/ios/chrome/browser/passwords/password_controller.mm index 395d3025..b4f65f1 100644 --- a/ios/chrome/browser/passwords/password_controller.mm +++ b/ios/chrome/browser/passwords/password_controller.mm
@@ -1,4 +1,4 @@ -// Copyright 2012 The Chromium Authors. All rights reserved. +// 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. @@ -65,6 +65,7 @@ using autofill::PasswordForm; using password_manager::AccountSelectFillData; using password_manager::FillData; +using password_manager::GetPageURLAndCheckTrustLevel; using password_manager::PasswordFormManagerForUI; using password_manager::PasswordManager; using password_manager::PasswordManagerClient; @@ -92,10 +93,6 @@ // Duration for notify user auto-sign in dialog being displayed. constexpr int kNotifyAutoSigninDuration = 3; // seconds -// Script command prefix for form changes. Possible command to be sent from -// injected JS is 'form.buttonClicked'. -constexpr char kCommandPrefix[] = "passwordForm"; - // The string ' •••' appended to the username in the suggestion. NSString* const kSuggestionSuffix = @" ••••••••"; @@ -117,11 +114,12 @@ @property(nonatomic, strong) NotifyUserAutoSigninViewController* notifyAutoSigninViewController; +// Helper contains common password controller logic. +@property(nonatomic, readonly) PasswordControllerHelper* helper; + @end -@interface PasswordController ()<FormActivityObserver, - FormSuggestionProvider, - PasswordFormFiller> +@interface PasswordController ()<FormSuggestionProvider, PasswordFormFiller> // Parses the |jsonString| which contatins the password forms found on a web // page to populate the |forms| vector. @@ -159,24 +157,12 @@ // fetching stored credentials. - (void)findPasswordFormsAndSendThemToPasswordStore; -// Finds the currently submitted password form and calls |completionHandler| -// with the populated data structure. |found| is YES if the current form was -// found successfully, NO otherwise. |completionHandler| cannot be nil. -- (void)extractSubmittedPasswordForm:(const std::string&)formName - completionHandler: - (void (^)(BOOL found, - const autofill::PasswordForm& form)) - completionHandler; - // Displays infobar for |form| with |type|. If |type| is UPDATE, the user // is prompted to update the password. If |type| is SAVE, the user is prompted // to save the password. - (void)showInfoBarForForm:(std::unique_ptr<PasswordFormManagerForUI>)form infoBarType:(PasswordInfoBarType)type; -// Handler for injected JavaScript callbacks. -- (BOOL)handleScriptCommand:(const base::DictionaryValue&)JSONCommand; - @end namespace { @@ -227,18 +213,6 @@ return [suggestions copy]; } -// Returns true if the trust level for the current page URL of |web_state| is -// kAbsolute. If |page_url| is not null, fills it with the current page URL. -bool GetPageURLAndCheckTrustLevel(web::WebState* web_state, GURL* page_url) { - auto trustLevel = web::URLVerificationTrustLevel::kNone; - GURL dummy; - if (!page_url) { - page_url = &dummy; - } - *page_url = web_state->GetCurrentURL(&trustLevel); - return trustLevel == web::URLVerificationTrustLevel::kAbsolute; -} - } // namespace @implementation PasswordController { @@ -247,8 +221,6 @@ std::unique_ptr<PasswordManagerDriver> passwordManagerDriver_; std::unique_ptr<CredentialManager> credentialManager_; - JsPasswordManager* passwordJsManager_; - AccountSelectFillData fillData_; // The WebState this instance is observing. Will be null after @@ -272,10 +244,6 @@ // User credential waiting to be displayed in autosign-in snackbar, once tab // becomes active. std::unique_ptr<autofill::PasswordForm> pendingAutoSigninPasswordForm_; - - // Bridge to observe form activity in |webState_|. - std::unique_ptr<autofill::FormActivityObserverBridge> - formActivityObserverBridge_; } @synthesize baseViewController = _baseViewController; @@ -286,6 +254,8 @@ @synthesize notifyAutoSigninViewController = _notifyAutoSigninViewController; +@synthesize helper = helper_; + - (instancetype)initWithWebState:(web::WebState*)webState { self = [self initWithWebState:webState client:nullptr]; @@ -299,6 +269,11 @@ if (self) { DCHECK(webState); webState_ = webState; + webStateObserverBridge_ = + std::make_unique<web::WebStateObserverBridge>(self); + webState_->AddObserver(webStateObserverBridge_.get()); + helper_ = [[PasswordControllerHelper alloc] initWithWebState:webState + delegate:self]; if (passwordManagerClient) passwordManagerClient_ = std::move(passwordManagerClient); else @@ -306,39 +281,18 @@ passwordManager_.reset(new PasswordManager(passwordManagerClient_.get())); passwordManagerDriver_.reset(new IOSChromePasswordManagerDriver(self)); - webStateObserverBridge_ = - std::make_unique<web::WebStateObserverBridge>(self); - webState_->AddObserver(webStateObserverBridge_.get()); - formActivityObserverBridge_ = - std::make_unique<autofill::FormActivityObserverBridge>(webState_, self); - passwordJsManager_ = [[JsPasswordManager alloc] - initWithReceiver:webState_->GetJSInjectionReceiver()]; sentRequestToStore_ = NO; if (base::FeatureList::IsEnabled(features::kCredentialManager)) { credentialManager_ = std::make_unique<CredentialManager>( passwordManagerClient_.get(), webState_); } - - __weak PasswordController* weakSelf = self; - auto callback = base::BindRepeating( - ^bool(const base::DictionaryValue& JSON, const GURL& originURL, - bool interacting, bool isMainFrame) { - if (!isMainFrame) { - // Passwords is only supported on main frame. - return false; - } - // |originURL| and |isInteracting| aren't used. - return [weakSelf handleScriptCommand:JSON]; - }); - webState_->AddScriptCommandCallback(callback, kCommandPrefix); } return self; } - (void)dealloc { if (webState_) { - webState_->RemoveScriptCommandCallback(kCommandPrefix); webState_->RemoveObserver(webStateObserverBridge_.get()); } } @@ -360,6 +314,18 @@ return self; } +- (PasswordManagerClient*)passwordManagerClient { + return passwordManagerClient_.get(); +} + +- (PasswordManagerDriver*)passwordManagerDriver { + return passwordManagerDriver_.get(); +} + +- (PasswordManager*)passwordManager { + return passwordManager_.get(); +} + #pragma mark - #pragma mark PasswordFormFiller @@ -386,38 +352,6 @@ } #pragma mark - -#pragma mark FormActivityObserver - -- (void)webState:(web::WebState*)webState - submittedDocumentWithFormNamed:(const std::string&)formName - hasUserGesture:(BOOL)hasUserGesture - formInMainFrame:(BOOL)formInMainFrame { - DCHECK_EQ(webState_, webState); - __weak PasswordController* weakSelf = self; - // This code is racing against the new page loading and will not get the - // password form data if the page has changed. In most cases this code wins - // the race. - // TODO(crbug.com/418827): Fix this by passing in more data from the JS side. - id completionHandler = ^(BOOL found, const autofill::PasswordForm& form) { - PasswordController* strongSelf = weakSelf; - if (!strongSelf || !strongSelf->webState_ || !strongSelf.passwordManager) { - return; - } - if (formInMainFrame) { - strongSelf.passwordManager->OnPasswordFormSubmitted( - strongSelf.passwordManagerDriver, form); - } else { - // Show a save prompt immediately because for iframes it is very hard to - // figure out correctness of password forms submission. - strongSelf.passwordManager->OnPasswordFormSubmittedNoChecks( - strongSelf.passwordManagerDriver, form); - } - }; - [self extractSubmittedPasswordForm:formName - completionHandler:completionHandler]; -} - -#pragma mark - #pragma mark CRWWebStateObserver // If Tab was shown, and there is a pending PasswordForm, display autosign-in @@ -454,7 +388,7 @@ // Notify the password manager that the page loaded so it can clear its own // per-page state. - passwordManager_->DidNavigateMainFrame(); + self.passwordManager->DidNavigateMainFrame(); if (!webState->ContentIsHTML()) { // If the current page is not HTML, it does not contain any HTML forms. @@ -468,8 +402,6 @@ - (void)webStateDestroyed:(web::WebState*)webState { DCHECK_EQ(webState_, webState); if (webState_) { - formActivityObserverBridge_.reset(); - webState_->RemoveScriptCommandCallback(kCommandPrefix); webState_->RemoveObserver(webStateObserverBridge_.get()); webStateObserverBridge_.reset(); webState_ = nullptr; @@ -480,7 +412,7 @@ credentialManager_.reset(); } -#pragma mark - Private methods. +#pragma mark - Private methods - (void)findPasswordFormsWithCompletionHandler: (void (^)(const std::vector<autofill::PasswordForm>&))completionHandler { @@ -495,8 +427,8 @@ } __weak PasswordController* weakSelf = self; - [passwordJsManager_ findPasswordFormsWithCompletionHandler:^( - NSString* jsonString) { + [self.helper.jsPasswordManager findPasswordFormsWithCompletionHandler:^( + NSString* jsonString) { std::vector<autofill::PasswordForm> forms; [weakSelf getPasswordForms:&forms fromFormsJSON:jsonString pageURL:pageURL]; completionHandler(forms); @@ -531,54 +463,10 @@ } } -- (void)extractSubmittedPasswordForm:(const std::string&)formName - completionHandler: - (void (^)(BOOL found, - const autofill::PasswordForm& form)) - completionHandler { - DCHECK(completionHandler); - - if (!webState_) - return; - - GURL pageURL; - if (!GetPageURLAndCheckTrustLevel(webState_, &pageURL)) { - completionHandler(NO, autofill::PasswordForm()); - return; - } - - id extractSubmittedFormCompletionHandler = ^(NSString* jsonString) { - std::unique_ptr<base::Value> formValue = autofill::ParseJson(jsonString); - if (!formValue) { - completionHandler(NO, PasswordForm()); - return; - } - - FormData formData; - if (!autofill::ExtractFormData(*formValue, false, base::string16(), pageURL, - &formData)) { - completionHandler(NO, PasswordForm()); - return; - } - - std::unique_ptr<PasswordForm> form = - ParseFormData(formData, password_manager::FormParsingMode::SAVING); - if (!form) { - completionHandler(NO, PasswordForm()); - return; - } - - completionHandler(YES, *form); - }; - - [passwordJsManager_ extractForm:base::SysUTF8ToNSString(formName) - completionHandler:extractSubmittedFormCompletionHandler]; -} - - (void)didFinishPasswordFormExtraction: (const std::vector<autofill::PasswordForm>&)forms { // Do nothing if |self| has been detached. - if (!passwordManager_) + if (!self.passwordManager) return; if (!forms.empty()) { @@ -592,8 +480,8 @@ sentRequestToStore_ = YES; // Invoke the password manager callback to autofill password forms // on the loaded page. - passwordManager_->OnPasswordFormsParsed(passwordManagerDriver_.get(), - forms); + self.passwordManager->OnPasswordFormsParsed(self.passwordManagerDriver, + forms); } else { [self onNoSavedCredentials]; } @@ -603,8 +491,8 @@ // w/ a renderer, it is the renderer who calls OnPasswordFormsParsed() // and OnPasswordFormsRendered(). Bling has to improvised a bit on the // ordering of these two calls. - passwordManager_->OnPasswordFormsRendered(passwordManagerDriver_.get(), forms, - true); + self.passwordManager->OnPasswordFormsRendered(self.passwordManagerDriver, + forms, true); } #pragma mark - @@ -777,13 +665,14 @@ } // Send JSON over to the web view. - [passwordJsManager_ fillPasswordForm:SerializePasswordFormFillData(formData) - withUsername:base::SysUTF16ToNSString(username) - password:base::SysUTF16ToNSString(password) - completionHandler:^(BOOL result) { - if (completionHandler) - completionHandler(result); - }]; + [self.helper.jsPasswordManager + fillPasswordForm:SerializePasswordFormFillData(formData) + withUsername:base::SysUTF16ToNSString(username) + password:base::SysUTF16ToNSString(password) + completionHandler:^(BOOL result) { + if (completionHandler) + completionHandler(result); + }]; } - (void)fillPasswordForm:(const autofill::PasswordFormFillData&)formData @@ -817,7 +706,7 @@ - (void)fillPasswordFormWithFillData:(const password_manager::FillData&)fillData completionHandler:(void (^)(BOOL))completionHandler { // Send JSON over to the web view. - [passwordJsManager_ + [self.helper.jsPasswordManager fillPasswordForm:SerializeFillData(fillData) withUsername:base::SysUTF16ToNSString(fillData.username_value) password:base::SysUTF16ToNSString(fillData.password_value) @@ -827,52 +716,20 @@ }]; } -- (BOOL)handleScriptCommand:(const base::DictionaryValue&)JSONCommand { - std::string command; - if (!JSONCommand.GetString("command", &command)) - return NO; +#pragma mark - PasswordControllerHelperDelegate - if (command != "passwordForm.submitButtonClick") - return NO; - - GURL pageURL; - if (!GetPageURLAndCheckTrustLevel(webState_, &pageURL)) - return NO; - - FormData formData; - if (!autofill::ExtractFormData(JSONCommand, false, base::string16(), pageURL, - &formData)) { - return NO; - } - - std::unique_ptr<PasswordForm> form = - ParseFormData(formData, password_manager::FormParsingMode::SAVING); - if (!form) - return NO; - - if (webState_) { +- (void)helper:(PasswordControllerHelper*)helper + didSubmitForm:(const PasswordForm&)form + inMainFrame:(BOOL)inMainFrame { + if (inMainFrame) { self.passwordManager->OnPasswordFormSubmitted(self.passwordManagerDriver, - *form); - return YES; + form); + } else { + // Show a save prompt immediately because for iframes it is very hard to + // figure out correctness of password forms submission. + self.passwordManager->OnPasswordFormSubmittedNoChecks( + self.passwordManagerDriver, form); } - - return NO; -} - -- (PasswordManagerClient*)passwordManagerClient { - return passwordManagerClient_.get(); -} - -- (PasswordManagerDriver*)passwordManagerDriver { - return passwordManagerDriver_.get(); -} - -- (PasswordManager*)passwordManager { - return passwordManager_.get(); -} - -- (JsPasswordManager*)passwordJsManager { - return passwordJsManager_; } #pragma mark - Private methods
diff --git a/ios/chrome/browser/passwords/password_controller_unittest.mm b/ios/chrome/browser/passwords/password_controller_unittest.mm index 0ecf65db..de5943c 100644 --- a/ios/chrome/browser/passwords/password_controller_unittest.mm +++ b/ios/chrome/browser/passwords/password_controller_unittest.mm
@@ -23,6 +23,7 @@ #include "components/password_manager/core/browser/stub_password_manager_client.h" #include "components/password_manager/core/common/password_manager_pref_names.h" #import "components/password_manager/ios/js_password_manager.h" +#import "components/password_manager/ios/password_controller_helper.h" #include "components/password_manager/ios/test_helpers.h" #include "components/prefs/pref_registry_simple.h" #include "components/prefs/testing_pref_service.h" @@ -149,11 +150,6 @@ - (void)findPasswordFormsWithCompletionHandler: (void (^)(const std::vector<PasswordForm>&))completionHandler; -- (void)extractSubmittedPasswordForm:(const std::string&)formName - completionHandler: - (void (^)(BOOL found, - const PasswordForm& form))completionHandler; - - (void)fillPasswordForm:(const PasswordFormFillData&)formData completionHandler:(void (^)(BOOL))completionHandler; @@ -163,11 +159,21 @@ fromDictionary:(const base::DictionaryValue*)dictionary pageURL:(const GURL&)pageLocation; -// Provides access to JavaScript Manager for testing with mocks. -@property(readonly) JsPasswordManager* passwordJsManager; +// Provides access to common helper logic for testing with mocks. +@property(readonly) PasswordControllerHelper* helper; @end +@interface PasswordControllerHelper (Testing) + +- (void)extractSubmittedPasswordForm:(const std::string&)formName + completionHandler: + (void (^)(BOOL found, + const PasswordForm& form))completionHandler; +// Provides access to JavaScript Manager for testing with mocks. +@property(readonly) JsPasswordManager* jsPasswordManager; +@end + // Real FormSuggestionController is wrapped to register the addition of // suggestions. @interface PasswordsTestSuggestionController : FormSuggestionController @@ -247,7 +253,7 @@ // |failure_count| reaches |target_failure_count|, stop the partial mock // and let the original JavaScript manager execute. void SetFillPasswordFormFailureCount(int target_failure_count) { - id original_manager = [passwordController_ passwordJsManager]; + id original_manager = passwordController_.helper.jsPasswordManager; OCPartialMockObject* failing_manager = [OCMockObject partialMockForObject:original_manager]; __block int failure_count = 0; @@ -482,7 +488,7 @@ form.username_element); } }; - [passwordController_ + [passwordController_.helper extractSubmittedPasswordForm:FormName(data.number_of_forms_to_submit) completionHandler:completion_handler]; EXPECT_TRUE(
diff --git a/ios/chrome/browser/ui/settings/autofill_credit_card_collection_view_controller.mm b/ios/chrome/browser/ui/settings/autofill_credit_card_collection_view_controller.mm index a8a6c3a8..ffca254 100644 --- a/ios/chrome/browser/ui/settings/autofill_credit_card_collection_view_controller.mm +++ b/ios/chrome/browser/ui/settings/autofill_credit_card_collection_view_controller.mm
@@ -16,14 +16,19 @@ #include "ios/chrome/browser/application_context.h" #include "ios/chrome/browser/autofill/personal_data_manager_factory.h" #include "ios/chrome/browser/browser_state/chrome_browser_state.h" +#include "ios/chrome/browser/experimental_flags.h" #import "ios/chrome/browser/ui/collection_view/cells/MDCCollectionViewCell+Chrome.h" +#include "ios/chrome/browser/ui/collection_view/cells/collection_view_cell_constants.h" +#import "ios/chrome/browser/ui/collection_view/cells/collection_view_text_item.h" #import "ios/chrome/browser/ui/collection_view/collection_view_model.h" #import "ios/chrome/browser/ui/settings/autofill_credit_card_edit_collection_view_controller.h" #import "ios/chrome/browser/ui/settings/cells/autofill_data_item.h" #import "ios/chrome/browser/ui/settings/cells/settings_switch_item.h" #import "ios/chrome/browser/ui/settings/cells/settings_text_item.h" +#import "ios/chrome/browser/ui/uikit_ui_util.h" #include "ios/chrome/grit/ios_strings.h" #import "ios/third_party/material_components_ios/src/components/Palettes/src/MaterialPalettes.h" +#import "ios/third_party/material_components_ios/src/components/Typography/src/MaterialTypography.h" #include "ui/base/l10n/l10n_util.h" #if !defined(__has_feature) || !__has_feature(objc_arc) @@ -34,11 +39,13 @@ typedef NS_ENUM(NSInteger, SectionIdentifier) { SectionIdentifierSwitches = kSectionIdentifierEnumZero, + SectionIdentifierSubtitle, SectionIdentifierCards, }; typedef NS_ENUM(NSInteger, ItemType) { ItemTypeAutofillCardSwitch = kItemTypeEnumZero, + ItemTypeAutofillCardSwitchSubtitle, ItemTypeCard, ItemTypeHeader, }; @@ -106,6 +113,10 @@ [model addItem:[self cardSwitchItem] toSectionWithIdentifier:SectionIdentifierSwitches]; + [model addSectionWithIdentifier:SectionIdentifierSubtitle]; + [model addItem:[self cardSwitchSubtitleItem] + toSectionWithIdentifier:SectionIdentifierSubtitle]; + [self populateCardSection]; } @@ -138,6 +149,22 @@ return switchItem; } +- (CollectionViewItem*)cardSwitchSubtitleItem { + CollectionViewTextItem* textItem = [[CollectionViewTextItem alloc] + initWithType:ItemTypeAutofillCardSwitchSubtitle]; + textItem.text = + l10n_util::GetNSString(IDS_AUTOFILL_ENABLE_CREDIT_CARDS_TOGGLE_SUBLABEL); + if (experimental_flags::IsSettingsUIRebootEnabled()) { + textItem.textFont = [UIFont systemFontOfSize:kUIKitMultilineDetailFontSize]; + textItem.textColor = UIColorFromRGB(kUIKitMultilineDetailTextColor); + } else { + textItem.textFont = [[MDCTypography fontLoader] regularFontOfSize:14]; + textItem.textColor = [[MDCPalette greyPalette] tint500]; + } + textItem.numberOfTextLines = 0; + return textItem; +} + - (CollectionViewItem*)cardSectionHeader { SettingsTextItem* header = [self genericHeader]; header.text = l10n_util::GetNSString(IDS_AUTOFILL_PAYMENT_METHODS); @@ -259,8 +286,17 @@ - (BOOL)collectionView:(UICollectionView*)collectionView hidesInkViewAtIndexPath:(NSIndexPath*)indexPath { - NSInteger type = [self.collectionViewModel itemTypeForIndexPath:indexPath]; - return type == ItemTypeAutofillCardSwitch; + NSInteger sectionIdentifier = + [self.collectionViewModel sectionIdentifierForSection:indexPath.section]; + return sectionIdentifier == SectionIdentifierSwitches || + sectionIdentifier == SectionIdentifierSubtitle; +} + +- (BOOL)collectionView:(UICollectionView*)collectionView + shouldHideItemBackgroundAtIndexPath:(NSIndexPath*)indexPath { + NSInteger sectionIdentifier = + [self.collectionViewModel sectionIdentifierForSection:indexPath.section]; + return sectionIdentifier == SectionIdentifierSubtitle; } #pragma mark - UICollectionViewDelegate
diff --git a/ios/chrome/browser/ui/settings/autofill_credit_card_collection_view_controller_unittest.mm b/ios/chrome/browser/ui/settings/autofill_credit_card_collection_view_controller_unittest.mm index 3072f85..9aa05b9 100644 --- a/ios/chrome/browser/ui/settings/autofill_credit_card_collection_view_controller_unittest.mm +++ b/ios/chrome/browser/ui/settings/autofill_credit_card_collection_view_controller_unittest.mm
@@ -65,15 +65,18 @@ std::unique_ptr<TestChromeBrowserState> chrome_browser_state_; }; -// Default test case of no addresses or credit cards. +// Default test case of no credit cards. TEST_F(AutofillCreditCardCollectionViewControllerTest, TestInitialization) { CreateController(); CheckController(); - // Expect one header section. - EXPECT_EQ(1, NumberOfSections()); + // Expect one header section and one subtitle section. + EXPECT_EQ(2, NumberOfSections()); // Expect header section to contain one row (the credit card Autofill toggle). EXPECT_EQ(1, NumberOfItemsInSection(0)); + // Expect subtitle section to contain one row (the credit card Autofill toggle + // subtitle). + EXPECT_EQ(1, NumberOfItemsInSection(1)); } // Adding a single credit card results in a credit card section. @@ -82,10 +85,10 @@ CreateController(); CheckController(); - // Expect two sections (header and credit cards section). - EXPECT_EQ(2, NumberOfSections()); - // Expect address section to contain one row (the credit card itself). - EXPECT_EQ(1, NumberOfItemsInSection(1)); + // Expect three sections (header, subtitle, and credit card section). + EXPECT_EQ(3, NumberOfSections()); + // Expect credit card section to contain one row (the credit card itself). + EXPECT_EQ(1, NumberOfItemsInSection(2)); } // Deleting the only credit card results in item deletion and section deletion. @@ -95,10 +98,10 @@ CreateController(); CheckController(); - // Expect two sections (header and credit cards section). - EXPECT_EQ(2, NumberOfSections()); - // Expect address section to contain one row (the credit card itself). - EXPECT_EQ(1, NumberOfItemsInSection(1)); + // Expect three sections (header, subtitle, and credit card section). + EXPECT_EQ(3, NumberOfSections()); + // Expect credit card section to contain one row (the credit card itself). + EXPECT_EQ(1, NumberOfItemsInSection(2)); AutofillCreditCardCollectionViewController* view_controller = base::mac::ObjCCastStrict<AutofillCreditCardCollectionViewController>( @@ -126,14 +129,14 @@ // This call cause a modification of the PersonalDataManager, so wait until // the asynchronous task complete in addition to waiting for the UI update. - delete_item_with_wait(1, 0); + delete_item_with_wait(2, 0); observer.Wait(); // Wait for completion of the asynchronous operation. // Exit 'edit' mode. [view_controller editButtonPressed]; - // Expect one header section only. - EXPECT_EQ(1, NumberOfSections()); + // Expect credit card section to have been removed. + EXPECT_EQ(2, NumberOfSections()); } } // namespace
diff --git a/ios/chrome/browser/ui/settings/autofill_profile_collection_view_controller.mm b/ios/chrome/browser/ui/settings/autofill_profile_collection_view_controller.mm index 2ad7f63e..80c524b 100644 --- a/ios/chrome/browser/ui/settings/autofill_profile_collection_view_controller.mm +++ b/ios/chrome/browser/ui/settings/autofill_profile_collection_view_controller.mm
@@ -15,14 +15,19 @@ #include "ios/chrome/browser/application_context.h" #include "ios/chrome/browser/autofill/personal_data_manager_factory.h" #include "ios/chrome/browser/browser_state/chrome_browser_state.h" +#include "ios/chrome/browser/experimental_flags.h" #import "ios/chrome/browser/ui/collection_view/cells/MDCCollectionViewCell+Chrome.h" +#include "ios/chrome/browser/ui/collection_view/cells/collection_view_cell_constants.h" +#import "ios/chrome/browser/ui/collection_view/cells/collection_view_text_item.h" #import "ios/chrome/browser/ui/collection_view/collection_view_model.h" #import "ios/chrome/browser/ui/settings/autofill_profile_edit_collection_view_controller.h" #import "ios/chrome/browser/ui/settings/cells/autofill_data_item.h" #import "ios/chrome/browser/ui/settings/cells/settings_switch_item.h" #import "ios/chrome/browser/ui/settings/cells/settings_text_item.h" +#import "ios/chrome/browser/ui/uikit_ui_util.h" #include "ios/chrome/grit/ios_strings.h" #import "ios/third_party/material_components_ios/src/components/Palettes/src/MaterialPalettes.h" +#import "ios/third_party/material_components_ios/src/components/Typography/src/MaterialTypography.h" #include "ui/base/l10n/l10n_util.h" #if !defined(__has_feature) || !__has_feature(objc_arc) @@ -33,11 +38,13 @@ typedef NS_ENUM(NSInteger, SectionIdentifier) { SectionIdentifierSwitches = kSectionIdentifierEnumZero, + SectionIdentifierSubtitle, SectionIdentifierProfiles, }; typedef NS_ENUM(NSInteger, ItemType) { ItemTypeAutofillAddressSwitch = kItemTypeEnumZero, + ItemTypeAutofillAddressSwitchSubtitle, ItemTypeAddress, ItemTypeHeader, }; @@ -75,7 +82,7 @@ [super initWithLayout:layout style:CollectionViewControllerStyleAppBar]; if (self) { self.collectionViewAccessibilityIdentifier = @"kAutofillCollectionViewId"; - self.title = l10n_util::GetNSString(IDS_AUTOFILL_ADDRESSES); + self.title = l10n_util::GetNSString(IDS_AUTOFILL_ADDRESSES_SETTINGS_TITLE); self.shouldHideDoneButton = YES; _browserState = browserState; _personalDataManager = @@ -105,6 +112,10 @@ [model addItem:[self addressSwitchItem] toSectionWithIdentifier:SectionIdentifierSwitches]; + [model addSectionWithIdentifier:SectionIdentifierSubtitle]; + [model addItem:[self addressSwitchSubtitleItem] + toSectionWithIdentifier:SectionIdentifierSubtitle]; + [self populateProfileSection]; } @@ -137,6 +148,22 @@ return switchItem; } +- (CollectionViewItem*)addressSwitchSubtitleItem { + CollectionViewTextItem* textItem = [[CollectionViewTextItem alloc] + initWithType:ItemTypeAutofillAddressSwitchSubtitle]; + textItem.text = + l10n_util::GetNSString(IDS_AUTOFILL_ENABLE_PROFILES_TOGGLE_SUBLABEL); + if (experimental_flags::IsSettingsUIRebootEnabled()) { + textItem.textFont = [UIFont systemFontOfSize:kUIKitMultilineDetailFontSize]; + textItem.textColor = UIColorFromRGB(kUIKitMultilineDetailTextColor); + } else { + textItem.textFont = [[MDCTypography fontLoader] regularFontOfSize:14]; + textItem.textColor = [[MDCPalette greyPalette] tint500]; + } + textItem.numberOfTextLines = 0; + return textItem; +} + - (CollectionViewItem*)profileSectionHeader { SettingsTextItem* header = [self genericHeader]; header.text = l10n_util::GetNSString(IDS_AUTOFILL_ADDRESSES); @@ -266,8 +293,17 @@ - (BOOL)collectionView:(UICollectionView*)collectionView hidesInkViewAtIndexPath:(NSIndexPath*)indexPath { - NSInteger type = [self.collectionViewModel itemTypeForIndexPath:indexPath]; - return type == ItemTypeAutofillAddressSwitch; + NSInteger sectionIdentifier = + [self.collectionViewModel sectionIdentifierForSection:indexPath.section]; + return sectionIdentifier == SectionIdentifierSwitches || + sectionIdentifier == SectionIdentifierSubtitle; +} + +- (BOOL)collectionView:(UICollectionView*)collectionView + shouldHideItemBackgroundAtIndexPath:(NSIndexPath*)indexPath { + NSInteger sectionIdentifier = + [self.collectionViewModel sectionIdentifierForSection:indexPath.section]; + return sectionIdentifier == SectionIdentifierSubtitle; } #pragma mark - UICollectionViewDelegate
diff --git a/ios/chrome/browser/ui/settings/autofill_profile_collection_view_controller_unittest.mm b/ios/chrome/browser/ui/settings/autofill_profile_collection_view_controller_unittest.mm index 59166596..b18fb53 100644 --- a/ios/chrome/browser/ui/settings/autofill_profile_collection_view_controller_unittest.mm +++ b/ios/chrome/browser/ui/settings/autofill_profile_collection_view_controller_unittest.mm
@@ -69,10 +69,13 @@ CreateController(); CheckController(); - // Expect one header section. - EXPECT_EQ(1, NumberOfSections()); + // Expect one header section and one subtitle section. + EXPECT_EQ(2, NumberOfSections()); // Expect header section to contain one row (the address Autofill toggle). EXPECT_EQ(1, NumberOfItemsInSection(0)); + // Expect subtitle section to contain one row (the address Autofill toggle + // subtitle). + EXPECT_EQ(1, NumberOfItemsInSection(1)); } // Adding a single address results in an address section. @@ -81,10 +84,10 @@ CreateController(); CheckController(); - // Expect two sections (header and addresses section). - EXPECT_EQ(2, NumberOfSections()); + // Expect three sections (header, subtitle, and addresses section). + EXPECT_EQ(3, NumberOfSections()); // Expect address section to contain one row (the address itself). - EXPECT_EQ(1, NumberOfItemsInSection(1)); + EXPECT_EQ(1, NumberOfItemsInSection(2)); } // Deleting the only profile results in item deletion and section deletion. @@ -93,10 +96,10 @@ CreateController(); CheckController(); - // Expect two sections (header and addresses section). - EXPECT_EQ(2, NumberOfSections()); + // Expect three sections (header, subtitle, and addresses section). + EXPECT_EQ(3, NumberOfSections()); // Expect address section to contain one row (the address itself). - EXPECT_EQ(1, NumberOfItemsInSection(1)); + EXPECT_EQ(1, NumberOfItemsInSection(2)); AutofillProfileCollectionViewController* view_controller = base::mac::ObjCCastStrict<AutofillProfileCollectionViewController>( @@ -124,14 +127,14 @@ // This call cause a modification of the PersonalDataManager, so wait until // the asynchronous task complete in addition to waiting for the UI update. - delete_item_with_wait(1, 0); + delete_item_with_wait(2, 0); observer.Wait(); // Wait for completion of the asynchronous operation. // Exit 'edit' mode. [view_controller editButtonPressed]; - // Expect one header section only. - EXPECT_EQ(1, NumberOfSections()); + // Expect address section to have been removed. + EXPECT_EQ(2, NumberOfSections()); } } // namespace
diff --git a/ios/chrome/browser/ui/settings/autofill_profile_settings_egtest.mm b/ios/chrome/browser/ui/settings/autofill_profile_settings_egtest.mm index 71121f91..9d21872 100644 --- a/ios/chrome/browser/ui/settings/autofill_profile_settings_egtest.mm +++ b/ios/chrome/browser/ui/settings/autofill_profile_settings_egtest.mm
@@ -131,9 +131,9 @@ // Helper to open the settings page for Autofill profiles. - (void)openAutofillProfilesSettings { [ChromeEarlGreyUI openSettingsMenu]; - [[EarlGrey selectElementWithMatcher:ButtonWithAccessibilityLabel( - l10n_util::GetNSString( - IDS_AUTOFILL_ADDRESSES))] + id<GREYMatcher> addressesButton = + ButtonWithAccessibilityLabelId(IDS_AUTOFILL_ADDRESSES_SETTINGS_TITLE); + [[EarlGrey selectElementWithMatcher:addressesButton] performAction:grey_tap()]; }
diff --git a/ios/chrome/browser/ui/settings/settings_collection_view_controller.mm b/ios/chrome/browser/ui/settings/settings_collection_view_controller.mm index 405df2d..16bf078 100644 --- a/ios/chrome/browser/ui/settings/settings_collection_view_controller.mm +++ b/ios/chrome/browser/ui/settings/settings_collection_view_controller.mm
@@ -592,7 +592,8 @@ : l10n_util::GetNSString(IDS_IOS_SETTING_OFF); _autoFillProfileDetailItem = [self detailItemWithType:ItemTypeAutofillProfile - text:l10n_util::GetNSString(IDS_AUTOFILL_ADDRESSES) + text:l10n_util::GetNSString( + IDS_AUTOFILL_ADDRESSES_SETTINGS_TITLE) detailText:detailText iconImageName:kSettingsAutofillProfileImageName];
diff --git a/ios/chrome/browser/ui/settings/settings_egtest.mm b/ios/chrome/browser/ui/settings/settings_egtest.mm index 2199806..7b4f107 100644 --- a/ios/chrome/browser/ui/settings/settings_egtest.mm +++ b/ios/chrome/browser/ui/settings/settings_egtest.mm
@@ -103,7 +103,7 @@ } // Matcher for the addresses cell on the main Settings screen. id<GREYMatcher> AddressesButton() { - return ButtonWithAccessibilityLabelId(IDS_AUTOFILL_ADDRESSES); + return ButtonWithAccessibilityLabelId(IDS_AUTOFILL_ADDRESSES_SETTINGS_TITLE); } // Matcher for the Google Chrome cell on the main Settings screen. id<GREYMatcher> GoogleChromeButton() {
diff --git a/ios/web_view/test/navigation_delegate_inttest.mm b/ios/web_view/test/navigation_delegate_inttest.mm index 46669f2..215100e 100644 --- a/ios/web_view/test/navigation_delegate_inttest.mm +++ b/ios/web_view/test/navigation_delegate_inttest.mm
@@ -22,25 +22,32 @@ // Tests CWVNavigationDelegate. class NavigationDelegateTest : public ios_web_view::WebViewInttestBase { public: - void SetUp() override { - ASSERT_TRUE(test_server_->Start()); - url_with_content_ = - net::NSURLWithGURL(GetUrlForPageWithTitleAndBody("Title", "Body")); - url_with_error_ = net::NSURLWithGURL(test_server_->GetURL("/close-socket")); - - mock_delegate_ = OCMStrictProtocolMock(@protocol(CWVNavigationDelegate)); + NavigationDelegateTest() + : mock_delegate_( + OCMStrictProtocolMock(@protocol(CWVNavigationDelegate))) { [(id)mock_delegate_ setExpectationOrderMatters:YES]; web_view_.navigationDelegate = mock_delegate_; } + void SetUp() override { + ios_web_view::WebViewInttestBase::SetUp(); + ASSERT_TRUE(test_server_->Start()); + } + + NSURL* GetEchoURL() { + return net::NSURLWithGURL(test_server_->GetURL("/echo")); + } + + NSURL* GetCloseSocketURL() { + return net::NSURLWithGURL(test_server_->GetURL("/close-socket")); + } + id ArgWithURL(NSURL* url) { return [OCMArg checkWithBlock:^(id object) { return [[object URL] isEqual:url]; }]; } - NSURL* url_with_content_; - NSURL* url_with_error_; id<CWVNavigationDelegate> mock_delegate_; }; @@ -48,25 +55,25 @@ TEST_F(NavigationDelegateTest, RequestSucceeds) { // A request made with -loadRequest: has type CWVNavigationTypeClientRedirect. OCMExpect([mock_delegate_ webView:web_view_ - shouldStartLoadWithRequest:ArgWithURL(url_with_content_) + shouldStartLoadWithRequest:ArgWithURL(GetEchoURL()) navigationType:CWVNavigationTypeClientRedirect]) .andReturn(YES); OCMExpect([mock_delegate_ webViewDidStartProvisionalNavigation:web_view_]); OCMExpect([mock_delegate_ webView:web_view_ - shouldContinueLoadWithResponse:ArgWithURL(url_with_content_) + shouldContinueLoadWithResponse:ArgWithURL(GetEchoURL()) forMainFrame:YES]) .andReturn(YES); OCMExpect([mock_delegate_ webViewDidCommitNavigation:web_view_]); OCMExpect([mock_delegate_ webViewDidFinishNavigation:web_view_]); - ASSERT_TRUE(test::LoadUrl(web_view_, url_with_content_)); + ASSERT_TRUE(test::LoadUrl(web_view_, GetEchoURL())); [(id)mock_delegate_ verify]; } // Tests that expected delegate methods are called for a failed request. TEST_F(NavigationDelegateTest, RequestFails) { OCMExpect([mock_delegate_ webView:web_view_ - shouldStartLoadWithRequest:ArgWithURL(url_with_error_) + shouldStartLoadWithRequest:ArgWithURL(GetCloseSocketURL()) navigationType:CWVNavigationTypeClientRedirect]) .andReturn(YES); OCMExpect([mock_delegate_ webViewDidStartProvisionalNavigation:web_view_]); @@ -76,7 +83,7 @@ // -webViewDidCommitNavigation: is called one more time for failures. OCMExpect([mock_delegate_ webViewDidCommitNavigation:web_view_]); - ASSERT_TRUE(test::LoadUrl(web_view_, url_with_error_)); + ASSERT_TRUE(test::LoadUrl(web_view_, GetCloseSocketURL())); [(id)mock_delegate_ verify]; } @@ -84,11 +91,11 @@ // when -shouldStartLoadWithRequest:navigationType: returns NO. TEST_F(NavigationDelegateTest, CancelRequest) { OCMExpect([mock_delegate_ webView:web_view_ - shouldStartLoadWithRequest:ArgWithURL(url_with_content_) + shouldStartLoadWithRequest:ArgWithURL(GetEchoURL()) navigationType:CWVNavigationTypeClientRedirect]) .andReturn(NO); - ASSERT_TRUE(test::LoadUrl(web_view_, url_with_content_)); + ASSERT_TRUE(test::LoadUrl(web_view_, GetEchoURL())); [(id)mock_delegate_ verify]; } @@ -96,16 +103,16 @@ // when -shouldContinueLoadWithResponse:forMainFrame: returns NO. TEST_F(NavigationDelegateTest, CancelResponse) { OCMExpect([mock_delegate_ webView:web_view_ - shouldStartLoadWithRequest:ArgWithURL(url_with_content_) + shouldStartLoadWithRequest:ArgWithURL(GetEchoURL()) navigationType:CWVNavigationTypeClientRedirect]) .andReturn(YES); OCMExpect([mock_delegate_ webViewDidStartProvisionalNavigation:web_view_]); OCMExpect([mock_delegate_ webView:web_view_ - shouldContinueLoadWithResponse:ArgWithURL(url_with_content_) + shouldContinueLoadWithResponse:ArgWithURL(GetEchoURL()) forMainFrame:YES]) .andReturn(NO); - ASSERT_TRUE(test::LoadUrl(web_view_, url_with_content_)); + ASSERT_TRUE(test::LoadUrl(web_view_, GetEchoURL())); [(id)mock_delegate_ verify]; }
diff --git a/ios/web_view/test/ui_delegate_inttest.mm b/ios/web_view/test/ui_delegate_inttest.mm index 6cb59550..7a36e63 100644 --- a/ios/web_view/test/ui_delegate_inttest.mm +++ b/ios/web_view/test/ui_delegate_inttest.mm
@@ -25,16 +25,20 @@ // Tests CWVUIDelegate. class UIDelegateTest : public ios_web_view::WebViewInttestBase { public: - void SetUp() override { - mock_delegate_ = OCMProtocolMock(@protocol(CWVUIDelegate)); + UIDelegateTest() : mock_delegate_(OCMProtocolMock(@protocol(CWVUIDelegate))) { web_view_.UIDelegate = mock_delegate_; + } + void SetUp() override { + ios_web_view::WebViewInttestBase::SetUp(); ASSERT_TRUE(test_server_->Start()); - url_ = net::NSURLWithGURL(GetUrlForPageWithTitleAndBody("Title", "Body")); + } + + NSURL* GetEchoURL() { + return net::NSURLWithGURL(test_server_->GetURL("/echo")); } id<CWVUIDelegate> mock_delegate_; - NSURL* url_; }; // Tests -webView:createWebViewWithConfiguration:forNavigationAction: @@ -48,7 +52,7 @@ createWebViewWithConfiguration:web_view_.configuration forNavigationAction:expected_navigation_action]); - ASSERT_TRUE(test::LoadUrl(web_view_, url_)); + ASSERT_TRUE(test::LoadUrl(web_view_, GetEchoURL())); NSError* error = nil; EXPECT_NE(nil, test::EvaluateJavaScript( web_view_, @"open('http://example.com/')", &error)); @@ -67,10 +71,10 @@ OCMExpect([mock_delegate_ webView:web_view_ runJavaScriptAlertPanelWithMessage:@"message" - pageURL:url_ + pageURL:GetEchoURL() completionHandler:mock_completion_handler]); - ASSERT_TRUE(test::LoadUrl(web_view_, url_)); + ASSERT_TRUE(test::LoadUrl(web_view_, GetEchoURL())); NSError* error = nil; test::EvaluateJavaScript(web_view_, @"alert('message')", &error); EXPECT_EQ(nil, error); @@ -89,10 +93,10 @@ OCMExpect([mock_delegate_ webView:web_view_ runJavaScriptConfirmPanelWithMessage:@"message" - pageURL:url_ + pageURL:GetEchoURL() completionHandler:mock_completion_handler]); - ASSERT_TRUE(test::LoadUrl(web_view_, url_)); + ASSERT_TRUE(test::LoadUrl(web_view_, GetEchoURL())); NSError* error = nil; EXPECT_NSEQ(@(YES), test::EvaluateJavaScript(web_view_, @"confirm('message')", &error)); @@ -113,10 +117,10 @@ OCMExpect([mock_delegate_ webView:web_view_ runJavaScriptTextInputPanelWithPrompt:@"prompt" defaultText:@"default" - pageURL:url_ + pageURL:GetEchoURL() completionHandler:mock_completion_handler]); - ASSERT_TRUE(test::LoadUrl(web_view_, url_)); + ASSERT_TRUE(test::LoadUrl(web_view_, GetEchoURL())); NSError* error = nil; EXPECT_NSEQ(@"input", test::EvaluateJavaScript( web_view_, @"prompt('prompt', 'default')", &error));
diff --git a/ios/web_view/test/web_view_inttest.mm b/ios/web_view/test/web_view_inttest.mm index 06f78c44..bc7ea3c9 100644 --- a/ios/web_view/test/web_view_inttest.mm +++ b/ios/web_view/test/web_view_inttest.mm
@@ -29,7 +29,7 @@ // Note that some methods are covered by other tests in this directory. class WebViewTest : public ios_web_view::WebViewInttestBase { public: - void SetUp() override { + WebViewTest() { test_server_->RegisterRequestHandler(base::BindRepeating( &WebViewTest::CaptureRequestHandler, base::Unretained(this))); }
diff --git a/media/base/decoder_buffer.cc b/media/base/decoder_buffer.cc index a6fef55..456d2ba5 100644 --- a/media/base/decoder_buffer.cc +++ b/media/base/decoder_buffer.cc
@@ -51,7 +51,13 @@ shm_(std::move(shm)), is_key_frame_(false) {} -DecoderBuffer::~DecoderBuffer() = default; +DecoderBuffer::~DecoderBuffer() { + // TODO(crbug.com/794740). As a lot of the crashes have |side_data_size_| + // == 0 yet |side_data| is not null, check that here hoping to get better + // minidumps. This check verifies that size == 0 and |side_data_| is null, + // or size != 0 and |side_data_| not null. + CHECK_EQ(!!side_data_size_, !!side_data_); +} void DecoderBuffer::Initialize() { data_.reset(AllocateFFmpegSafeBlock(size_));
diff --git a/media/capture/content/android/screen_capture_machine_android.cc b/media/capture/content/android/screen_capture_machine_android.cc index be83b13..7064e3a4 100644 --- a/media/capture/content/android/screen_capture_machine_android.cc +++ b/media/capture/content/android/screen_capture_machine_android.cc
@@ -191,14 +191,20 @@ const JavaRef<jobject>& obj, jboolean result) { if (!result) { - oracle_proxy_->ReportError(FROM_HERE, "The user denied screen capture"); + oracle_proxy_->ReportError( + media::VideoCaptureError:: + kAndroidScreenCaptureTheUserDeniedScreenCapture, + FROM_HERE, "The user denied screen capture"); return; } if (Java_ScreenCapture_startCapture(env, obj)) oracle_proxy_->ReportStarted(); else - oracle_proxy_->ReportError(FROM_HERE, "Failed to start Screen Capture"); + oracle_proxy_->ReportError( + media::VideoCaptureError:: + kAndroidScreenCaptureFailedToStartScreenCapture, + FROM_HERE, "Failed to start Screen Capture"); } void ScreenCaptureMachineAndroid::OnOrientationChange(
diff --git a/media/capture/content/android/thread_safe_capture_oracle.cc b/media/capture/content/android/thread_safe_capture_oracle.cc index ef8732f..2f4ec28 100644 --- a/media/capture/content/android/thread_safe_capture_oracle.cc +++ b/media/capture/content/android/thread_safe_capture_oracle.cc
@@ -186,11 +186,12 @@ client_.reset(); } -void ThreadSafeCaptureOracle::ReportError(const base::Location& from_here, +void ThreadSafeCaptureOracle::ReportError(media::VideoCaptureError error, + const base::Location& from_here, const std::string& reason) { base::AutoLock guard(lock_); if (client_) - client_->OnError(from_here, reason); + client_->OnError(error, from_here, reason); } void ThreadSafeCaptureOracle::ReportStarted() {
diff --git a/media/capture/content/android/thread_safe_capture_oracle.h b/media/capture/content/android/thread_safe_capture_oracle.h index 65e62f66..2a2f38b 100644 --- a/media/capture/content/android/thread_safe_capture_oracle.h +++ b/media/capture/content/android/thread_safe_capture_oracle.h
@@ -71,7 +71,9 @@ void Stop(); // Signal an error to the client. - void ReportError(const base::Location& from_here, const std::string& reason); + void ReportError(media::VideoCaptureError error, + const base::Location& from_here, + const std::string& reason); // Signal device started to the client. void ReportStarted();
diff --git a/media/capture/mojom/video_capture_types.mojom b/media/capture/mojom/video_capture_types.mojom index a0d5b030..e538bf3 100644 --- a/media/capture/mojom/video_capture_types.mojom +++ b/media/capture/mojom/video_capture_types.mojom
@@ -90,6 +90,124 @@ kMailboxHolder }; +enum VideoCaptureError { + kNone, + kVideoCaptureControllerInvalidOrUnsupportedVideoCaptureParametersRequested, + kVideoCaptureControllerIsAlreadyInErrorState, + kVideoCaptureManagerDeviceConnectionLost, + kFrameSinkVideoCaptureDeviceAleradyEndedOnFatalError, + kFrameSinkVideoCaptureDeviceEncounteredFatalError, + kV4L2FailedToOpenV4L2DeviceDriverFile, + kV4L2ThisIsNotAV4L2VideoCaptureDevice, + kV4L2FailedToFindASupportedCameraFormat, + kV4L2FailedToSetVideoCaptureFormat, + kV4L2UnsupportedPixelFormat, + kV4L2FailedToSetCameraFramerate, + kV4L2ErrorRequestingMmapBuffers, + kV4L2AllocateBufferFailed, + kV4L2VidiocStreamonFailed, + kV4L2VidiocStreamoffFailed, + kV4L2FailedToVidiocReqbufsWithCount0, + kV4L2PollFailed, + kV4L2MultipleContinuousTimeoutsWhileReadPolling, + kV4L2FailedToDequeueCaptureBuffer, + kV4L2FailedToEnqueueCaptureBuffer, + kSingleClientVideoCaptureHostLostConnectionToDevice, + kSingleClientVideoCaptureDeviceLaunchAborted, + kDesktopCaptureDeviceWebrtcDesktopCapturerHasFailed, + kFileVideoCaptureDeviceCouldNotOpenVideoFile, + kDeviceCaptureLinuxFailedToCreateVideoCaptureDelegate, + kErrorFakeDeviceIntentionallyEmittingErrorEvent, + kDeviceClientTooManyFramesDropped, + kDeviceClientTooManyFramesDroppedY16, + kDeviceMediaToMojoAdapterEncounteredUnsupportedBufferType, + kVideoCaptureManagerProcessDeviceStartQueueDeviceInfoNotFound, + kInProcessDeviceLauncherFailedToCreateDeviceInstance, + kServiceDeviceLauncherLostConnectionToDeviceFactoryDuringDeviceStart, + kServiceDeviceLauncherServiceRespondedWithDeviceNotFound, + kServiceDeviceLauncherConnectionLostWhileWaitingForCallback, + kIntentionalErrorRaisedByUnitTest, + kCrosHalV3FailedToStartDeviceThread, + kCrosHalV3DeviceDelegateMojoConnectionError, + kCrosHalV3DeviceDelegateFailedToGetCameraInfo, + kCrosHalV3DeviceDelegateMissingSensorOrientationInfo, + kCrosHalV3DeviceDelegateFailedToOpenCameraDevice, + kCrosHalV3DeviceDelegateFailedToInitializeCameraDevice, + kCrosHalV3DeviceDelegateFailedToConfigureStreams, + kCrosHalV3DeviceDelegateWrongNumberOfStreamsConfigured, + kCrosHalV3DeviceDelegateFailedToGetDefaultRequestSettings, + kCrosHalV3BufferManagerHalRequestedTooManyBuffers, + kCrosHalV3BufferManagerFailedToCreateGpuMemoryBuffer, + kCrosHalV3BufferManagerFailedToMapGpuMemoryBuffer, + kCrosHalV3BufferManagerUnsupportedVideoPixelFormat, + kCrosHalV3BufferManagerFailedToDupFd, + kCrosHalV3BufferManagerFailedToWrapGpuMemoryHandle, + kCrosHalV3BufferManagerFailedToRegisterBuffer, + kCrosHalV3BufferManagerProcessCaptureRequestFailed, + kCrosHalV3BufferManagerInvalidPendingResultId, + kCrosHalV3BufferManagerReceivedDuplicatedPartialMetadata, + kCrosHalV3BufferManagerIncorrectNumberOfOutputBuffersReceived, + kCrosHalV3BufferManagerInvalidTypeOfOutputBuffersReceived, + kCrosHalV3BufferManagerReceivedMultipleResultBuffersForFrame, + kCrosHalV3BufferManagerUnknownStreamInCamera3NotifyMsg, + kCrosHalV3BufferManagerReceivedInvalidShutterTime, + kCrosHalV3BufferManagerFatalDeviceError, + kCrosHalV3BufferManagerReceivedFrameIsOutOfOrder, + kCrosHalV3BufferManagerFailedToUnwrapReleaseFenceFd, + kCrosHalV3BufferManagerSyncWaitOnReleaseFenceTimedOut, + kCrosHalV3BufferManagerInvalidJpegBlob, + kAndroidFailedToAllocate, + kAndroidFailedToStartCapture, + kAndroidFailedToStopCapture, + kAndroidApi1CameraErrorCallbackReceived, + kAndroidApi2CameraDeviceErrorReceived, + kAndroidApi2CaptureSessionConfigureFailed, + kAndroidApi2ImageReaderUnexpectedImageFormat, + kAndroidApi2ImageReaderSizeDidNotMatchImageSize, + kAndroidApi2ErrorRestartingPreview, + kAndroidScreenCaptureUnsupportedFormat, + kAndroidScreenCaptureFailedToStartCaptureMachine, + kAndroidScreenCaptureTheUserDeniedScreenCapture, + kAndroidScreenCaptureFailedToStartScreenCapture, + kWinDirectShowCantGetCaptureFormatSettings, + kWinDirectShowFailedToGetNumberOfCapabilities, + kWinDirectShowFailedToGetCaptureDeviceCapabilities, + kWinDirectShowFailedToSetCaptureDeviceOutputFormat, + kWinDirectShowFailedToConnectTheCaptureGraph, + kWinDirectShowFailedToPauseTheCaptureDevice, + kWinDirectShowFailedToStartTheCaptureDevice, + kWinDirectShowFailedToStopTheCaptureGraph, + kWinMediaFoundationEngineIsNull, + kWinMediaFoundationEngineGetSourceFailed , + kWinMediaFoundationFillPhotoCapabilitiesFailed , + kWinMediaFoundationFillVideoCapabilitiesFailed, + kWinMediaFoundationNoVideoCapabilityFound, + kWinMediaFoundationGetAvailableDeviceMediaTypeFailed, + kWinMediaFoundationSetCurrentDeviceMediaTypeFailed, + kWinMediaFoundationEngineGetSinkFailed, + kWinMediaFoundationSinkQueryCapturePreviewInterfaceFailed, + kWinMediaFoundationSinkRemoveAllStreamsFailed, + kWinMediaFoundationCreateSinkVideoMediaTypeFailed, + kWinMediaFoundationConvertToVideoSinkMediaTypeFailed, + kWinMediaFoundationSinkAddStreamFailed, + kWinMediaFoundationSinkSetSampleCallbackFailed, + kWinMediaFoundationEngineStartPreviewFailed, + kWinMediaFoundationGetMediaEventStatusFailed, + kMacSetCaptureDeviceFailed, + kMacCouldNotStartCaptureDevice, + kMacReceivedFrameWithUnexpectedResolution, + kMacUpdateCaptureResolutionFailed, + kMacDeckLinkDeviceIdNotFoundInTheSystem, + kMacDeckLinkErrorQueryingInputInterface, + kMacDeckLinkErrorCreatingDisplayModeIterator, + kMacDeckLinkCouldNotFindADisplayMode, + kMacDeckLinkCouldNotSelectTheVideoFormatWeLike, + kMacDeckLinkCouldNotStartCapturing, + kMacDeckLinkUnsupportedPixelFormat, + kMacAvFoundationReceivedAVCaptureSessionRuntimeErrorNotification, + kAndroidApi2ErrorConfiguringCamera +}; + struct VideoCaptureFormat { gfx.mojom.Size frame_size; float frame_rate;
diff --git a/media/capture/mojom/video_capture_types.typemap b/media/capture/mojom/video_capture_types.typemap index cec8543c..7516007 100644 --- a/media/capture/mojom/video_capture_types.typemap +++ b/media/capture/mojom/video_capture_types.typemap
@@ -34,6 +34,7 @@ "media.mojom.PowerLineFrequency=media::PowerLineFrequency", "media.mojom.VideoCapturePixelFormat=media::VideoPixelFormat", "media.mojom.VideoCaptureBufferType=media::VideoCaptureBufferType", + "media.mojom.VideoCaptureError=media::VideoCaptureError", "media.mojom.VideoCaptureFormat=media::VideoCaptureFormat", "media.mojom.VideoCaptureParams=media::VideoCaptureParams", "media.mojom.VideoCaptureDeviceDescriptorCameraCalibration=media::VideoCaptureDeviceDescriptor::CameraCalibration",
diff --git a/media/capture/mojom/video_capture_types_mojom_traits.cc b/media/capture/mojom/video_capture_types_mojom_traits.cc index f02c0ac..7653507 100644 --- a/media/capture/mojom/video_capture_types_mojom_traits.cc +++ b/media/capture/mojom/video_capture_types_mojom_traits.cc
@@ -274,6 +274,919 @@ } // static +media::mojom::VideoCaptureError +EnumTraits<media::mojom::VideoCaptureError, media::VideoCaptureError>::ToMojom( + media::VideoCaptureError input) { + switch (input) { + case media::VideoCaptureError::kNone: + return media::mojom::VideoCaptureError::kNone; + case media::VideoCaptureError:: + kVideoCaptureControllerInvalidOrUnsupportedVideoCaptureParametersRequested: + return media::mojom::VideoCaptureError:: + kVideoCaptureControllerInvalidOrUnsupportedVideoCaptureParametersRequested; + case media::VideoCaptureError::kVideoCaptureControllerIsAlreadyInErrorState: + return media::mojom::VideoCaptureError:: + kVideoCaptureControllerIsAlreadyInErrorState; + case media::VideoCaptureError::kVideoCaptureManagerDeviceConnectionLost: + return media::mojom::VideoCaptureError:: + kVideoCaptureManagerDeviceConnectionLost; + case media::VideoCaptureError:: + kFrameSinkVideoCaptureDeviceAleradyEndedOnFatalError: + return media::mojom::VideoCaptureError:: + kFrameSinkVideoCaptureDeviceAleradyEndedOnFatalError; + case media::VideoCaptureError:: + kFrameSinkVideoCaptureDeviceEncounteredFatalError: + return media::mojom::VideoCaptureError:: + kFrameSinkVideoCaptureDeviceEncounteredFatalError; + case media::VideoCaptureError::kV4L2FailedToOpenV4L2DeviceDriverFile: + return media::mojom::VideoCaptureError:: + kV4L2FailedToOpenV4L2DeviceDriverFile; + case media::VideoCaptureError::kV4L2ThisIsNotAV4L2VideoCaptureDevice: + return media::mojom::VideoCaptureError:: + kV4L2ThisIsNotAV4L2VideoCaptureDevice; + case media::VideoCaptureError::kV4L2FailedToFindASupportedCameraFormat: + return media::mojom::VideoCaptureError:: + kV4L2FailedToFindASupportedCameraFormat; + case media::VideoCaptureError::kV4L2FailedToSetVideoCaptureFormat: + return media::mojom::VideoCaptureError:: + kV4L2FailedToSetVideoCaptureFormat; + case media::VideoCaptureError::kV4L2UnsupportedPixelFormat: + return media::mojom::VideoCaptureError::kV4L2UnsupportedPixelFormat; + case media::VideoCaptureError::kV4L2FailedToSetCameraFramerate: + return media::mojom::VideoCaptureError::kV4L2FailedToSetCameraFramerate; + case media::VideoCaptureError::kV4L2ErrorRequestingMmapBuffers: + return media::mojom::VideoCaptureError::kV4L2ErrorRequestingMmapBuffers; + case media::VideoCaptureError::kV4L2AllocateBufferFailed: + return media::mojom::VideoCaptureError::kV4L2AllocateBufferFailed; + case media::VideoCaptureError::kV4L2VidiocStreamonFailed: + return media::mojom::VideoCaptureError::kV4L2VidiocStreamonFailed; + case media::VideoCaptureError::kV4L2VidiocStreamoffFailed: + return media::mojom::VideoCaptureError::kV4L2VidiocStreamoffFailed; + case media::VideoCaptureError::kV4L2FailedToVidiocReqbufsWithCount0: + return media::mojom::VideoCaptureError:: + kV4L2FailedToVidiocReqbufsWithCount0; + case media::VideoCaptureError::kV4L2PollFailed: + return media::mojom::VideoCaptureError::kV4L2PollFailed; + case media::VideoCaptureError:: + kV4L2MultipleContinuousTimeoutsWhileReadPolling: + return media::mojom::VideoCaptureError:: + kV4L2MultipleContinuousTimeoutsWhileReadPolling; + case media::VideoCaptureError::kV4L2FailedToDequeueCaptureBuffer: + return media::mojom::VideoCaptureError::kV4L2FailedToDequeueCaptureBuffer; + case media::VideoCaptureError::kV4L2FailedToEnqueueCaptureBuffer: + return media::mojom::VideoCaptureError::kV4L2FailedToEnqueueCaptureBuffer; + case media::VideoCaptureError:: + kSingleClientVideoCaptureHostLostConnectionToDevice: + return media::mojom::VideoCaptureError:: + kSingleClientVideoCaptureHostLostConnectionToDevice; + case media::VideoCaptureError::kSingleClientVideoCaptureDeviceLaunchAborted: + return media::mojom::VideoCaptureError:: + kSingleClientVideoCaptureDeviceLaunchAborted; + case media::VideoCaptureError:: + kDesktopCaptureDeviceWebrtcDesktopCapturerHasFailed: + return media::mojom::VideoCaptureError:: + kDesktopCaptureDeviceWebrtcDesktopCapturerHasFailed; + case media::VideoCaptureError::kFileVideoCaptureDeviceCouldNotOpenVideoFile: + return media::mojom::VideoCaptureError:: + kFileVideoCaptureDeviceCouldNotOpenVideoFile; + case media::VideoCaptureError:: + kDeviceCaptureLinuxFailedToCreateVideoCaptureDelegate: + return media::mojom::VideoCaptureError:: + kDeviceCaptureLinuxFailedToCreateVideoCaptureDelegate; + case media::VideoCaptureError:: + kErrorFakeDeviceIntentionallyEmittingErrorEvent: + return media::mojom::VideoCaptureError:: + kErrorFakeDeviceIntentionallyEmittingErrorEvent; + case media::VideoCaptureError::kDeviceClientTooManyFramesDropped: + return media::mojom::VideoCaptureError::kDeviceClientTooManyFramesDropped; + case media::VideoCaptureError::kDeviceClientTooManyFramesDroppedY16: + return media::mojom::VideoCaptureError:: + kDeviceClientTooManyFramesDroppedY16; + case media::VideoCaptureError:: + kDeviceMediaToMojoAdapterEncounteredUnsupportedBufferType: + return media::mojom::VideoCaptureError:: + kDeviceMediaToMojoAdapterEncounteredUnsupportedBufferType; + case media::VideoCaptureError:: + kVideoCaptureManagerProcessDeviceStartQueueDeviceInfoNotFound: + return media::mojom::VideoCaptureError:: + kVideoCaptureManagerProcessDeviceStartQueueDeviceInfoNotFound; + case media::VideoCaptureError:: + kInProcessDeviceLauncherFailedToCreateDeviceInstance: + return media::mojom::VideoCaptureError:: + kInProcessDeviceLauncherFailedToCreateDeviceInstance; + case media::VideoCaptureError:: + kServiceDeviceLauncherLostConnectionToDeviceFactoryDuringDeviceStart: + return media::mojom::VideoCaptureError:: + kServiceDeviceLauncherLostConnectionToDeviceFactoryDuringDeviceStart; + case media::VideoCaptureError:: + kServiceDeviceLauncherServiceRespondedWithDeviceNotFound: + return media::mojom::VideoCaptureError:: + kServiceDeviceLauncherServiceRespondedWithDeviceNotFound; + case media::VideoCaptureError:: + kServiceDeviceLauncherConnectionLostWhileWaitingForCallback: + return media::mojom::VideoCaptureError:: + kServiceDeviceLauncherConnectionLostWhileWaitingForCallback; + case media::VideoCaptureError::kIntentionalErrorRaisedByUnitTest: + return media::mojom::VideoCaptureError::kIntentionalErrorRaisedByUnitTest; + case media::VideoCaptureError::kCrosHalV3FailedToStartDeviceThread: + return media::mojom::VideoCaptureError:: + kCrosHalV3FailedToStartDeviceThread; + case media::VideoCaptureError::kCrosHalV3DeviceDelegateMojoConnectionError: + return media::mojom::VideoCaptureError:: + kCrosHalV3DeviceDelegateMojoConnectionError; + case media::VideoCaptureError:: + kCrosHalV3DeviceDelegateFailedToGetCameraInfo: + return media::mojom::VideoCaptureError:: + kCrosHalV3DeviceDelegateFailedToGetCameraInfo; + case media::VideoCaptureError:: + kCrosHalV3DeviceDelegateMissingSensorOrientationInfo: + return media::mojom::VideoCaptureError:: + kCrosHalV3DeviceDelegateMissingSensorOrientationInfo; + case media::VideoCaptureError:: + kCrosHalV3DeviceDelegateFailedToOpenCameraDevice: + return media::mojom::VideoCaptureError:: + kCrosHalV3DeviceDelegateFailedToOpenCameraDevice; + case media::VideoCaptureError:: + kCrosHalV3DeviceDelegateFailedToInitializeCameraDevice: + return media::mojom::VideoCaptureError:: + kCrosHalV3DeviceDelegateFailedToInitializeCameraDevice; + case media::VideoCaptureError:: + kCrosHalV3DeviceDelegateFailedToConfigureStreams: + return media::mojom::VideoCaptureError:: + kCrosHalV3DeviceDelegateFailedToConfigureStreams; + case media::VideoCaptureError:: + kCrosHalV3DeviceDelegateWrongNumberOfStreamsConfigured: + return media::mojom::VideoCaptureError:: + kCrosHalV3DeviceDelegateWrongNumberOfStreamsConfigured; + case media::VideoCaptureError:: + kCrosHalV3DeviceDelegateFailedToGetDefaultRequestSettings: + return media::mojom::VideoCaptureError:: + kCrosHalV3DeviceDelegateFailedToGetDefaultRequestSettings; + case media::VideoCaptureError:: + kCrosHalV3BufferManagerHalRequestedTooManyBuffers: + return media::mojom::VideoCaptureError:: + kCrosHalV3BufferManagerHalRequestedTooManyBuffers; + case media::VideoCaptureError:: + kCrosHalV3BufferManagerFailedToCreateGpuMemoryBuffer: + return media::mojom::VideoCaptureError:: + kCrosHalV3BufferManagerFailedToCreateGpuMemoryBuffer; + case media::VideoCaptureError:: + kCrosHalV3BufferManagerFailedToMapGpuMemoryBuffer: + return media::mojom::VideoCaptureError:: + kCrosHalV3BufferManagerFailedToMapGpuMemoryBuffer; + case media::VideoCaptureError:: + kCrosHalV3BufferManagerUnsupportedVideoPixelFormat: + return media::mojom::VideoCaptureError:: + kCrosHalV3BufferManagerUnsupportedVideoPixelFormat; + case media::VideoCaptureError::kCrosHalV3BufferManagerFailedToDupFd: + return media::mojom::VideoCaptureError:: + kCrosHalV3BufferManagerFailedToDupFd; + case media::VideoCaptureError:: + kCrosHalV3BufferManagerFailedToWrapGpuMemoryHandle: + return media::mojom::VideoCaptureError:: + kCrosHalV3BufferManagerFailedToWrapGpuMemoryHandle; + case media::VideoCaptureError:: + kCrosHalV3BufferManagerFailedToRegisterBuffer: + return media::mojom::VideoCaptureError:: + kCrosHalV3BufferManagerFailedToRegisterBuffer; + case media::VideoCaptureError:: + kCrosHalV3BufferManagerProcessCaptureRequestFailed: + return media::mojom::VideoCaptureError:: + kCrosHalV3BufferManagerProcessCaptureRequestFailed; + case media::VideoCaptureError:: + kCrosHalV3BufferManagerInvalidPendingResultId: + return media::mojom::VideoCaptureError:: + kCrosHalV3BufferManagerInvalidPendingResultId; + case media::VideoCaptureError:: + kCrosHalV3BufferManagerReceivedDuplicatedPartialMetadata: + return media::mojom::VideoCaptureError:: + kCrosHalV3BufferManagerReceivedDuplicatedPartialMetadata; + case media::VideoCaptureError:: + kCrosHalV3BufferManagerIncorrectNumberOfOutputBuffersReceived: + return media::mojom::VideoCaptureError:: + kCrosHalV3BufferManagerIncorrectNumberOfOutputBuffersReceived; + case media::VideoCaptureError:: + kCrosHalV3BufferManagerInvalidTypeOfOutputBuffersReceived: + return media::mojom::VideoCaptureError:: + kCrosHalV3BufferManagerInvalidTypeOfOutputBuffersReceived; + case media::VideoCaptureError:: + kCrosHalV3BufferManagerReceivedMultipleResultBuffersForFrame: + return media::mojom::VideoCaptureError:: + kCrosHalV3BufferManagerReceivedMultipleResultBuffersForFrame; + case media::VideoCaptureError:: + kCrosHalV3BufferManagerUnknownStreamInCamera3NotifyMsg: + return media::mojom::VideoCaptureError:: + kCrosHalV3BufferManagerUnknownStreamInCamera3NotifyMsg; + case media::VideoCaptureError:: + kCrosHalV3BufferManagerReceivedInvalidShutterTime: + return media::mojom::VideoCaptureError:: + kCrosHalV3BufferManagerReceivedInvalidShutterTime; + case media::VideoCaptureError::kCrosHalV3BufferManagerFatalDeviceError: + return media::mojom::VideoCaptureError:: + kCrosHalV3BufferManagerFatalDeviceError; + case media::VideoCaptureError:: + kCrosHalV3BufferManagerReceivedFrameIsOutOfOrder: + return media::mojom::VideoCaptureError:: + kCrosHalV3BufferManagerReceivedFrameIsOutOfOrder; + case media::VideoCaptureError:: + kCrosHalV3BufferManagerFailedToUnwrapReleaseFenceFd: + return media::mojom::VideoCaptureError:: + kCrosHalV3BufferManagerFailedToUnwrapReleaseFenceFd; + case media::VideoCaptureError:: + kCrosHalV3BufferManagerSyncWaitOnReleaseFenceTimedOut: + return media::mojom::VideoCaptureError:: + kCrosHalV3BufferManagerSyncWaitOnReleaseFenceTimedOut; + case media::VideoCaptureError::kCrosHalV3BufferManagerInvalidJpegBlob: + return media::mojom::VideoCaptureError:: + kCrosHalV3BufferManagerInvalidJpegBlob; + case media::VideoCaptureError::kAndroidFailedToAllocate: + return media::mojom::VideoCaptureError::kAndroidFailedToAllocate; + case media::VideoCaptureError::kAndroidFailedToStartCapture: + return media::mojom::VideoCaptureError::kAndroidFailedToStartCapture; + case media::VideoCaptureError::kAndroidFailedToStopCapture: + return media::mojom::VideoCaptureError::kAndroidFailedToStopCapture; + case media::VideoCaptureError::kAndroidApi1CameraErrorCallbackReceived: + return media::mojom::VideoCaptureError:: + kAndroidApi1CameraErrorCallbackReceived; + case media::VideoCaptureError::kAndroidApi2CameraDeviceErrorReceived: + return media::mojom::VideoCaptureError:: + kAndroidApi2CameraDeviceErrorReceived; + case media::VideoCaptureError::kAndroidApi2CaptureSessionConfigureFailed: + return media::mojom::VideoCaptureError:: + kAndroidApi2CaptureSessionConfigureFailed; + case media::VideoCaptureError::kAndroidApi2ImageReaderUnexpectedImageFormat: + return media::mojom::VideoCaptureError:: + kAndroidApi2ImageReaderUnexpectedImageFormat; + case media::VideoCaptureError:: + kAndroidApi2ImageReaderSizeDidNotMatchImageSize: + return media::mojom::VideoCaptureError:: + kAndroidApi2ImageReaderSizeDidNotMatchImageSize; + case media::VideoCaptureError::kAndroidApi2ErrorRestartingPreview: + return media::mojom::VideoCaptureError:: + kAndroidApi2ErrorRestartingPreview; + case media::VideoCaptureError::kAndroidScreenCaptureUnsupportedFormat: + return media::mojom::VideoCaptureError:: + kAndroidScreenCaptureUnsupportedFormat; + case media::VideoCaptureError:: + kAndroidScreenCaptureFailedToStartCaptureMachine: + return media::mojom::VideoCaptureError:: + kAndroidScreenCaptureFailedToStartCaptureMachine; + case media::VideoCaptureError:: + kAndroidScreenCaptureTheUserDeniedScreenCapture: + return media::mojom::VideoCaptureError:: + kAndroidScreenCaptureTheUserDeniedScreenCapture; + case media::VideoCaptureError:: + kAndroidScreenCaptureFailedToStartScreenCapture: + return media::mojom::VideoCaptureError:: + kAndroidScreenCaptureFailedToStartScreenCapture; + case media::VideoCaptureError::kWinDirectShowCantGetCaptureFormatSettings: + return media::mojom::VideoCaptureError:: + kWinDirectShowCantGetCaptureFormatSettings; + case media::VideoCaptureError:: + kWinDirectShowFailedToGetNumberOfCapabilities: + return media::mojom::VideoCaptureError:: + kWinDirectShowFailedToGetNumberOfCapabilities; + case media::VideoCaptureError:: + kWinDirectShowFailedToGetCaptureDeviceCapabilities: + return media::mojom::VideoCaptureError:: + kWinDirectShowFailedToGetCaptureDeviceCapabilities; + case media::VideoCaptureError:: + kWinDirectShowFailedToSetCaptureDeviceOutputFormat: + return media::mojom::VideoCaptureError:: + kWinDirectShowFailedToSetCaptureDeviceOutputFormat; + case media::VideoCaptureError::kWinDirectShowFailedToConnectTheCaptureGraph: + return media::mojom::VideoCaptureError:: + kWinDirectShowFailedToConnectTheCaptureGraph; + case media::VideoCaptureError::kWinDirectShowFailedToPauseTheCaptureDevice: + return media::mojom::VideoCaptureError:: + kWinDirectShowFailedToPauseTheCaptureDevice; + case media::VideoCaptureError::kWinDirectShowFailedToStartTheCaptureDevice: + return media::mojom::VideoCaptureError:: + kWinDirectShowFailedToStartTheCaptureDevice; + case media::VideoCaptureError::kWinDirectShowFailedToStopTheCaptureGraph: + return media::mojom::VideoCaptureError:: + kWinDirectShowFailedToStopTheCaptureGraph; + case media::VideoCaptureError::kWinMediaFoundationEngineIsNull: + return media::mojom::VideoCaptureError::kWinMediaFoundationEngineIsNull; + case media::VideoCaptureError::kWinMediaFoundationEngineGetSourceFailed: + return media::mojom::VideoCaptureError:: + kWinMediaFoundationEngineGetSourceFailed; + case media::VideoCaptureError:: + kWinMediaFoundationFillPhotoCapabilitiesFailed: + return media::mojom::VideoCaptureError:: + kWinMediaFoundationFillPhotoCapabilitiesFailed; + case media::VideoCaptureError:: + kWinMediaFoundationFillVideoCapabilitiesFailed: + return media::mojom::VideoCaptureError:: + kWinMediaFoundationFillVideoCapabilitiesFailed; + case media::VideoCaptureError::kWinMediaFoundationNoVideoCapabilityFound: + return media::mojom::VideoCaptureError:: + kWinMediaFoundationNoVideoCapabilityFound; + case media::VideoCaptureError:: + kWinMediaFoundationGetAvailableDeviceMediaTypeFailed: + return media::mojom::VideoCaptureError:: + kWinMediaFoundationGetAvailableDeviceMediaTypeFailed; + case media::VideoCaptureError:: + kWinMediaFoundationSetCurrentDeviceMediaTypeFailed: + return media::mojom::VideoCaptureError:: + kWinMediaFoundationSetCurrentDeviceMediaTypeFailed; + case media::VideoCaptureError::kWinMediaFoundationEngineGetSinkFailed: + return media::mojom::VideoCaptureError:: + kWinMediaFoundationEngineGetSinkFailed; + case media::VideoCaptureError:: + kWinMediaFoundationSinkQueryCapturePreviewInterfaceFailed: + return media::mojom::VideoCaptureError:: + kWinMediaFoundationSinkQueryCapturePreviewInterfaceFailed; + case media::VideoCaptureError:: + kWinMediaFoundationSinkRemoveAllStreamsFailed: + return media::mojom::VideoCaptureError:: + kWinMediaFoundationSinkRemoveAllStreamsFailed; + case media::VideoCaptureError:: + kWinMediaFoundationCreateSinkVideoMediaTypeFailed: + return media::mojom::VideoCaptureError:: + kWinMediaFoundationCreateSinkVideoMediaTypeFailed; + case media::VideoCaptureError:: + kWinMediaFoundationConvertToVideoSinkMediaTypeFailed: + return media::mojom::VideoCaptureError:: + kWinMediaFoundationConvertToVideoSinkMediaTypeFailed; + case media::VideoCaptureError::kWinMediaFoundationSinkAddStreamFailed: + return media::mojom::VideoCaptureError:: + kWinMediaFoundationSinkAddStreamFailed; + case media::VideoCaptureError:: + kWinMediaFoundationSinkSetSampleCallbackFailed: + return media::mojom::VideoCaptureError:: + kWinMediaFoundationSinkSetSampleCallbackFailed; + case media::VideoCaptureError::kWinMediaFoundationEngineStartPreviewFailed: + return media::mojom::VideoCaptureError:: + kWinMediaFoundationEngineStartPreviewFailed; + case media::VideoCaptureError::kWinMediaFoundationGetMediaEventStatusFailed: + return media::mojom::VideoCaptureError:: + kWinMediaFoundationGetMediaEventStatusFailed; + case media::VideoCaptureError::kMacSetCaptureDeviceFailed: + return media::mojom::VideoCaptureError::kMacSetCaptureDeviceFailed; + case media::VideoCaptureError::kMacCouldNotStartCaptureDevice: + return media::mojom::VideoCaptureError::kMacCouldNotStartCaptureDevice; + case media::VideoCaptureError::kMacReceivedFrameWithUnexpectedResolution: + return media::mojom::VideoCaptureError:: + kMacReceivedFrameWithUnexpectedResolution; + case media::VideoCaptureError::kMacUpdateCaptureResolutionFailed: + return media::mojom::VideoCaptureError::kMacUpdateCaptureResolutionFailed; + case media::VideoCaptureError::kMacDeckLinkDeviceIdNotFoundInTheSystem: + return media::mojom::VideoCaptureError:: + kMacDeckLinkDeviceIdNotFoundInTheSystem; + case media::VideoCaptureError::kMacDeckLinkErrorQueryingInputInterface: + return media::mojom::VideoCaptureError:: + kMacDeckLinkErrorQueryingInputInterface; + case media::VideoCaptureError::kMacDeckLinkErrorCreatingDisplayModeIterator: + return media::mojom::VideoCaptureError:: + kMacDeckLinkErrorCreatingDisplayModeIterator; + case media::VideoCaptureError::kMacDeckLinkCouldNotFindADisplayMode: + return media::mojom::VideoCaptureError:: + kMacDeckLinkCouldNotFindADisplayMode; + case media::VideoCaptureError:: + kMacDeckLinkCouldNotSelectTheVideoFormatWeLike: + return media::mojom::VideoCaptureError:: + kMacDeckLinkCouldNotSelectTheVideoFormatWeLike; + case media::VideoCaptureError::kMacDeckLinkCouldNotStartCapturing: + return media::mojom::VideoCaptureError:: + kMacDeckLinkCouldNotStartCapturing; + case media::VideoCaptureError::kMacDeckLinkUnsupportedPixelFormat: + return media::mojom::VideoCaptureError:: + kMacDeckLinkUnsupportedPixelFormat; + case media::VideoCaptureError:: + kMacAvFoundationReceivedAVCaptureSessionRuntimeErrorNotification: + return media::mojom::VideoCaptureError:: + kMacAvFoundationReceivedAVCaptureSessionRuntimeErrorNotification; + case media::VideoCaptureError::kAndroidApi2ErrorConfiguringCamera: + return media::mojom::VideoCaptureError:: + kAndroidApi2ErrorConfiguringCamera; + } + NOTREACHED(); + return media::mojom::VideoCaptureError::kNone; +} + +// static +bool EnumTraits<media::mojom::VideoCaptureError, media::VideoCaptureError>:: + FromMojom(media::mojom::VideoCaptureError input, + media::VideoCaptureError* output) { + switch (input) { + case media::mojom::VideoCaptureError::kNone: + *output = media::VideoCaptureError::kNone; + return true; + case media::mojom::VideoCaptureError:: + kVideoCaptureControllerInvalidOrUnsupportedVideoCaptureParametersRequested: + *output = media::VideoCaptureError:: + kVideoCaptureControllerInvalidOrUnsupportedVideoCaptureParametersRequested; + return true; + case media::mojom::VideoCaptureError:: + kVideoCaptureControllerIsAlreadyInErrorState: + *output = media::VideoCaptureError:: + kVideoCaptureControllerIsAlreadyInErrorState; + return true; + case media::mojom::VideoCaptureError:: + kVideoCaptureManagerDeviceConnectionLost: + *output = + media::VideoCaptureError::kVideoCaptureManagerDeviceConnectionLost; + return true; + case media::mojom::VideoCaptureError:: + kFrameSinkVideoCaptureDeviceAleradyEndedOnFatalError: + *output = media::VideoCaptureError:: + kFrameSinkVideoCaptureDeviceAleradyEndedOnFatalError; + return true; + case media::mojom::VideoCaptureError:: + kFrameSinkVideoCaptureDeviceEncounteredFatalError: + *output = media::VideoCaptureError:: + kFrameSinkVideoCaptureDeviceEncounteredFatalError; + return true; + case media::mojom::VideoCaptureError::kV4L2FailedToOpenV4L2DeviceDriverFile: + *output = media::VideoCaptureError::kV4L2FailedToOpenV4L2DeviceDriverFile; + return true; + case media::mojom::VideoCaptureError::kV4L2ThisIsNotAV4L2VideoCaptureDevice: + *output = media::VideoCaptureError::kV4L2ThisIsNotAV4L2VideoCaptureDevice; + return true; + case media::mojom::VideoCaptureError:: + kV4L2FailedToFindASupportedCameraFormat: + *output = + media::VideoCaptureError::kV4L2FailedToFindASupportedCameraFormat; + return true; + case media::mojom::VideoCaptureError::kV4L2FailedToSetVideoCaptureFormat: + *output = media::VideoCaptureError::kV4L2FailedToSetVideoCaptureFormat; + return true; + case media::mojom::VideoCaptureError::kV4L2UnsupportedPixelFormat: + *output = media::VideoCaptureError::kV4L2UnsupportedPixelFormat; + return true; + case media::mojom::VideoCaptureError::kV4L2FailedToSetCameraFramerate: + *output = media::VideoCaptureError::kV4L2FailedToSetCameraFramerate; + return true; + case media::mojom::VideoCaptureError::kV4L2ErrorRequestingMmapBuffers: + *output = media::VideoCaptureError::kV4L2ErrorRequestingMmapBuffers; + return true; + case media::mojom::VideoCaptureError::kV4L2AllocateBufferFailed: + *output = media::VideoCaptureError::kV4L2AllocateBufferFailed; + return true; + case media::mojom::VideoCaptureError::kV4L2VidiocStreamonFailed: + *output = media::VideoCaptureError::kV4L2VidiocStreamonFailed; + return true; + case media::mojom::VideoCaptureError::kV4L2VidiocStreamoffFailed: + *output = media::VideoCaptureError::kV4L2VidiocStreamoffFailed; + return true; + case media::mojom::VideoCaptureError::kV4L2FailedToVidiocReqbufsWithCount0: + *output = media::VideoCaptureError::kV4L2FailedToVidiocReqbufsWithCount0; + return true; + case media::mojom::VideoCaptureError::kV4L2PollFailed: + *output = media::VideoCaptureError::kV4L2PollFailed; + return true; + case media::mojom::VideoCaptureError:: + kV4L2MultipleContinuousTimeoutsWhileReadPolling: + *output = media::VideoCaptureError:: + kV4L2MultipleContinuousTimeoutsWhileReadPolling; + return true; + case media::mojom::VideoCaptureError::kV4L2FailedToDequeueCaptureBuffer: + *output = media::VideoCaptureError::kV4L2FailedToDequeueCaptureBuffer; + return true; + case media::mojom::VideoCaptureError::kV4L2FailedToEnqueueCaptureBuffer: + *output = media::VideoCaptureError::kV4L2FailedToEnqueueCaptureBuffer; + return true; + case media::mojom::VideoCaptureError:: + kSingleClientVideoCaptureHostLostConnectionToDevice: + *output = media::VideoCaptureError:: + kSingleClientVideoCaptureHostLostConnectionToDevice; + return true; + case media::mojom::VideoCaptureError:: + kSingleClientVideoCaptureDeviceLaunchAborted: + *output = media::VideoCaptureError:: + kSingleClientVideoCaptureDeviceLaunchAborted; + return true; + case media::mojom::VideoCaptureError:: + kDesktopCaptureDeviceWebrtcDesktopCapturerHasFailed: + *output = media::VideoCaptureError:: + kDesktopCaptureDeviceWebrtcDesktopCapturerHasFailed; + return true; + case media::mojom::VideoCaptureError:: + kFileVideoCaptureDeviceCouldNotOpenVideoFile: + *output = media::VideoCaptureError:: + kFileVideoCaptureDeviceCouldNotOpenVideoFile; + return true; + case media::mojom::VideoCaptureError:: + kDeviceCaptureLinuxFailedToCreateVideoCaptureDelegate: + *output = media::VideoCaptureError:: + kDeviceCaptureLinuxFailedToCreateVideoCaptureDelegate; + return true; + case media::mojom::VideoCaptureError:: + kErrorFakeDeviceIntentionallyEmittingErrorEvent: + *output = media::VideoCaptureError:: + kErrorFakeDeviceIntentionallyEmittingErrorEvent; + return true; + case media::mojom::VideoCaptureError::kDeviceClientTooManyFramesDropped: + *output = media::VideoCaptureError::kDeviceClientTooManyFramesDropped; + return true; + case media::mojom::VideoCaptureError::kDeviceClientTooManyFramesDroppedY16: + *output = media::VideoCaptureError::kDeviceClientTooManyFramesDroppedY16; + return true; + case media::mojom::VideoCaptureError:: + kDeviceMediaToMojoAdapterEncounteredUnsupportedBufferType: + *output = media::VideoCaptureError:: + kDeviceMediaToMojoAdapterEncounteredUnsupportedBufferType; + return true; + case media::mojom::VideoCaptureError:: + kVideoCaptureManagerProcessDeviceStartQueueDeviceInfoNotFound: + *output = media::VideoCaptureError:: + kVideoCaptureManagerProcessDeviceStartQueueDeviceInfoNotFound; + return true; + case media::mojom::VideoCaptureError:: + kInProcessDeviceLauncherFailedToCreateDeviceInstance: + *output = media::VideoCaptureError:: + kInProcessDeviceLauncherFailedToCreateDeviceInstance; + return true; + case media::mojom::VideoCaptureError:: + kServiceDeviceLauncherLostConnectionToDeviceFactoryDuringDeviceStart: + *output = media::VideoCaptureError:: + kServiceDeviceLauncherLostConnectionToDeviceFactoryDuringDeviceStart; + return true; + case media::mojom::VideoCaptureError:: + kServiceDeviceLauncherServiceRespondedWithDeviceNotFound: + *output = media::VideoCaptureError:: + kServiceDeviceLauncherServiceRespondedWithDeviceNotFound; + return true; + case media::mojom::VideoCaptureError:: + kServiceDeviceLauncherConnectionLostWhileWaitingForCallback: + *output = media::VideoCaptureError:: + kServiceDeviceLauncherConnectionLostWhileWaitingForCallback; + return true; + case media::mojom::VideoCaptureError::kIntentionalErrorRaisedByUnitTest: + *output = media::VideoCaptureError::kIntentionalErrorRaisedByUnitTest; + return true; + case media::mojom::VideoCaptureError::kCrosHalV3FailedToStartDeviceThread: + *output = media::VideoCaptureError::kCrosHalV3FailedToStartDeviceThread; + return true; + case media::mojom::VideoCaptureError:: + kCrosHalV3DeviceDelegateMojoConnectionError: + *output = + media::VideoCaptureError::kCrosHalV3DeviceDelegateMojoConnectionError; + return true; + case media::mojom::VideoCaptureError:: + kCrosHalV3DeviceDelegateFailedToGetCameraInfo: + *output = media::VideoCaptureError:: + kCrosHalV3DeviceDelegateFailedToGetCameraInfo; + return true; + case media::mojom::VideoCaptureError:: + kCrosHalV3DeviceDelegateMissingSensorOrientationInfo: + *output = media::VideoCaptureError:: + kCrosHalV3DeviceDelegateMissingSensorOrientationInfo; + return true; + case media::mojom::VideoCaptureError:: + kCrosHalV3DeviceDelegateFailedToOpenCameraDevice: + *output = media::VideoCaptureError:: + kCrosHalV3DeviceDelegateFailedToOpenCameraDevice; + return true; + case media::mojom::VideoCaptureError:: + kCrosHalV3DeviceDelegateFailedToInitializeCameraDevice: + *output = media::VideoCaptureError:: + kCrosHalV3DeviceDelegateFailedToInitializeCameraDevice; + return true; + case media::mojom::VideoCaptureError:: + kCrosHalV3DeviceDelegateFailedToConfigureStreams: + *output = media::VideoCaptureError:: + kCrosHalV3DeviceDelegateFailedToConfigureStreams; + return true; + case media::mojom::VideoCaptureError:: + kCrosHalV3DeviceDelegateWrongNumberOfStreamsConfigured: + *output = media::VideoCaptureError:: + kCrosHalV3DeviceDelegateWrongNumberOfStreamsConfigured; + return true; + case media::mojom::VideoCaptureError:: + kCrosHalV3DeviceDelegateFailedToGetDefaultRequestSettings: + *output = media::VideoCaptureError:: + kCrosHalV3DeviceDelegateFailedToGetDefaultRequestSettings; + return true; + case media::mojom::VideoCaptureError:: + kCrosHalV3BufferManagerHalRequestedTooManyBuffers: + *output = media::VideoCaptureError:: + kCrosHalV3BufferManagerHalRequestedTooManyBuffers; + return true; + case media::mojom::VideoCaptureError:: + kCrosHalV3BufferManagerFailedToCreateGpuMemoryBuffer: + *output = media::VideoCaptureError:: + kCrosHalV3BufferManagerFailedToCreateGpuMemoryBuffer; + return true; + case media::mojom::VideoCaptureError:: + kCrosHalV3BufferManagerFailedToMapGpuMemoryBuffer: + *output = media::VideoCaptureError:: + kCrosHalV3BufferManagerFailedToMapGpuMemoryBuffer; + return true; + case media::mojom::VideoCaptureError:: + kCrosHalV3BufferManagerUnsupportedVideoPixelFormat: + *output = media::VideoCaptureError:: + kCrosHalV3BufferManagerUnsupportedVideoPixelFormat; + return true; + case media::mojom::VideoCaptureError::kCrosHalV3BufferManagerFailedToDupFd: + *output = media::VideoCaptureError::kCrosHalV3BufferManagerFailedToDupFd; + return true; + case media::mojom::VideoCaptureError:: + kCrosHalV3BufferManagerFailedToWrapGpuMemoryHandle: + *output = media::VideoCaptureError:: + kCrosHalV3BufferManagerFailedToWrapGpuMemoryHandle; + return true; + case media::mojom::VideoCaptureError:: + kCrosHalV3BufferManagerFailedToRegisterBuffer: + *output = media::VideoCaptureError:: + kCrosHalV3BufferManagerFailedToRegisterBuffer; + return true; + case media::mojom::VideoCaptureError:: + kCrosHalV3BufferManagerProcessCaptureRequestFailed: + *output = media::VideoCaptureError:: + kCrosHalV3BufferManagerProcessCaptureRequestFailed; + return true; + case media::mojom::VideoCaptureError:: + kCrosHalV3BufferManagerInvalidPendingResultId: + *output = media::VideoCaptureError:: + kCrosHalV3BufferManagerInvalidPendingResultId; + return true; + case media::mojom::VideoCaptureError:: + kCrosHalV3BufferManagerReceivedDuplicatedPartialMetadata: + *output = media::VideoCaptureError:: + kCrosHalV3BufferManagerReceivedDuplicatedPartialMetadata; + return true; + case media::mojom::VideoCaptureError:: + kCrosHalV3BufferManagerIncorrectNumberOfOutputBuffersReceived: + *output = media::VideoCaptureError:: + kCrosHalV3BufferManagerIncorrectNumberOfOutputBuffersReceived; + return true; + case media::mojom::VideoCaptureError:: + kCrosHalV3BufferManagerInvalidTypeOfOutputBuffersReceived: + *output = media::VideoCaptureError:: + kCrosHalV3BufferManagerInvalidTypeOfOutputBuffersReceived; + return true; + case media::mojom::VideoCaptureError:: + kCrosHalV3BufferManagerReceivedMultipleResultBuffersForFrame: + *output = media::VideoCaptureError:: + kCrosHalV3BufferManagerReceivedMultipleResultBuffersForFrame; + return true; + case media::mojom::VideoCaptureError:: + kCrosHalV3BufferManagerUnknownStreamInCamera3NotifyMsg: + *output = media::VideoCaptureError:: + kCrosHalV3BufferManagerUnknownStreamInCamera3NotifyMsg; + return true; + case media::mojom::VideoCaptureError:: + kCrosHalV3BufferManagerReceivedInvalidShutterTime: + *output = media::VideoCaptureError:: + kCrosHalV3BufferManagerReceivedInvalidShutterTime; + return true; + case media::mojom::VideoCaptureError:: + kCrosHalV3BufferManagerFatalDeviceError: + *output = + media::VideoCaptureError::kCrosHalV3BufferManagerFatalDeviceError; + return true; + case media::mojom::VideoCaptureError:: + kCrosHalV3BufferManagerReceivedFrameIsOutOfOrder: + *output = media::VideoCaptureError:: + kCrosHalV3BufferManagerReceivedFrameIsOutOfOrder; + return true; + case media::mojom::VideoCaptureError:: + kCrosHalV3BufferManagerFailedToUnwrapReleaseFenceFd: + *output = media::VideoCaptureError:: + kCrosHalV3BufferManagerFailedToUnwrapReleaseFenceFd; + return true; + case media::mojom::VideoCaptureError:: + kCrosHalV3BufferManagerSyncWaitOnReleaseFenceTimedOut: + *output = media::VideoCaptureError:: + kCrosHalV3BufferManagerSyncWaitOnReleaseFenceTimedOut; + return true; + case media::mojom::VideoCaptureError:: + kCrosHalV3BufferManagerInvalidJpegBlob: + *output = + media::VideoCaptureError::kCrosHalV3BufferManagerInvalidJpegBlob; + return true; + case media::mojom::VideoCaptureError::kAndroidFailedToAllocate: + *output = media::VideoCaptureError::kAndroidFailedToAllocate; + return true; + case media::mojom::VideoCaptureError::kAndroidFailedToStartCapture: + *output = media::VideoCaptureError::kAndroidFailedToStartCapture; + return true; + case media::mojom::VideoCaptureError::kAndroidFailedToStopCapture: + *output = media::VideoCaptureError::kAndroidFailedToStopCapture; + return true; + case media::mojom::VideoCaptureError:: + kAndroidApi1CameraErrorCallbackReceived: + *output = + media::VideoCaptureError::kAndroidApi1CameraErrorCallbackReceived; + return true; + case media::mojom::VideoCaptureError::kAndroidApi2CameraDeviceErrorReceived: + *output = media::VideoCaptureError::kAndroidApi2CameraDeviceErrorReceived; + return true; + case media::mojom::VideoCaptureError:: + kAndroidApi2CaptureSessionConfigureFailed: + *output = + media::VideoCaptureError::kAndroidApi2CaptureSessionConfigureFailed; + return true; + case media::mojom::VideoCaptureError:: + kAndroidApi2ImageReaderUnexpectedImageFormat: + *output = media::VideoCaptureError:: + kAndroidApi2ImageReaderUnexpectedImageFormat; + return true; + case media::mojom::VideoCaptureError:: + kAndroidApi2ImageReaderSizeDidNotMatchImageSize: + *output = media::VideoCaptureError:: + kAndroidApi2ImageReaderSizeDidNotMatchImageSize; + return true; + case media::mojom::VideoCaptureError::kAndroidApi2ErrorRestartingPreview: + *output = media::VideoCaptureError::kAndroidApi2ErrorRestartingPreview; + return true; + case media::mojom::VideoCaptureError:: + kAndroidScreenCaptureUnsupportedFormat: + *output = + media::VideoCaptureError::kAndroidScreenCaptureUnsupportedFormat; + return true; + case media::mojom::VideoCaptureError:: + kAndroidScreenCaptureFailedToStartCaptureMachine: + *output = media::VideoCaptureError:: + kAndroidScreenCaptureFailedToStartCaptureMachine; + return true; + case media::mojom::VideoCaptureError:: + kAndroidScreenCaptureTheUserDeniedScreenCapture: + *output = media::VideoCaptureError:: + kAndroidScreenCaptureTheUserDeniedScreenCapture; + return true; + case media::mojom::VideoCaptureError:: + kAndroidScreenCaptureFailedToStartScreenCapture: + *output = media::VideoCaptureError:: + kAndroidScreenCaptureFailedToStartScreenCapture; + return true; + case media::mojom::VideoCaptureError:: + kWinDirectShowCantGetCaptureFormatSettings: + *output = + media::VideoCaptureError::kWinDirectShowCantGetCaptureFormatSettings; + return true; + case media::mojom::VideoCaptureError:: + kWinDirectShowFailedToGetNumberOfCapabilities: + *output = media::VideoCaptureError:: + kWinDirectShowFailedToGetNumberOfCapabilities; + return true; + case media::mojom::VideoCaptureError:: + kWinDirectShowFailedToGetCaptureDeviceCapabilities: + *output = media::VideoCaptureError:: + kWinDirectShowFailedToGetCaptureDeviceCapabilities; + return true; + case media::mojom::VideoCaptureError:: + kWinDirectShowFailedToSetCaptureDeviceOutputFormat: + *output = media::VideoCaptureError:: + kWinDirectShowFailedToSetCaptureDeviceOutputFormat; + return true; + case media::mojom::VideoCaptureError:: + kWinDirectShowFailedToConnectTheCaptureGraph: + *output = media::VideoCaptureError:: + kWinDirectShowFailedToConnectTheCaptureGraph; + return true; + case media::mojom::VideoCaptureError:: + kWinDirectShowFailedToPauseTheCaptureDevice: + *output = + media::VideoCaptureError::kWinDirectShowFailedToPauseTheCaptureDevice; + return true; + case media::mojom::VideoCaptureError:: + kWinDirectShowFailedToStartTheCaptureDevice: + *output = + media::VideoCaptureError::kWinDirectShowFailedToStartTheCaptureDevice; + return true; + case media::mojom::VideoCaptureError:: + kWinDirectShowFailedToStopTheCaptureGraph: + *output = + media::VideoCaptureError::kWinDirectShowFailedToStopTheCaptureGraph; + return true; + case media::mojom::VideoCaptureError::kWinMediaFoundationEngineIsNull: + *output = media::VideoCaptureError::kWinMediaFoundationEngineIsNull; + return true; + case media::mojom::VideoCaptureError:: + kWinMediaFoundationEngineGetSourceFailed: + *output = + media::VideoCaptureError::kWinMediaFoundationEngineGetSourceFailed; + return true; + case media::mojom::VideoCaptureError:: + kWinMediaFoundationFillPhotoCapabilitiesFailed: + *output = media::VideoCaptureError:: + kWinMediaFoundationFillPhotoCapabilitiesFailed; + return true; + case media::mojom::VideoCaptureError:: + kWinMediaFoundationFillVideoCapabilitiesFailed: + *output = media::VideoCaptureError:: + kWinMediaFoundationFillVideoCapabilitiesFailed; + return true; + case media::mojom::VideoCaptureError:: + kWinMediaFoundationNoVideoCapabilityFound: + *output = + media::VideoCaptureError::kWinMediaFoundationNoVideoCapabilityFound; + return true; + case media::mojom::VideoCaptureError:: + kWinMediaFoundationGetAvailableDeviceMediaTypeFailed: + *output = media::VideoCaptureError:: + kWinMediaFoundationGetAvailableDeviceMediaTypeFailed; + return true; + case media::mojom::VideoCaptureError:: + kWinMediaFoundationSetCurrentDeviceMediaTypeFailed: + *output = media::VideoCaptureError:: + kWinMediaFoundationSetCurrentDeviceMediaTypeFailed; + return true; + case media::mojom::VideoCaptureError:: + kWinMediaFoundationEngineGetSinkFailed: + *output = + media::VideoCaptureError::kWinMediaFoundationEngineGetSinkFailed; + return true; + case media::mojom::VideoCaptureError:: + kWinMediaFoundationSinkQueryCapturePreviewInterfaceFailed: + *output = media::VideoCaptureError:: + kWinMediaFoundationSinkQueryCapturePreviewInterfaceFailed; + return true; + case media::mojom::VideoCaptureError:: + kWinMediaFoundationSinkRemoveAllStreamsFailed: + *output = media::VideoCaptureError:: + kWinMediaFoundationSinkRemoveAllStreamsFailed; + return true; + case media::mojom::VideoCaptureError:: + kWinMediaFoundationCreateSinkVideoMediaTypeFailed: + *output = media::VideoCaptureError:: + kWinMediaFoundationCreateSinkVideoMediaTypeFailed; + return true; + case media::mojom::VideoCaptureError:: + kWinMediaFoundationConvertToVideoSinkMediaTypeFailed: + *output = media::VideoCaptureError:: + kWinMediaFoundationConvertToVideoSinkMediaTypeFailed; + return true; + case media::mojom::VideoCaptureError:: + kWinMediaFoundationSinkAddStreamFailed: + *output = + media::VideoCaptureError::kWinMediaFoundationSinkAddStreamFailed; + return true; + case media::mojom::VideoCaptureError:: + kWinMediaFoundationSinkSetSampleCallbackFailed: + *output = media::VideoCaptureError:: + kWinMediaFoundationSinkSetSampleCallbackFailed; + return true; + case media::mojom::VideoCaptureError:: + kWinMediaFoundationEngineStartPreviewFailed: + *output = + media::VideoCaptureError::kWinMediaFoundationEngineStartPreviewFailed; + return true; + case media::mojom::VideoCaptureError:: + kWinMediaFoundationGetMediaEventStatusFailed: + *output = media::VideoCaptureError:: + kWinMediaFoundationGetMediaEventStatusFailed; + return true; + case media::mojom::VideoCaptureError::kMacSetCaptureDeviceFailed: + *output = media::VideoCaptureError::kMacSetCaptureDeviceFailed; + return true; + case media::mojom::VideoCaptureError::kMacCouldNotStartCaptureDevice: + *output = media::VideoCaptureError::kMacCouldNotStartCaptureDevice; + return true; + case media::mojom::VideoCaptureError:: + kMacReceivedFrameWithUnexpectedResolution: + *output = + media::VideoCaptureError::kMacReceivedFrameWithUnexpectedResolution; + return true; + case media::mojom::VideoCaptureError::kMacUpdateCaptureResolutionFailed: + *output = media::VideoCaptureError::kMacUpdateCaptureResolutionFailed; + return true; + case media::mojom::VideoCaptureError:: + kMacDeckLinkDeviceIdNotFoundInTheSystem: + *output = + media::VideoCaptureError::kMacDeckLinkDeviceIdNotFoundInTheSystem; + return true; + case media::mojom::VideoCaptureError:: + kMacDeckLinkErrorQueryingInputInterface: + *output = + media::VideoCaptureError::kMacDeckLinkErrorQueryingInputInterface; + return true; + case media::mojom::VideoCaptureError:: + kMacDeckLinkErrorCreatingDisplayModeIterator: + *output = media::VideoCaptureError:: + kMacDeckLinkErrorCreatingDisplayModeIterator; + return true; + case media::mojom::VideoCaptureError::kMacDeckLinkCouldNotFindADisplayMode: + *output = media::VideoCaptureError::kMacDeckLinkCouldNotFindADisplayMode; + return true; + case media::mojom::VideoCaptureError:: + kMacDeckLinkCouldNotSelectTheVideoFormatWeLike: + *output = media::VideoCaptureError:: + kMacDeckLinkCouldNotSelectTheVideoFormatWeLike; + return true; + case media::mojom::VideoCaptureError::kMacDeckLinkCouldNotStartCapturing: + *output = media::VideoCaptureError::kMacDeckLinkCouldNotStartCapturing; + return true; + case media::mojom::VideoCaptureError::kMacDeckLinkUnsupportedPixelFormat: + *output = media::VideoCaptureError::kMacDeckLinkUnsupportedPixelFormat; + return true; + case media::mojom::VideoCaptureError:: + kMacAvFoundationReceivedAVCaptureSessionRuntimeErrorNotification: + *output = media::VideoCaptureError:: + kMacAvFoundationReceivedAVCaptureSessionRuntimeErrorNotification; + return true; + case media::mojom::VideoCaptureError::kAndroidApi2ErrorConfiguringCamera: + *output = media::VideoCaptureError::kAndroidApi2ErrorConfiguringCamera; + return true; + } + NOTREACHED(); + return false; +} + +// static media::mojom::VideoFacingMode EnumTraits<media::mojom::VideoFacingMode, media::VideoFacingMode>::ToMojom( media::VideoFacingMode input) {
diff --git a/media/capture/mojom/video_capture_types_mojom_traits.h b/media/capture/mojom/video_capture_types_mojom_traits.h index 1b7649a..8cdfb46 100644 --- a/media/capture/mojom/video_capture_types_mojom_traits.h +++ b/media/capture/mojom/video_capture_types_mojom_traits.h
@@ -52,6 +52,15 @@ }; template <> +struct EnumTraits<media::mojom::VideoCaptureError, media::VideoCaptureError> { + static media::mojom::VideoCaptureError ToMojom( + media::VideoCaptureError buffer_type); + + static bool FromMojom(media::mojom::VideoCaptureError input, + media::VideoCaptureError* out); +}; + +template <> struct EnumTraits<media::mojom::VideoFacingMode, media::VideoFacingMode> { static media::mojom::VideoFacingMode ToMojom(media::VideoFacingMode input); static bool FromMojom(media::mojom::VideoFacingMode input,
diff --git a/media/capture/video/android/java/src/org/chromium/media/VideoCapture.java b/media/capture/video/android/java/src/org/chromium/media/VideoCapture.java index a69f654..7e9c9081 100644 --- a/media/capture/video/android/java/src/org/chromium/media/VideoCapture.java +++ b/media/capture/video/android/java/src/org/chromium/media/VideoCapture.java
@@ -228,7 +228,8 @@ long timestamp); // Method for VideoCapture implementations to signal an asynchronous error. - public native void nativeOnError(long nativeVideoCaptureDeviceAndroid, String message); + public native void nativeOnError( + long nativeVideoCaptureDeviceAndroid, int androidVideoCaptureError, String message); // Method for VideoCapture implementations to send Photos back to. public native void nativeOnPhotoTaken(
diff --git a/media/capture/video/android/java/src/org/chromium/media/VideoCaptureCamera.java b/media/capture/video/android/java/src/org/chromium/media/VideoCaptureCamera.java index 79ca13f6..db2be319 100644 --- a/media/capture/video/android/java/src/org/chromium/media/VideoCaptureCamera.java +++ b/media/capture/video/android/java/src/org/chromium/media/VideoCaptureCamera.java
@@ -142,7 +142,9 @@ private class CrErrorCallback implements android.hardware.Camera.ErrorCallback { @Override public void onError(int error, android.hardware.Camera camera) { - nativeOnError(mNativeVideoCaptureDeviceAndroid, "Error id: " + error); + nativeOnError(mNativeVideoCaptureDeviceAndroid, + AndroidVideoCaptureError.ANDROID_API_1_CAMERA_ERROR_CALLBACK_RECEIVED, + "Error id: " + error); synchronized (mPhotoTakenCallbackLock) { if (mPhotoTakenCallbackId == 0) return;
diff --git a/media/capture/video/android/java/src/org/chromium/media/VideoCaptureCamera2.java b/media/capture/video/android/java/src/org/chromium/media/VideoCaptureCamera2.java index 1f5ab3f..dbe5761 100644 --- a/media/capture/video/android/java/src/org/chromium/media/VideoCaptureCamera2.java +++ b/media/capture/video/android/java/src/org/chromium/media/VideoCaptureCamera2.java
@@ -59,7 +59,9 @@ if (createPreviewObjectsAndStartPreview()) return; changeCameraStateAndNotify(CameraState.STOPPED); - nativeOnError(mNativeVideoCaptureDeviceAndroid, "Error configuring camera"); + nativeOnError(mNativeVideoCaptureDeviceAndroid, + AndroidVideoCaptureError.ANDROID_API_2_ERROR_CONFIGURING_CAMERA, + "Error configuring camera"); } @Override @@ -77,6 +79,7 @@ mCameraDevice = null; changeCameraStateAndNotify(CameraState.STOPPED); nativeOnError(mNativeVideoCaptureDeviceAndroid, + AndroidVideoCaptureError.ANDROID_API_2_CAMERA_DEVICE_ERROR_RECEIVED, "Camera device error " + Integer.toString(error)); } }; @@ -126,7 +129,9 @@ // TODO(mcasas): When signalling error, C++ will tear us down. Is there need for // cleanup? changeCameraStateAndNotify(CameraState.STOPPED); - nativeOnError(mNativeVideoCaptureDeviceAndroid, "Camera session configuration error"); + nativeOnError(mNativeVideoCaptureDeviceAndroid, + AndroidVideoCaptureError.ANDROID_API_2_CAPTURE_SESSION_CONFIGURE_FAILED, + "Camera session configuration error"); } }; @@ -139,17 +144,22 @@ if (image == null) return; if (image.getFormat() != ImageFormat.YUV_420_888 || image.getPlanes().length != 3) { - nativeOnError(mNativeVideoCaptureDeviceAndroid, "Unexpected image format: " - + image.getFormat() + " or #planes: " + image.getPlanes().length); + nativeOnError(mNativeVideoCaptureDeviceAndroid, + AndroidVideoCaptureError + .ANDROID_API_2_IMAGE_READER_UNEXPECTED_IMAGE_FORMAT, + "Unexpected image format: " + image.getFormat() + + " or #planes: " + image.getPlanes().length); throw new IllegalStateException(); } if (reader.getWidth() != image.getWidth() || reader.getHeight() != image.getHeight()) { - nativeOnError(mNativeVideoCaptureDeviceAndroid, "ImageReader size (" - + reader.getWidth() + "x" + reader.getHeight() - + ") did not match Image size (" + image.getWidth() + "x" - + image.getHeight() + ")"); + nativeOnError(mNativeVideoCaptureDeviceAndroid, + AndroidVideoCaptureError + .ANDROID_API_2_IMAGE_READER_SIZE_DID_NOT_MATCH_IMAGE_SIZE, + "ImageReader size (" + reader.getWidth() + "x" + reader.getHeight() + + ") did not match Image size (" + image.getWidth() + "x" + + image.getHeight() + ")"); throw new IllegalStateException(); } @@ -254,7 +264,9 @@ if (createPreviewObjectsAndStartPreview()) return; - nativeOnError(mNativeVideoCaptureDeviceAndroid, "Error restarting preview"); + nativeOnError(mNativeVideoCaptureDeviceAndroid, + AndroidVideoCaptureError.ANDROID_API_2_ERROR_RESTARTING_PREVIEW, + "Error restarting preview"); } };
diff --git a/media/capture/video/android/video_capture_device_android.cc b/media/capture/video/android/video_capture_device_android.cc index cf6b4b0..5d496c50 100644 --- a/media/capture/video/android/video_capture_device_android.cc +++ b/media/capture/video/android/video_capture_device_android.cc
@@ -136,7 +136,8 @@ params.requested_format.frame_size.height(), params.requested_format.frame_rate); if (!ret) { - SetErrorState(FROM_HERE, "failed to allocate"); + SetErrorState(media::VideoCaptureError::kAndroidFailedToAllocate, FROM_HERE, + "failed to allocate"); return; } @@ -163,7 +164,8 @@ ret = Java_VideoCapture_startCapture(env, j_capture_); if (!ret) { - SetErrorState(FROM_HERE, "failed to start capture"); + SetErrorState(media::VideoCaptureError::kAndroidFailedToStartCapture, + FROM_HERE, "failed to start capture"); return; } @@ -185,7 +187,8 @@ const jboolean ret = Java_VideoCapture_stopCapture(env, j_capture_); if (!ret) { - SetErrorState(FROM_HERE, "failed to stop capture"); + SetErrorState(media::VideoCaptureError::kAndroidFailedToStopCapture, + FROM_HERE, "failed to stop capture"); return; } @@ -339,9 +342,11 @@ void VideoCaptureDeviceAndroid::OnError(JNIEnv* env, const JavaParamRef<jobject>& obj, + int android_video_capture_error, const JavaParamRef<jstring>& message) { - SetErrorState(FROM_HERE, - base::android::ConvertJavaStringToUTF8(env, message)); + SetErrorState( + static_cast<media::VideoCaptureError>(android_video_capture_error), + FROM_HERE, base::android::ConvertJavaStringToUTF8(env, message)); } void VideoCaptureDeviceAndroid::OnPhotoTaken( @@ -440,14 +445,15 @@ } } -void VideoCaptureDeviceAndroid::SetErrorState(const base::Location& from_here, +void VideoCaptureDeviceAndroid::SetErrorState(media::VideoCaptureError error, + const base::Location& from_here, const std::string& reason) { { base::AutoLock lock(lock_); state_ = kError; if (!client_) return; - client_->OnError(from_here, reason); + client_->OnError(error, from_here, reason); } }
diff --git a/media/capture/video/android/video_capture_device_android.h b/media/capture/video/android/video_capture_device_android.h index e3ea36e..500dea4c 100644 --- a/media/capture/video/android/video_capture_device_android.h +++ b/media/capture/video/android/video_capture_device_android.h
@@ -44,6 +44,20 @@ ANDROID_IMAGE_FORMAT_UNKNOWN = 0, }; + // A Java counterpart will be generated for this enum. + // The values of these are matched with the ones in media::VideoCaptureError + // to allow direct static_casting. + // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.media + enum class AndroidVideoCaptureError { + ANDROID_API_1_CAMERA_ERROR_CALLBACK_RECEIVED = 68, + ANDROID_API_2_CAMERA_DEVICE_ERROR_RECEIVED = 69, + ANDROID_API_2_CAPTURE_SESSION_CONFIGURE_FAILED = 70, + ANDROID_API_2_IMAGE_READER_UNEXPECTED_IMAGE_FORMAT = 71, + ANDROID_API_2_IMAGE_READER_SIZE_DID_NOT_MATCH_IMAGE_SIZE = 72, + ANDROID_API_2_ERROR_RESTARTING_PREVIEW = 73, + ANDROID_API_2_ERROR_CONFIGURING_CAMERA = 114, + }; + explicit VideoCaptureDeviceAndroid( const VideoCaptureDeviceDescriptor& device_descriptor); ~VideoCaptureDeviceAndroid() override; @@ -89,6 +103,7 @@ // Implement org.chromium.media.VideoCapture.nativeOnError. void OnError(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj, + int android_video_capture_error, const base::android::JavaParamRef<jstring>& message); // Implement org.chromium.media.VideoCapture.nativeOnPhotoTaken. @@ -128,7 +143,8 @@ }; VideoPixelFormat GetColorspace(); - void SetErrorState(const base::Location& from_here, + void SetErrorState(media::VideoCaptureError error, + const base::Location& from_here, const std::string& reason); void DoGetPhotoState(GetPhotoStateCallback callback);
diff --git a/media/capture/video/chromeos/camera_device_context.cc b/media/capture/video/chromeos/camera_device_context.cc index 32de506..d267a77 100644 --- a/media/capture/video/chromeos/camera_device_context.cc +++ b/media/capture/video/chromeos/camera_device_context.cc
@@ -30,12 +30,13 @@ return state_; } -void CameraDeviceContext::SetErrorState(const base::Location& from_here, +void CameraDeviceContext::SetErrorState(media::VideoCaptureError error, + const base::Location& from_here, const std::string& reason) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); state_ = State::kError; LOG(ERROR) << reason; - client_->OnError(from_here, reason); + client_->OnError(error, from_here, reason); } void CameraDeviceContext::LogToClient(std::string message) {
diff --git a/media/capture/video/chromeos/camera_device_context.h b/media/capture/video/chromeos/camera_device_context.h index 96bd7ed..83e34da 100644 --- a/media/capture/video/chromeos/camera_device_context.h +++ b/media/capture/video/chromeos/camera_device_context.h
@@ -102,7 +102,8 @@ // Sets state to kError and call |client_->OnError| to tear down the // VideoCaptureDevice. - void SetErrorState(const base::Location& from_here, + void SetErrorState(media::VideoCaptureError error, + const base::Location& from_here, const std::string& reason); // Logs |message| to |client_|.
diff --git a/media/capture/video/chromeos/camera_device_delegate.cc b/media/capture/video/chromeos/camera_device_delegate.cc index ad245ae3..9ccd214 100644 --- a/media/capture/video/chromeos/camera_device_delegate.cc +++ b/media/capture/video/chromeos/camera_device_delegate.cc
@@ -272,7 +272,9 @@ stream_buffer_manager_->StopPreview(); } device_context_->SetState(CameraDeviceContext::State::kStopped); - device_context_->SetErrorState(FROM_HERE, "Mojo connection error"); + device_context_->SetErrorState( + media::VideoCaptureError::kCrosHalV3DeviceDelegateMojoConnectionError, + FROM_HERE, "Mojo connection error"); ResetMojoInterface(); // We cannnot reset |device_context_| here because // |device_context_->SetErrorState| above will call StopAndDeAllocate later @@ -315,7 +317,9 @@ } if (result) { - device_context_->SetErrorState(FROM_HERE, "Failed to get camera info"); + device_context_->SetErrorState( + media::VideoCaptureError::kCrosHalV3DeviceDelegateFailedToGetCameraInfo, + FROM_HERE, "Failed to get camera info"); return; } SortCameraMetadata(&camera_info->static_camera_characteristics); @@ -330,6 +334,8 @@ *reinterpret_cast<int32_t*>((*sensor_orientation)->data.data())); } else { device_context_->SetErrorState( + media::VideoCaptureError:: + kCrosHalV3DeviceDelegateMissingSensorOrientationInfo, FROM_HERE, "Camera is missing required sensor orientation info"); return; } @@ -361,7 +367,10 @@ } if (result) { - device_context_->SetErrorState(FROM_HERE, "Failed to open camera device"); + device_context_->SetErrorState( + media::VideoCaptureError:: + kCrosHalV3DeviceDelegateFailedToOpenCameraDevice, + FROM_HERE, "Failed to open camera device"); return; } Initialize(); @@ -396,8 +405,11 @@ } if (result) { device_context_->SetErrorState( - FROM_HERE, std::string("Failed to initialize camera device: ") + - base::safe_strerror(-result)); + media::VideoCaptureError:: + kCrosHalV3DeviceDelegateFailedToInitializeCameraDevice, + FROM_HERE, + std::string("Failed to initialize camera device: ") + + base::safe_strerror(-result)); return; } device_context_->SetState(CameraDeviceContext::State::kInitialized); @@ -469,15 +481,21 @@ } if (result) { device_context_->SetErrorState( - FROM_HERE, std::string("Failed to configure streams: ") + - base::safe_strerror(-result)); + media::VideoCaptureError:: + kCrosHalV3DeviceDelegateFailedToConfigureStreams, + FROM_HERE, + std::string("Failed to configure streams: ") + + base::safe_strerror(-result)); return; } if (!updated_config || updated_config->streams.size() != kMaxConfiguredStreams) { device_context_->SetErrorState( - FROM_HERE, std::string("Wrong number of streams configured: ") + - std::to_string(updated_config->streams.size())); + media::VideoCaptureError:: + kCrosHalV3DeviceDelegateWrongNumberOfStreamsConfigured, + FROM_HERE, + std::string("Wrong number of streams configured: ") + + std::to_string(updated_config->streams.size())); return; } @@ -523,8 +541,10 @@ return; } if (!settings) { - device_context_->SetErrorState(FROM_HERE, - "Failed to get default request settings"); + device_context_->SetErrorState( + media::VideoCaptureError:: + kCrosHalV3DeviceDelegateFailedToGetDefaultRequestSettings, + FROM_HERE, "Failed to get default request settings"); return; } device_context_->SetState(CameraDeviceContext::State::kCapturing);
diff --git a/media/capture/video/chromeos/camera_device_delegate_unittest.cc b/media/capture/video/chromeos/camera_device_delegate_unittest.cc index aad0c9b..27ed4aa 100644 --- a/media/capture/video/chromeos/camera_device_delegate_unittest.cc +++ b/media/capture/video/chromeos/camera_device_delegate_unittest.cc
@@ -601,7 +601,7 @@ &CameraDeviceDelegateTest::QuitRunLoop, base::Unretained(this))))); }; - EXPECT_CALL(*mock_client, OnError(_, _)) + EXPECT_CALL(*mock_client, OnError(_, _, _)) .Times(AtLeast(1)) .WillOnce(InvokeWithoutArgs(stop_on_error));
diff --git a/media/capture/video/chromeos/mock_video_capture_client.cc b/media/capture/video/chromeos/mock_video_capture_client.cc index 29d57c5..85b4c86 100644 --- a/media/capture/video/chromeos/mock_video_capture_client.cc +++ b/media/capture/video/chromeos/mock_video_capture_client.cc
@@ -14,7 +14,7 @@ namespace unittest_internal { MockVideoCaptureClient::MockVideoCaptureClient() { - ON_CALL(*this, OnError(_, _)) + ON_CALL(*this, OnError(_, _, _)) .WillByDefault(Invoke(this, &MockVideoCaptureClient::DumpError)); } @@ -32,7 +32,8 @@ quit_cb_ = std::move(quit_cb); } -void MockVideoCaptureClient::DumpError(const base::Location& location, +void MockVideoCaptureClient::DumpError(media::VideoCaptureError, + const base::Location& location, const std::string& message) { DPLOG(ERROR) << location.ToString() << " " << message; }
diff --git a/media/capture/video/chromeos/mock_video_capture_client.h b/media/capture/video/chromeos/mock_video_capture_client.h index cd3452d..ce6f237 100644 --- a/media/capture/video/chromeos/mock_video_capture_client.h +++ b/media/capture/video/chromeos/mock_video_capture_client.h
@@ -20,8 +20,9 @@ MOCK_METHOD0(DoOnIncomingCapturedBuffer, void(void)); MOCK_METHOD0(DoOnIncomingCapturedVideoFrame, void(void)); MOCK_METHOD0(DoResurrectLastOutputBuffer, void(void)); - MOCK_METHOD2(OnError, - void(const base::Location& from_here, + MOCK_METHOD3(OnError, + void(media::VideoCaptureError error, + const base::Location& from_here, const std::string& reason)); MOCK_CONST_METHOD0(GetBufferPoolUtilization, double(void)); MOCK_METHOD0(OnStarted, void(void)); @@ -34,7 +35,9 @@ void SetQuitCb(base::OnceClosure quit_cb); - void DumpError(const base::Location& location, const std::string& message); + void DumpError(media::VideoCaptureError error, + const base::Location& location, + const std::string& message); void OnIncomingCapturedData(const uint8_t* data, int length,
diff --git a/media/capture/video/chromeos/stream_buffer_manager.cc b/media/capture/video/chromeos/stream_buffer_manager.cc index de74c1d..c443cc8 100644 --- a/media/capture/video/chromeos/stream_buffer_manager.cc +++ b/media/capture/video/chromeos/stream_buffer_manager.cc
@@ -99,6 +99,8 @@ const size_t kMaximumAllowedBuffers = 15; if (stream->max_buffers > kMaximumAllowedBuffers) { device_context_->SetErrorState( + media::VideoCaptureError:: + kCrosHalV3BufferManagerHalRequestedTooManyBuffers, FROM_HERE, std::string("Camera HAL requested ") + std::to_string(stream->max_buffers) + @@ -146,14 +148,18 @@ auto buffer = camera_buffer_factory_->CreateGpuMemoryBuffer( gfx::Size(buffer_width, buffer_height), stream_format.gfx_format); if (!buffer) { - device_context_->SetErrorState(FROM_HERE, - "Failed to create GpuMemoryBuffer"); + device_context_->SetErrorState( + media::VideoCaptureError:: + kCrosHalV3BufferManagerFailedToCreateGpuMemoryBuffer, + FROM_HERE, "Failed to create GpuMemoryBuffer"); return; } bool ret = buffer->Map(); if (!ret) { - device_context_->SetErrorState(FROM_HERE, - "Failed to map GpuMemoryBuffer"); + device_context_->SetErrorState( + media::VideoCaptureError:: + kCrosHalV3BufferManagerFailedToMapGpuMemoryBuffer, + FROM_HERE, "Failed to map GpuMemoryBuffer"); return; } stream_context_[stream_type]->buffers[j] = std::move(buffer); @@ -307,8 +313,11 @@ uint32_t drm_format = PixFormatVideoToDrm(buffer_format); if (!drm_format) { device_context_->SetErrorState( - FROM_HERE, std::string("Unsupported video pixel format") + - VideoPixelFormatToString(buffer_format)); + media::VideoCaptureError:: + kCrosHalV3BufferManagerUnsupportedVideoPixelFormat, + FROM_HERE, + std::string("Unsupported video pixel format") + + VideoPixelFormatToString(buffer_format)); return; } cros::mojom::HalPixelFormat hal_pixel_format = @@ -328,14 +337,18 @@ for (size_t i = 0; i < num_planes; ++i) { int dup_fd = dup(fd.get()); if (dup_fd == -1) { - device_context_->SetErrorState(FROM_HERE, "Failed to dup fd"); + device_context_->SetErrorState( + media::VideoCaptureError::kCrosHalV3BufferManagerFailedToDupFd, + FROM_HERE, "Failed to dup fd"); return; } planes[i].fd = mojo::WrapPlatformHandle(mojo::PlatformHandle(base::ScopedFD(dup_fd))); if (!planes[i].fd.is_valid()) { - device_context_->SetErrorState(FROM_HERE, - "Failed to wrap gpu memory handle"); + device_context_->SetErrorState( + media::VideoCaptureError:: + kCrosHalV3BufferManagerFailedToWrapGpuMemoryHandle, + FROM_HERE, "Failed to wrap gpu memory handle"); return; } planes[i].stride = buffer_handle.planes[i].stride; @@ -367,9 +380,11 @@ return; } if (result) { - device_context_->SetErrorState(FROM_HERE, - std::string("Failed to register buffer: ") + - base::safe_strerror(-result)); + device_context_->SetErrorState( + media::VideoCaptureError::kCrosHalV3BufferManagerFailedToRegisterBuffer, + FROM_HERE, + std::string("Failed to register buffer: ") + + base::safe_strerror(-result)); return; } stream_context_[stream_type]->registered_buffers.push(buffer_id); @@ -441,8 +456,11 @@ } if (result) { device_context_->SetErrorState( - FROM_HERE, std::string("Process capture request failed: ") + - base::safe_strerror(-result)); + media::VideoCaptureError:: + kCrosHalV3BufferManagerProcessCaptureRequestFailed, + FROM_HERE, + std::string("Process capture request failed: ") + + base::safe_strerror(-result)); return; } // Keeps the preview stream going. @@ -467,14 +485,20 @@ uint32_t result_id = result->partial_result; if (result_id > partial_result_count_) { device_context_->SetErrorState( - FROM_HERE, std::string("Invalid pending_result id: ") + - std::to_string(result_id)); + media::VideoCaptureError:: + kCrosHalV3BufferManagerInvalidPendingResultId, + FROM_HERE, + std::string("Invalid pending_result id: ") + + std::to_string(result_id)); return; } if (pending_result.partial_metadata_received.count(result_id)) { device_context_->SetErrorState( - FROM_HERE, std::string("Received duplicated partial metadata: ") + - std::to_string(result_id)); + media::VideoCaptureError:: + kCrosHalV3BufferManagerReceivedDuplicatedPartialMetadata, + FROM_HERE, + std::string("Received duplicated partial metadata: ") + + std::to_string(result_id)); return; } DVLOG(2) << "Received partial result " << result_id << " for frame " @@ -486,6 +510,8 @@ if (result->output_buffers) { if (result->output_buffers->size() > kMaxConfiguredStreams) { device_context_->SetErrorState( + media::VideoCaptureError:: + kCrosHalV3BufferManagerIncorrectNumberOfOutputBuffersReceived, FROM_HERE, std::string("Incorrect number of output buffers received: ") + std::to_string(result->output_buffers->size())); @@ -497,6 +523,8 @@ StreamType stream_type = StreamIdToStreamType(stream_buffer->stream_id); if (stream_type == StreamType::kUnknown) { device_context_->SetErrorState( + media::VideoCaptureError:: + kCrosHalV3BufferManagerInvalidTypeOfOutputBuffersReceived, FROM_HERE, std::string("Invalid type of output buffers received: ") + std::to_string(stream_buffer->stream_id)); @@ -508,6 +536,8 @@ if (stream_context_[stream_type]->capture_results_with_buffer.count( frame_number)) { device_context_->SetErrorState( + media::VideoCaptureError:: + kCrosHalV3BufferManagerReceivedMultipleResultBuffersForFrame, FROM_HERE, std::string("Received multiple result buffers for frame ") + std::to_string(frame_number) + std::string(" for stream ") + @@ -545,8 +575,11 @@ StreamType stream_type = StreamIdToStreamType(error_stream_id); if (stream_type == StreamType::kUnknown) { device_context_->SetErrorState( - FROM_HERE, std::string("Unknown stream in Camera3NotifyMsg: ") + - std::to_string(error_stream_id)); + media::VideoCaptureError:: + kCrosHalV3BufferManagerUnknownStreamInCamera3NotifyMsg, + FROM_HERE, + std::string("Unknown stream in Camera3NotifyMsg: ") + + std::to_string(error_stream_id)); return; } cros::mojom::Camera3ErrorMsgCode error_code = @@ -558,8 +591,11 @@ DVLOG(2) << "Received shutter time for frame " << frame_number; if (!shutter_time) { device_context_->SetErrorState( - FROM_HERE, std::string("Received invalid shutter time: ") + - std::to_string(shutter_time)); + media::VideoCaptureError:: + kCrosHalV3BufferManagerReceivedInvalidShutterTime, + FROM_HERE, + std::string("Received invalid shutter time: ") + + std::to_string(shutter_time)); return; } CaptureResult& pending_result = pending_results_[frame_number]; @@ -590,7 +626,9 @@ switch (error_code) { case cros::mojom::Camera3ErrorMsgCode::CAMERA3_MSG_ERROR_DEVICE: // Fatal error and no more frames will be produced by the device. - device_context_->SetErrorState(FROM_HERE, "Fatal device error"); + device_context_->SetErrorState( + media::VideoCaptureError::kCrosHalV3BufferManagerFatalDeviceError, + FROM_HERE, "Fatal device error"); return; case cros::mojom::Camera3ErrorMsgCode::CAMERA3_MSG_ERROR_REQUEST: @@ -684,9 +722,12 @@ ->capture_results_with_buffer.begin() ->first != frame_number) { device_context_->SetErrorState( - FROM_HERE, std::string("Received frame is out-of-order; expect ") + - std::to_string(pending_results_.begin()->first) + - std::string(" but got ") + std::to_string(frame_number)); + media::VideoCaptureError:: + kCrosHalV3BufferManagerReceivedFrameIsOutOfOrder, + FROM_HERE, + std::string("Received frame is out-of-order; expect ") + + std::to_string(pending_results_.begin()->first) + + std::string(" but got ") + std::to_string(frame_number)); return; } @@ -707,13 +748,17 @@ mojo::PlatformHandle fence = mojo::UnwrapPlatformHandle(std::move(stream_buffer->release_fence)); if (!fence.is_valid()) { - device_context_->SetErrorState(FROM_HERE, - "Failed to unwrap release fence fd"); + device_context_->SetErrorState( + media::VideoCaptureError:: + kCrosHalV3BufferManagerFailedToUnwrapReleaseFenceFd, + FROM_HERE, "Failed to unwrap release fence fd"); return; } if (!sync_wait(fence.GetFD().get(), kSyncWaitTimeoutMs)) { - device_context_->SetErrorState(FROM_HERE, - "Sync wait on release fence timed out"); + device_context_->SetErrorState( + media::VideoCaptureError:: + kCrosHalV3BufferManagerSyncWaitOnReleaseFenceTimedOut, + FROM_HERE, "Sync wait on release fence timed out"); return; } } @@ -738,7 +783,9 @@ reinterpret_cast<uintptr_t>(buffer->memory(0)) + buffer->GetSize().width() - sizeof(Camera3JpegBlob)); if (header->jpeg_blob_id != kCamera3JpegBlobId) { - device_context_->SetErrorState(FROM_HERE, "Invalid JPEG blob"); + device_context_->SetErrorState( + media::VideoCaptureError::kCrosHalV3BufferManagerInvalidJpegBlob, + FROM_HERE, "Invalid JPEG blob"); return; } mojom::BlobPtr blob = blobify_callback_.Run(
diff --git a/media/capture/video/chromeos/stream_buffer_manager_unittest.cc b/media/capture/video/chromeos/stream_buffer_manager_unittest.cc index dafe3d3c..df1efe7 100644 --- a/media/capture/video/chromeos/stream_buffer_manager_unittest.cc +++ b/media/capture/video/chromeos/stream_buffer_manager_unittest.cc
@@ -382,7 +382,7 @@ test->QuitCaptureLoop(); }, base::Unretained(this))); - EXPECT_CALL(*GetMockVideoCaptureClient(), OnError(_, _)) + EXPECT_CALL(*GetMockVideoCaptureClient(), OnError(_, _, _)) .Times(1) .WillOnce( InvokeWithoutArgs(this, &StreamBufferManagerTest::QuitCaptureLoop));
diff --git a/media/capture/video/chromeos/video_capture_device_chromeos_halv3.cc b/media/capture/video/chromeos/video_capture_device_chromeos_halv3.cc index 7b88f6e..a7e16cdb 100644 --- a/media/capture/video/chromeos/video_capture_device_chromeos_halv3.cc +++ b/media/capture/video/chromeos/video_capture_device_chromeos_halv3.cc
@@ -65,7 +65,9 @@ if (!camera_device_ipc_thread_.Start()) { std::string error_msg = "Failed to start device thread"; LOG(ERROR) << error_msg; - client->OnError(FROM_HERE, error_msg); + client->OnError( + media::VideoCaptureError::kCrosHalV3FailedToStartDeviceThread, + FROM_HERE, error_msg); return; } capture_params_ = params;
diff --git a/media/capture/video/fake_video_capture_device_factory.cc b/media/capture/video/fake_video_capture_device_factory.cc index b592a41b..ece8de1 100644 --- a/media/capture/video/fake_video_capture_device_factory.cc +++ b/media/capture/video/fake_video_capture_device_factory.cc
@@ -72,7 +72,9 @@ // VideoCaptureDevice implementation. void AllocateAndStart(const media::VideoCaptureParams& params, std::unique_ptr<Client> client) override { - client->OnError(FROM_HERE, "Device has no supported formats."); + client->OnError(media::VideoCaptureError:: + kErrorFakeDeviceIntentionallyEmittingErrorEvent, + FROM_HERE, "Device has no supported formats."); } void StopAndDeAllocate() override {}
diff --git a/media/capture/video/fake_video_capture_device_unittest.cc b/media/capture/video/fake_video_capture_device_unittest.cc index 1e524d5..749d0400 100644 --- a/media/capture/video/fake_video_capture_device_unittest.cc +++ b/media/capture/video/fake_video_capture_device_unittest.cc
@@ -144,7 +144,7 @@ image_capture_client_(new ImageCaptureClient()), video_capture_device_factory_(new FakeVideoCaptureDeviceFactory()) {} - void SetUp() override { EXPECT_CALL(*client_, OnError(_, _)).Times(0); } + void SetUp() override { EXPECT_CALL(*client_, OnError(_, _, _)).Times(0); } std::unique_ptr<MockVideoCaptureDeviceClient> CreateClient() { auto result = std::make_unique<MockVideoCaptureDeviceClient>(); @@ -243,7 +243,7 @@ for (const auto& resolution : resolutions_to_test) { std::unique_ptr<MockVideoCaptureDeviceClient> client = CreateClient(); - EXPECT_CALL(*client, OnError(_, _)).Times(0); + EXPECT_CALL(*client, OnError(_, _, _)).Times(0); EXPECT_CALL(*client, OnStarted()); VideoCaptureParams capture_params; @@ -328,7 +328,7 @@ TEST_F(FakeVideoCaptureDeviceTest, ErrorDeviceReportsError) { auto device = FakeVideoCaptureDeviceFactory::CreateErrorDevice(); ASSERT_TRUE(device); - EXPECT_CALL(*client_, OnError(_, _)); + EXPECT_CALL(*client_, OnError(_, _, _)); VideoCaptureParams capture_params; capture_params.requested_format.frame_size.SetSize(640, 480); capture_params.requested_format.frame_rate = 30.0; @@ -499,7 +499,7 @@ EXPECT_TRUE(device.get()); auto client = CreateClient(); - EXPECT_CALL(*client, OnError(_, _)); + EXPECT_CALL(*client, OnError(_, _, _)); VideoCaptureParams capture_params; capture_params.requested_format.frame_size.SetSize(1280, 720); device->AllocateAndStart(capture_params, std::move(client));
diff --git a/media/capture/video/file_video_capture_device.cc b/media/capture/video/file_video_capture_device.cc index c942ac87..1eb45655 100644 --- a/media/capture/video/file_video_capture_device.cc +++ b/media/capture/video/file_video_capture_device.cc
@@ -393,7 +393,9 @@ DCHECK(!file_parser_); file_parser_ = GetVideoFileParser(file_path_, &capture_format_); if (!file_parser_) { - client_->OnError(FROM_HERE, "Could not open Video file"); + client_->OnError( + VideoCaptureError::kFileVideoCaptureDeviceCouldNotOpenVideoFile, + FROM_HERE, "Could not open Video file"); return; }
diff --git a/media/capture/video/file_video_capture_device_unittest.cc b/media/capture/video/file_video_capture_device_unittest.cc index 9459ac47..9618bf3 100644 --- a/media/capture/video/file_video_capture_device_unittest.cc +++ b/media/capture/video/file_video_capture_device_unittest.cc
@@ -52,7 +52,7 @@ FileVideoCaptureDeviceTest() : client_(new MockVideoCaptureDeviceClient()) {} void SetUp() override { - EXPECT_CALL(*client_, OnError(_, _)).Times(0); + EXPECT_CALL(*client_, OnError(_, _, _)).Times(0); EXPECT_CALL(*client_, OnStarted()); device_ = std::make_unique<FileVideoCaptureDevice>( GetTestDataFilePath("bear.mjpeg"));
diff --git a/media/capture/video/linux/v4l2_capture_delegate.cc b/media/capture/video/linux/v4l2_capture_delegate.cc index dc08d20..fa91ce3 100644 --- a/media/capture/video/linux/v4l2_capture_delegate.cc +++ b/media/capture/video/linux/v4l2_capture_delegate.cc
@@ -257,7 +257,8 @@ device_fd_.reset( HANDLE_EINTR(v4l2_->open(device_descriptor_.device_id.c_str(), O_RDWR))); if (!device_fd_.is_valid()) { - SetErrorState(FROM_HERE, "Failed to open V4L2 device driver file."); + SetErrorState(VideoCaptureError::kV4L2FailedToOpenV4L2DeviceDriverFile, + FROM_HERE, "Failed to open V4L2 device driver file."); return; } @@ -269,7 +270,8 @@ ((cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) && !(cap.capabilities & V4L2_CAP_VIDEO_OUTPUT)))) { device_fd_.reset(); - SetErrorState(FROM_HERE, "This is not a V4L2 video capture device"); + SetErrorState(VideoCaptureError::kV4L2ThisIsNotAV4L2VideoCaptureDevice, + FROM_HERE, "This is not a V4L2 video capture device"); return; } @@ -287,7 +289,8 @@ best = std::find(desired_v4l2_formats.begin(), best, fmtdesc.pixelformat); } if (best == desired_v4l2_formats.end()) { - SetErrorState(FROM_HERE, "Failed to find a supported camera format."); + SetErrorState(VideoCaptureError::kV4L2FailedToFindASupportedCameraFormat, + FROM_HERE, "Failed to find a supported camera format."); return; } @@ -296,13 +299,15 @@ if (HANDLE_EINTR(v4l2_->ioctl(device_fd_.get(), VIDIOC_S_FMT, &video_fmt_)) < 0) { - SetErrorState(FROM_HERE, "Failed to set video capture format"); + SetErrorState(VideoCaptureError::kV4L2FailedToSetVideoCaptureFormat, + FROM_HERE, "Failed to set video capture format"); return; } const VideoPixelFormat pixel_format = V4l2FourCcToChromiumPixelFormat(video_fmt_.fmt.pix.pixelformat); if (pixel_format == PIXEL_FORMAT_UNKNOWN) { - SetErrorState(FROM_HERE, "Unsupported pixel format"); + SetErrorState(VideoCaptureError::kV4L2UnsupportedPixelFormat, FROM_HERE, + "Unsupported pixel format"); return; } @@ -322,7 +327,8 @@ if (HANDLE_EINTR( v4l2_->ioctl(device_fd_.get(), VIDIOC_S_PARM, &streamparm)) < 0) { - SetErrorState(FROM_HERE, "Failed to set camera framerate"); + SetErrorState(VideoCaptureError::kV4L2FailedToSetCameraFramerate, + FROM_HERE, "Failed to set camera framerate"); return; } DVLOG(2) << "Actual camera driverframerate: " @@ -356,12 +362,14 @@ FillV4L2RequestBuffer(&r_buffer, kNumVideoBuffers); if (HANDLE_EINTR(v4l2_->ioctl(device_fd_.get(), VIDIOC_REQBUFS, &r_buffer)) < 0) { - SetErrorState(FROM_HERE, "Error requesting MMAP buffers from V4L2"); + SetErrorState(VideoCaptureError::kV4L2ErrorRequestingMmapBuffers, FROM_HERE, + "Error requesting MMAP buffers from V4L2"); return; } for (unsigned int i = 0; i < r_buffer.count; ++i) { if (!MapAndQueueBuffer(i)) { - SetErrorState(FROM_HERE, "Allocate buffer failed"); + SetErrorState(VideoCaptureError::kV4L2AllocateBufferFailed, FROM_HERE, + "Allocate buffer failed"); return; } } @@ -369,7 +377,8 @@ v4l2_buf_type capture_type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if (HANDLE_EINTR( v4l2_->ioctl(device_fd_.get(), VIDIOC_STREAMON, &capture_type)) < 0) { - SetErrorState(FROM_HERE, "VIDIOC_STREAMON failed"); + SetErrorState(VideoCaptureError::kV4L2VidiocStreamonFailed, FROM_HERE, + "VIDIOC_STREAMON failed"); return; } @@ -388,7 +397,8 @@ v4l2_buf_type capture_type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if (HANDLE_EINTR(v4l2_->ioctl(device_fd_.get(), VIDIOC_STREAMOFF, &capture_type)) < 0) { - SetErrorState(FROM_HERE, "VIDIOC_STREAMOFF failed"); + SetErrorState(VideoCaptureError::kV4L2VidiocStreamoffFailed, FROM_HERE, + "VIDIOC_STREAMOFF failed"); return; } @@ -398,7 +408,8 @@ FillV4L2RequestBuffer(&r_buffer, 0); if (HANDLE_EINTR(v4l2_->ioctl(device_fd_.get(), VIDIOC_REQBUFS, &r_buffer)) < 0) - SetErrorState(FROM_HERE, "Failed to VIDIOC_REQBUFS with count = 0"); + SetErrorState(VideoCaptureError::kV4L2FailedToVidiocReqbufsWithCount0, + FROM_HERE, "Failed to VIDIOC_REQBUFS with count = 0"); // At this point we can close the device. // This is also needed for correctly changing settings later via VIDIOC_S_FMT. @@ -815,7 +826,7 @@ const int result = HANDLE_EINTR(v4l2_->poll(&device_pfd, 1, kCaptureTimeoutMs)); if (result < 0) { - SetErrorState(FROM_HERE, "Poll failed"); + SetErrorState(VideoCaptureError::kV4L2PollFailed, FROM_HERE, "Poll failed"); return; } @@ -824,8 +835,9 @@ if (result == 0) { timeout_count_++; if (timeout_count_ >= kContinuousTimeoutLimit) { - SetErrorState(FROM_HERE, - "Multiple continuous timeouts while read-polling."); + SetErrorState( + VideoCaptureError::kV4L2MultipleContinuousTimeoutsWhileReadPolling, + FROM_HERE, "Multiple continuous timeouts while read-polling."); timeout_count_ = 0; return; } @@ -840,7 +852,8 @@ if (HANDLE_EINTR(v4l2_->ioctl(device_fd_.get(), VIDIOC_DQBUF, &buffer)) < 0) { - SetErrorState(FROM_HERE, "Failed to dequeue capture buffer"); + SetErrorState(VideoCaptureError::kV4L2FailedToDequeueCaptureBuffer, + FROM_HERE, "Failed to dequeue capture buffer"); return; } @@ -887,7 +900,8 @@ if (HANDLE_EINTR(v4l2_->ioctl(device_fd_.get(), VIDIOC_QBUF, &buffer)) < 0) { - SetErrorState(FROM_HERE, "Failed to enqueue capture buffer"); + SetErrorState(VideoCaptureError::kV4L2FailedToEnqueueCaptureBuffer, + FROM_HERE, "Failed to enqueue capture buffer"); return; } } @@ -896,11 +910,12 @@ FROM_HERE, base::Bind(&V4L2CaptureDelegate::DoCapture, GetWeakPtr())); } -void V4L2CaptureDelegate::SetErrorState(const base::Location& from_here, +void V4L2CaptureDelegate::SetErrorState(VideoCaptureError error, + const base::Location& from_here, const std::string& reason) { DCHECK(v4l2_task_runner_->BelongsToCurrentThread()); is_capturing_ = false; - client_->OnError(from_here, reason); + client_->OnError(error, from_here, reason); } V4L2CaptureDelegate::BufferTracker::BufferTracker(V4L2CaptureDevice* v4l2)
diff --git a/media/capture/video/linux/v4l2_capture_delegate.h b/media/capture/video/linux/v4l2_capture_delegate.h index 7503343..03fb1fc4 100644 --- a/media/capture/video/linux/v4l2_capture_delegate.h +++ b/media/capture/video/linux/v4l2_capture_delegate.h
@@ -84,7 +84,8 @@ void DoCapture(); - void SetErrorState(const base::Location& from_here, + void SetErrorState(VideoCaptureError error, + const base::Location& from_here, const std::string& reason); V4L2CaptureDevice* const v4l2_;
diff --git a/media/capture/video/linux/video_capture_device_linux.cc b/media/capture/video/linux/video_capture_device_linux.cc index 808b74f..03b9d8d 100644 --- a/media/capture/video/linux/video_capture_device_linux.cc +++ b/media/capture/video/linux/video_capture_device_linux.cc
@@ -64,7 +64,9 @@ v4l2_.get(), device_descriptor_, v4l2_thread_.task_runner(), line_frequency); if (!capture_impl_) { - client->OnError(FROM_HERE, "Failed to create VideoCaptureDelegate"); + client->OnError(VideoCaptureError:: + kDeviceCaptureLinuxFailedToCreateVideoCaptureDelegate, + FROM_HERE, "Failed to create VideoCaptureDelegate"); return; } v4l2_thread_.task_runner()->PostTask(
diff --git a/media/capture/video/mac/video_capture_device_avfoundation_mac.mm b/media/capture/video/mac/video_capture_device_avfoundation_mac.mm index 6395d015..b445e3b 100644 --- a/media/capture/video/mac/video_capture_device_avfoundation_mac.mm +++ b/media/capture/video/mac/video_capture_device_avfoundation_mac.mm
@@ -16,6 +16,7 @@ #include "base/mac/mac_util.h" #include "base/metrics/histogram_macros.h" #include "base/strings/string_util.h" +#include "base/strings/sys_string_conversions.h" #include "media/base/timestamp_constants.h" #include "media/capture/video/mac/video_capture_device_mac.h" #include "media/capture/video_capture_types.h" @@ -170,7 +171,7 @@ NSArray* devices = [AVCaptureDevice devices]; AVCaptureDevice* device = nil; for (device in devices) { - if ([[device uniqueID] UTF8String] == descriptor.device_id) + if (base::SysNSStringToUTF8([device uniqueID]) == descriptor.device_id) break; } if (device == nil) @@ -498,10 +499,13 @@ } - (void)sendErrorString:(NSString*)error { - DLOG(ERROR) << [error UTF8String]; + DLOG(ERROR) << base::SysNSStringToUTF8(error); base::AutoLock lock(lock_); if (frameReceiver_) - frameReceiver_->ReceiveError(FROM_HERE, [error UTF8String]); + frameReceiver_->ReceiveError( + media::VideoCaptureError:: + kMacAvFoundationReceivedAVCaptureSessionRuntimeErrorNotification, + FROM_HERE, base::SysNSStringToUTF8(error)); } @end
diff --git a/media/capture/video/mac/video_capture_device_decklink_mac.h b/media/capture/video/mac/video_capture_device_decklink_mac.h index 1d6ac9f..e642354 100644 --- a/media/capture/video/mac/video_capture_device_decklink_mac.h +++ b/media/capture/video/mac/video_capture_device_decklink_mac.h
@@ -62,7 +62,8 @@ base::TimeDelta timestamp); // Forwarder to VideoCaptureDevice::Client::OnError(). - void SendErrorString(const base::Location& from_here, + void SendErrorString(VideoCaptureError error, + const base::Location& from_here, const std::string& reason); // Forwarder to VideoCaptureDevice::Client::OnLog().
diff --git a/media/capture/video/mac/video_capture_device_decklink_mac.mm b/media/capture/video/mac/video_capture_device_decklink_mac.mm index 3e9a602a..53e9649 100644 --- a/media/capture/video/mac/video_capture_device_decklink_mac.mm +++ b/media/capture/video/mac/video_capture_device_decklink_mac.mm
@@ -73,7 +73,8 @@ ULONG Release() override; // Forwarder to VideoCaptureDeviceDeckLinkMac::SendErrorString(). - void SendErrorString(const base::Location& from_here, + void SendErrorString(media::VideoCaptureError error, + const base::Location& from_here, const std::string& reason); // Forwarder to VideoCaptureDeviceDeckLinkMac::SendLogString(). @@ -150,21 +151,27 @@ } } if (!decklink_local.get()) { - SendErrorString(FROM_HERE, "Device id not found in the system"); + SendErrorString( + media::VideoCaptureError::kMacDeckLinkDeviceIdNotFoundInTheSystem, + FROM_HERE, "Device id not found in the system"); return; } ScopedDeckLinkPtr<IDeckLinkInput> decklink_input_local; if (decklink_local->QueryInterface( IID_IDeckLinkInput, decklink_input_local.ReceiveVoid()) != S_OK) { - SendErrorString(FROM_HERE, "Error querying input interface."); + SendErrorString( + media::VideoCaptureError::kMacDeckLinkErrorQueryingInputInterface, + FROM_HERE, "Error querying input interface."); return; } ScopedDeckLinkPtr<IDeckLinkDisplayModeIterator> display_mode_iter; if (decklink_input_local->GetDisplayModeIterator( display_mode_iter.Receive()) != S_OK) { - SendErrorString(FROM_HERE, "Error creating Display Mode Iterator"); + SendErrorString( + media::VideoCaptureError::kMacDeckLinkErrorCreatingDisplayModeIterator, + FROM_HERE, "Error creating Display Mode Iterator"); return; } @@ -185,7 +192,9 @@ display_mode.Release(); } if (!chosen_display_mode.get()) { - SendErrorString(FROM_HERE, "Could not find a display mode"); + SendErrorString( + media::VideoCaptureError::kMacDeckLinkCouldNotFindADisplayMode, + FROM_HERE, "Could not find a display mode"); return; } #if !defined(NDEBUG) @@ -201,13 +210,17 @@ if (decklink_input_local->EnableVideoInput( chosen_display_mode->GetDisplayMode(), bmdFormat8BitYUV, bmdVideoInputFlagDefault) != S_OK) { - SendErrorString(FROM_HERE, "Could not select the video format we like."); + SendErrorString(media::VideoCaptureError:: + kMacDeckLinkCouldNotSelectTheVideoFormatWeLike, + FROM_HERE, "Could not select the video format we like."); return; } decklink_input_local->SetCallback(this); if (decklink_input_local->StartStreams() != S_OK) - SendErrorString(FROM_HERE, "Could not start capturing"); + SendErrorString( + media::VideoCaptureError::kMacDeckLinkCouldNotStartCapturing, FROM_HERE, + "Could not start capturing"); if (frame_receiver_) frame_receiver_->ReportStarted(); @@ -254,7 +267,9 @@ pixel_format = media::PIXEL_FORMAT_ARGB; break; default: - SendErrorString(FROM_HERE, "Unsupported pixel format"); + SendErrorString( + media::VideoCaptureError::kMacDeckLinkUnsupportedPixelFormat, + FROM_HERE, "Unsupported pixel format"); break; } @@ -311,11 +326,12 @@ return ret_value; } -void DeckLinkCaptureDelegate::SendErrorString(const base::Location& from_here, +void DeckLinkCaptureDelegate::SendErrorString(media::VideoCaptureError error, + const base::Location& from_here, const std::string& reason) { base::AutoLock lock(lock_); if (frame_receiver_) - frame_receiver_->SendErrorString(from_here, reason); + frame_receiver_->SendErrorString(error, from_here, reason); } void DeckLinkCaptureDelegate::SendLogString(const std::string& message) { @@ -481,12 +497,13 @@ } void VideoCaptureDeviceDeckLinkMac::SendErrorString( + VideoCaptureError error, const base::Location& from_here, const std::string& reason) { DCHECK(thread_checker_.CalledOnValidThread()); base::AutoLock lock(lock_); if (client_) - client_->OnError(from_here, reason); + client_->OnError(error, from_here, reason); } void VideoCaptureDeviceDeckLinkMac::SendLogString(const std::string& message) {
diff --git a/media/capture/video/mac/video_capture_device_mac.h b/media/capture/video/mac/video_capture_device_mac.h index 92c07e18..ef1dc21 100644 --- a/media/capture/video/mac/video_capture_device_mac.h +++ b/media/capture/video/mac/video_capture_device_mac.h
@@ -87,7 +87,9 @@ void OnPhotoError(); // Forwarder to VideoCaptureDevice::Client::OnError(). - void ReceiveError(const base::Location& from_here, const std::string& reason); + void ReceiveError(VideoCaptureError error, + const base::Location& from_here, + const std::string& reason); // Forwarder to VideoCaptureDevice::Client::OnLog(). void LogMessage(const std::string& message); @@ -97,7 +99,8 @@ VideoCaptureTransportType transport_type); private: - void SetErrorState(const base::Location& from_here, + void SetErrorState(VideoCaptureError error, + const base::Location& from_here, const std::string& reason); bool UpdateCaptureResolution();
diff --git a/media/capture/video/mac/video_capture_device_mac.mm b/media/capture/video/mac/video_capture_device_mac.mm index 8e805dc..39fc01f2 100644 --- a/media/capture/video/mac/video_capture_device_mac.mm +++ b/media/capture/video/mac/video_capture_device_mac.mm
@@ -325,7 +325,8 @@ NSString* errorMessage = nil; if (![capture_device_ setCaptureDevice:deviceId errorMessage:&errorMessage]) { - SetErrorState(FROM_HERE, base::SysNSStringToUTF8(errorMessage)); + SetErrorState(VideoCaptureError::kMacSetCaptureDeviceFailed, FROM_HERE, + base::SysNSStringToUTF8(errorMessage)); return; } @@ -358,7 +359,8 @@ } if (![capture_device_ startCapture]) { - SetErrorState(FROM_HERE, "Could not start capture device."); + SetErrorState(VideoCaptureError::kMacCouldNotStartCaptureDevice, FROM_HERE, + "Could not start capture device."); return; } @@ -444,7 +446,8 @@ int aspect_denominator, base::TimeDelta timestamp) { if (capture_format_.frame_size != frame_format.frame_size) { - ReceiveError(FROM_HERE, + ReceiveError(VideoCaptureError::kMacReceivedFrameWithUnexpectedResolution, + FROM_HERE, "Captured resolution " + frame_format.frame_size.ToString() + ", and expected " + capture_format_.frame_size.ToString()); return; @@ -474,11 +477,13 @@ photo_callback_.Reset(); } -void VideoCaptureDeviceMac::ReceiveError(const base::Location& from_here, +void VideoCaptureDeviceMac::ReceiveError(VideoCaptureError error, + const base::Location& from_here, const std::string& reason) { task_runner_->PostTask( - FROM_HERE, base::Bind(&VideoCaptureDeviceMac::SetErrorState, - weak_factory_.GetWeakPtr(), from_here, reason)); + FROM_HERE, + base::BindOnce(&VideoCaptureDeviceMac::SetErrorState, + weak_factory_.GetWeakPtr(), error, from_here, reason)); } void VideoCaptureDeviceMac::LogMessage(const std::string& message) { @@ -511,18 +516,20 @@ return id_vendor + ":" + id_product; } -void VideoCaptureDeviceMac::SetErrorState(const base::Location& from_here, +void VideoCaptureDeviceMac::SetErrorState(VideoCaptureError error, + const base::Location& from_here, const std::string& reason) { DCHECK(task_runner_->BelongsToCurrentThread()); state_ = kError; - client_->OnError(from_here, reason); + client_->OnError(error, from_here, reason); } bool VideoCaptureDeviceMac::UpdateCaptureResolution() { if (![capture_device_ setCaptureHeight:capture_format_.frame_size.height() width:capture_format_.frame_size.width() frameRate:capture_format_.frame_rate]) { - ReceiveError(FROM_HERE, "Could not configure capture device."); + ReceiveError(VideoCaptureError::kMacUpdateCaptureResolutionFailed, + FROM_HERE, "Could not configure capture device."); return false; } return true;
diff --git a/media/capture/video/mock_video_capture_device_client.h b/media/capture/video/mock_video_capture_device_client.h index 54496204..558fbb2 100644 --- a/media/capture/video/mock_video_capture_device_client.h +++ b/media/capture/video/mock_video_capture_device_client.h
@@ -34,8 +34,9 @@ Buffer(const gfx::Size&, VideoPixelFormat, int)); MOCK_METHOD3(ResurrectLastOutputBuffer, Buffer(const gfx::Size&, VideoPixelFormat, int)); - MOCK_METHOD2(OnError, - void(const base::Location& from_here, + MOCK_METHOD3(OnError, + void(media::VideoCaptureError error, + const base::Location& from_here, const std::string& reason)); MOCK_METHOD0(OnStarted, void(void)); MOCK_CONST_METHOD0(GetBufferPoolUtilization, double(void));
diff --git a/media/capture/video/mock_video_frame_receiver.h b/media/capture/video/mock_video_frame_receiver.h index 71abcf7..3ae015e 100644 --- a/media/capture/video/mock_video_frame_receiver.h +++ b/media/capture/video/mock_video_frame_receiver.h
@@ -23,7 +23,7 @@ VideoCaptureDevice::Client::Buffer::ScopedAccessPermission>* buffer_read_permission, const gfx::Size&)); - MOCK_METHOD0(OnError, void()); + MOCK_METHOD1(OnError, void(media::VideoCaptureError error)); MOCK_METHOD1(OnLog, void(const std::string& message)); MOCK_METHOD1(OnBufferRetired, void(int buffer_id)); MOCK_METHOD0(OnStarted, void());
diff --git a/media/capture/video/video_capture_device.h b/media/capture/video/video_capture_device.h index a2642ba..b48ea664 100644 --- a/media/capture/video/video_capture_device.h +++ b/media/capture/video/video_capture_device.h
@@ -208,7 +208,8 @@ // An error has occurred that cannot be handled and VideoCaptureDevice must // be StopAndDeAllocate()-ed. |reason| is a text description of the error. - virtual void OnError(const base::Location& from_here, + virtual void OnError(VideoCaptureError error, + const base::Location& from_here, const std::string& reason) = 0; // VideoCaptureDevice requests the |message| to be logged.
diff --git a/media/capture/video/video_capture_device_client.cc b/media/capture/video/video_capture_device_client.cc index 64dd779f..7be73a4 100644 --- a/media/capture/video/video_capture_device_client.cc +++ b/media/capture/video/video_capture_device_client.cc
@@ -185,7 +185,8 @@ #if DCHECK_IS_ON() dropped_frame_counter_ = buffer.is_valid() ? 0 : dropped_frame_counter_ + 1; if (dropped_frame_counter_ >= kMaxDroppedFrames) - OnError(FROM_HERE, "Too many frames dropped"); + OnError(media::VideoCaptureError::kDeviceClientTooManyFramesDropped, + FROM_HERE, "Too many frames dropped"); #endif // Failed to reserve I420 output buffer, so drop the frame. if (!buffer.is_valid()) @@ -478,7 +479,8 @@ return MakeBufferStruct(buffer_pool_, buffer_id, new_frame_feedback_id); } -void VideoCaptureDeviceClient::OnError(const base::Location& from_here, +void VideoCaptureDeviceClient::OnError(VideoCaptureError error, + const base::Location& from_here, const std::string& reason) { const std::string log_message = base::StringPrintf( "error@ %s, %s, OS message: %s", from_here.ToString().c_str(), @@ -487,7 +489,7 @@ .c_str()); DLOG(ERROR) << log_message; OnLog(log_message); - receiver_->OnError(); + receiver_->OnError(error); } void VideoCaptureDeviceClient::OnLog(const std::string& message) { @@ -517,7 +519,8 @@ #if DCHECK_IS_ON() dropped_frame_counter_ = buffer.is_valid() ? 0 : dropped_frame_counter_ + 1; if (dropped_frame_counter_ >= kMaxDroppedFrames) - OnError(FROM_HERE, "Too many frames dropped"); + OnError(media::VideoCaptureError::kDeviceClientTooManyFramesDroppedY16, + FROM_HERE, "Too many frames dropped"); #endif // Failed to reserve output buffer, so drop the frame. if (!buffer.is_valid())
diff --git a/media/capture/video/video_capture_device_client.h b/media/capture/video/video_capture_device_client.h index 01dacc7..08723283 100644 --- a/media/capture/video/video_capture_device_client.h +++ b/media/capture/video/video_capture_device_client.h
@@ -86,7 +86,8 @@ Buffer ResurrectLastOutputBuffer(const gfx::Size& dimensions, VideoPixelFormat format, int new_frame_feedback_id) override; - void OnError(const base::Location& from_here, + void OnError(VideoCaptureError error, + const base::Location& from_here, const std::string& reason) override; void OnLog(const std::string& message) override; void OnStarted() override;
diff --git a/media/capture/video/video_capture_device_unittest.cc b/media/capture/video/video_capture_device_unittest.cc index 1c56003..06350bf 100644 --- a/media/capture/video/video_capture_device_unittest.cc +++ b/media/capture/video/video_capture_device_unittest.cc
@@ -114,7 +114,9 @@ closure.Run(); } -void DumpError(const base::Location& location, const std::string& message) { +void DumpError(media::VideoCaptureError, + const base::Location& location, + const std::string& message) { DPLOG(ERROR) << location.ToString() << " " << message; } @@ -254,7 +256,7 @@ std::unique_ptr<MockVideoCaptureDeviceClient> CreateDeviceClient() { auto result = std::make_unique<MockVideoCaptureDeviceClient>(); - ON_CALL(*result, OnError(_, _)).WillByDefault(Invoke(DumpError)); + ON_CALL(*result, OnError(_, _, _)).WillByDefault(Invoke(DumpError)); EXPECT_CALL(*result, ReserveOutputBuffer(_, _, _)).Times(0); EXPECT_CALL(*result, ResurrectLastOutputBuffer(_, _, _)).Times(0); EXPECT_CALL(*result, DoOnIncomingCapturedBuffer(_, _, _, _)).Times(0); @@ -420,7 +422,7 @@ #else // The presence of the actual device is only checked on AllocateAndStart() // and not on creation. - EXPECT_CALL(*video_capture_client_, OnError(_, _)).Times(1); + EXPECT_CALL(*video_capture_client_, OnError(_, _, _)).Times(1); VideoCaptureParams capture_params; capture_params.requested_format.frame_size.SetSize(640, 480); @@ -455,7 +457,7 @@ device_descriptors_->front())); ASSERT_TRUE(device); - EXPECT_CALL(*video_capture_client_, OnError(_, _)).Times(0); + EXPECT_CALL(*video_capture_client_, OnError(_, _, _)).Times(0); EXPECT_CALL(*video_capture_client_, OnStarted()); VideoCaptureParams capture_params; @@ -498,7 +500,7 @@ video_capture_device_factory_->CreateDevice(*descriptor)); ASSERT_TRUE(device); - EXPECT_CALL(*video_capture_client_, OnError(_, _)).Times(0); + EXPECT_CALL(*video_capture_client_, OnError(_, _, _)).Times(0); EXPECT_CALL(*video_capture_client_, OnStarted()); const gfx::Size input_size(640, 480); @@ -579,7 +581,7 @@ video_capture_device_factory_->CreateDevice(*device_descriptor)); ASSERT_TRUE(device); - EXPECT_CALL(*video_capture_client_, OnError(_, _)).Times(0); + EXPECT_CALL(*video_capture_client_, OnError(_, _, _)).Times(0); EXPECT_CALL(*video_capture_client_, OnStarted()); VideoCaptureParams capture_params; @@ -626,7 +628,7 @@ video_capture_device_factory_->CreateDevice(*descriptor)); ASSERT_TRUE(device); - EXPECT_CALL(*video_capture_client_, OnError(_, _)).Times(0); + EXPECT_CALL(*video_capture_client_, OnError(_, _, _)).Times(0); EXPECT_CALL(*video_capture_client_, OnStarted()); VideoCaptureParams capture_params; @@ -668,7 +670,7 @@ video_capture_device_factory_->CreateDevice(*descriptor)); ASSERT_TRUE(device); - EXPECT_CALL(*video_capture_client_, OnError(_, _)).Times(0); + EXPECT_CALL(*video_capture_client_, OnError(_, _, _)).Times(0); EXPECT_CALL(*video_capture_client_, OnStarted()); VideoCaptureParams capture_params; @@ -711,7 +713,7 @@ return; } - EXPECT_CALL(*video_capture_client_, OnError(_, _)).Times(0); + EXPECT_CALL(*video_capture_client_, OnError(_, _, _)).Times(0); EXPECT_CALL(*video_capture_client_, OnStarted()); std::unique_ptr<VideoCaptureDevice> device(
diff --git a/media/capture/video/video_frame_receiver.h b/media/capture/video/video_frame_receiver.h index 226f537..5cc5e58 100644 --- a/media/capture/video/video_frame_receiver.h +++ b/media/capture/video/video_frame_receiver.h
@@ -51,7 +51,7 @@ // with a new buffer via a call to OnNewBufferHandle(). virtual void OnBufferRetired(int buffer_id) = 0; - virtual void OnError() = 0; + virtual void OnError(VideoCaptureError error) = 0; virtual void OnLog(const std::string& message) = 0; virtual void OnStarted() = 0; virtual void OnStartedUsingGpuDecode() = 0;
diff --git a/media/capture/video/video_frame_receiver_on_task_runner.cc b/media/capture/video/video_frame_receiver_on_task_runner.cc index a49f93d..10691f2d 100644 --- a/media/capture/video/video_frame_receiver_on_task_runner.cc +++ b/media/capture/video/video_frame_receiver_on_task_runner.cc
@@ -30,11 +30,11 @@ std::unique_ptr<VideoCaptureDevice::Client::Buffer::ScopedAccessPermission> buffer_read_permission, mojom::VideoFrameInfoPtr frame_info) { - task_runner_->PostTask(FROM_HERE, - base::Bind(&VideoFrameReceiver::OnFrameReadyInBuffer, - receiver_, buffer_id, frame_feedback_id, - base::Passed(&buffer_read_permission), - base::Passed(&frame_info))); + task_runner_->PostTask( + FROM_HERE, base::BindOnce(&VideoFrameReceiver::OnFrameReadyInBuffer, + receiver_, buffer_id, frame_feedback_id, + base::Passed(&buffer_read_permission), + base::Passed(&frame_info))); } void VideoFrameReceiverOnTaskRunner::OnBufferRetired(int buffer_id) { @@ -43,25 +43,25 @@ base::Bind(&VideoFrameReceiver::OnBufferRetired, receiver_, buffer_id)); } -void VideoFrameReceiverOnTaskRunner::OnError() { - task_runner_->PostTask(FROM_HERE, - base::Bind(&VideoFrameReceiver::OnError, receiver_)); +void VideoFrameReceiverOnTaskRunner::OnError(VideoCaptureError error) { + task_runner_->PostTask(FROM_HERE, base::BindOnce(&VideoFrameReceiver::OnError, + receiver_, error)); } void VideoFrameReceiverOnTaskRunner::OnLog(const std::string& message) { - task_runner_->PostTask( - FROM_HERE, base::Bind(&VideoFrameReceiver::OnLog, receiver_, message)); + task_runner_->PostTask(FROM_HERE, base::BindOnce(&VideoFrameReceiver::OnLog, + receiver_, message)); } void VideoFrameReceiverOnTaskRunner::OnStarted() { - task_runner_->PostTask(FROM_HERE, - base::Bind(&VideoFrameReceiver::OnStarted, receiver_)); + task_runner_->PostTask( + FROM_HERE, base::BindOnce(&VideoFrameReceiver::OnStarted, receiver_)); } void VideoFrameReceiverOnTaskRunner::OnStartedUsingGpuDecode() { task_runner_->PostTask( FROM_HERE, - base::Bind(&VideoFrameReceiver::OnStartedUsingGpuDecode, receiver_)); + base::BindOnce(&VideoFrameReceiver::OnStartedUsingGpuDecode, receiver_)); } } // namespace media
diff --git a/media/capture/video/video_frame_receiver_on_task_runner.h b/media/capture/video/video_frame_receiver_on_task_runner.h index 7e7c70d..4e60d30 100644 --- a/media/capture/video/video_frame_receiver_on_task_runner.h +++ b/media/capture/video/video_frame_receiver_on_task_runner.h
@@ -33,7 +33,7 @@ buffer_read_permission, mojom::VideoFrameInfoPtr frame_info) override; void OnBufferRetired(int buffer_id) override; - void OnError() override; + void OnError(VideoCaptureError error) override; void OnLog(const std::string& message) override; void OnStarted() override; void OnStartedUsingGpuDecode() override;
diff --git a/media/capture/video/win/video_capture_device_mf_win.cc b/media/capture/video/win/video_capture_device_mf_win.cc index 198fa98..e8608f4 100644 --- a/media/capture/video/win/video_capture_device_mf_win.cc +++ b/media/capture/video/win/video_capture_device_mf_win.cc
@@ -626,20 +626,23 @@ DCHECK_EQ(false, is_started_); if (!engine_) { - OnError(FROM_HERE, E_FAIL); + OnError(VideoCaptureError::kWinMediaFoundationEngineIsNull, FROM_HERE, + E_FAIL); return; } ComPtr<IMFCaptureSource> source; HRESULT hr = engine_->GetSource(source.GetAddressOf()); if (FAILED(hr)) { - OnError(FROM_HERE, hr); + OnError(VideoCaptureError::kWinMediaFoundationEngineGetSourceFailed, + FROM_HERE, hr); return; } hr = FillCapabilities(source.Get(), true, &photo_capabilities_); if (FAILED(hr)) { - OnError(FROM_HERE, hr); + OnError(VideoCaptureError::kWinMediaFoundationFillPhotoCapabilitiesFailed, + FROM_HERE, hr); return; } @@ -651,12 +654,14 @@ CapabilityList video_capabilities; hr = FillCapabilities(source.Get(), false, &video_capabilities); if (FAILED(hr)) { - OnError(FROM_HERE, hr); + OnError(VideoCaptureError::kWinMediaFoundationFillVideoCapabilitiesFailed, + FROM_HERE, hr); return; } if (video_capabilities.empty()) { - OnError(FROM_HERE, "No video capability found"); + OnError(VideoCaptureError::kWinMediaFoundationNoVideoCapabilityFound, + FROM_HERE, "No video capability found"); return; } @@ -668,14 +673,18 @@ best_match_video_capability.media_type_index, source_video_media_type.GetAddressOf()); if (FAILED(hr)) { - OnError(FROM_HERE, hr); + OnError( + VideoCaptureError::kWinMediaFoundationGetAvailableDeviceMediaTypeFailed, + FROM_HERE, hr); return; } hr = source->SetCurrentDeviceMediaType( best_match_video_capability.stream_index, source_video_media_type.Get()); if (FAILED(hr)) { - OnError(FROM_HERE, hr); + OnError( + VideoCaptureError::kWinMediaFoundationSetCurrentDeviceMediaTypeFailed, + FROM_HERE, hr); return; } @@ -683,34 +692,42 @@ hr = engine_->GetSink(MF_CAPTURE_ENGINE_SINK_TYPE_PREVIEW, sink.GetAddressOf()); if (FAILED(hr)) { - OnError(FROM_HERE, hr); + OnError(VideoCaptureError::kWinMediaFoundationEngineGetSinkFailed, + FROM_HERE, hr); return; } ComPtr<IMFCapturePreviewSink> preview_sink; hr = sink->QueryInterface(IID_PPV_ARGS(preview_sink.GetAddressOf())); if (FAILED(hr)) { - OnError(FROM_HERE, hr); + OnError(VideoCaptureError:: + kWinMediaFoundationSinkQueryCapturePreviewInterfaceFailed, + FROM_HERE, hr); return; } hr = preview_sink->RemoveAllStreams(); if (FAILED(hr)) { - OnError(FROM_HERE, hr); + OnError(VideoCaptureError::kWinMediaFoundationSinkRemoveAllStreamsFailed, + FROM_HERE, hr); return; } ComPtr<IMFMediaType> sink_video_media_type; hr = MFCreateMediaType(sink_video_media_type.GetAddressOf()); if (FAILED(hr)) { - OnError(FROM_HERE, hr); + OnError( + VideoCaptureError::kWinMediaFoundationCreateSinkVideoMediaTypeFailed, + FROM_HERE, hr); return; } hr = ConvertToVideoSinkMediaType(source_video_media_type.Get(), sink_video_media_type.Get()); if (FAILED(hr)) { - OnError(FROM_HERE, hr); + OnError( + VideoCaptureError::kWinMediaFoundationConvertToVideoSinkMediaTypeFailed, + FROM_HERE, hr); return; } @@ -719,20 +736,23 @@ sink_video_media_type.Get(), NULL, &dw_sink_stream_index); if (FAILED(hr)) { - OnError(FROM_HERE, hr); + OnError(VideoCaptureError::kWinMediaFoundationSinkAddStreamFailed, + FROM_HERE, hr); return; } hr = preview_sink->SetSampleCallback(dw_sink_stream_index, video_callback_.get()); if (FAILED(hr)) { - OnError(FROM_HERE, hr); + OnError(VideoCaptureError::kWinMediaFoundationSinkSetSampleCallbackFailed, + FROM_HERE, hr); return; } hr = engine_->StartPreview(); if (FAILED(hr)) { - OnError(FROM_HERE, hr); + OnError(VideoCaptureError::kWinMediaFoundationEngineStartPreviewFailed, + FROM_HERE, hr); return; } @@ -992,19 +1012,23 @@ media_event->GetStatus(&hr); if (FAILED(hr)) - OnError(FROM_HERE, hr); + OnError(VideoCaptureError::kWinMediaFoundationGetMediaEventStatusFailed, + FROM_HERE, hr); } -void VideoCaptureDeviceMFWin::OnError(const Location& from_here, HRESULT hr) { - OnError(from_here, logging::SystemErrorCodeToString(hr).c_str()); +void VideoCaptureDeviceMFWin::OnError(VideoCaptureError error, + const Location& from_here, + HRESULT hr) { + OnError(error, from_here, logging::SystemErrorCodeToString(hr).c_str()); } -void VideoCaptureDeviceMFWin::OnError(const Location& from_here, +void VideoCaptureDeviceMFWin::OnError(VideoCaptureError error, + const Location& from_here, const char* message) { if (!client_.get()) return; - client_->OnError(from_here, + client_->OnError(error, from_here, base::StringPrintf("VideoCaptureDeviceMFWin: %s", message)); }
diff --git a/media/capture/video/win/video_capture_device_mf_win.h b/media/capture/video/win/video_capture_device_mf_win.h index a4a4acf..d567a0e 100644 --- a/media/capture/video/win/video_capture_device_mf_win.h +++ b/media/capture/video/win/video_capture_device_mf_win.h
@@ -108,8 +108,12 @@ HRESULT FillCapabilities(IMFCaptureSource* source, bool photo, CapabilityList* capabilities); - void OnError(const base::Location& from_here, HRESULT hr); - void OnError(const base::Location& from_here, const char* message); + void OnError(VideoCaptureError error, + const base::Location& from_here, + HRESULT hr); + void OnError(VideoCaptureError error, + const base::Location& from_here, + const char* message); VideoFacingMode facing_mode_; CreateMFPhotoCallbackCB create_mf_photo_callback_;
diff --git a/media/capture/video/win/video_capture_device_mf_win_unittest.cc b/media/capture/video/win/video_capture_device_mf_win_unittest.cc index bcccee0b..45177db 100644 --- a/media/capture/video/win/video_capture_device_mf_win_unittest.cc +++ b/media/capture/video/win/video_capture_device_mf_win_unittest.cc
@@ -60,7 +60,10 @@ MOCK_METHOD3(ResurrectLastOutputBuffer, Buffer(const gfx::Size&, VideoPixelFormat, int)); - MOCK_METHOD2(OnError, void(const base::Location&, const std::string&)); + MOCK_METHOD3(OnError, + void(VideoCaptureError, + const base::Location&, + const std::string&)); double GetBufferPoolUtilization() const override { return 0.0; } @@ -1069,7 +1072,7 @@ EXPECT_CALL(*(engine_.Get()), OnStartPreview()); EXPECT_CALL(*client_, OnStarted()); - EXPECT_CALL(*client_, OnError(_, _)); + EXPECT_CALL(*client_, OnError(_, _, _)); scoped_refptr<MockMFMediaEvent> media_event_error = new MockMFMediaEvent(); EXPECT_CALL(*media_event_error, DoGetStatus()).WillRepeatedly(Return(E_FAIL)); @@ -1138,7 +1141,7 @@ EXPECT_CALL(*capture_source_, DoGetDeviceStreamCount(_)) .WillRepeatedly(Return(MF_E_INVALIDREQUEST)); - EXPECT_CALL(*client_, OnError(_, _)); + EXPECT_CALL(*client_, OnError(_, _, _)); device_->AllocateAndStart(VideoCaptureParams(), std::move(client_)); }
diff --git a/media/capture/video/win/video_capture_device_win.cc b/media/capture/video/win/video_capture_device_win.cc index ae1bf4d..8a8decc 100644 --- a/media/capture/video/win/video_capture_device_win.cc +++ b/media/capture/video/win/video_capture_device_win.cc
@@ -524,14 +524,18 @@ ComPtr<IAMStreamConfig> stream_config; HRESULT hr = output_capture_pin_.CopyTo(stream_config.GetAddressOf()); if (FAILED(hr)) { - SetErrorState(FROM_HERE, "Can't get the Capture format settings", hr); + SetErrorState( + media::VideoCaptureError::kWinDirectShowCantGetCaptureFormatSettings, + FROM_HERE, "Can't get the Capture format settings", hr); return; } int count = 0, size = 0; hr = stream_config->GetNumberOfCapabilities(&count, &size); if (FAILED(hr)) { - SetErrorState(FROM_HERE, "Failed to GetNumberOfCapabilities", hr); + SetErrorState( + media::VideoCaptureError::kWinDirectShowFailedToGetNumberOfCapabilities, + FROM_HERE, "Failed to GetNumberOfCapabilities", hr); return; } @@ -544,7 +548,9 @@ hr = stream_config->GetStreamCaps(found_capability.media_type_index, media_type.Receive(), caps.get()); if (hr != S_OK) { - SetErrorState(FROM_HERE, "Failed to get capture device capabilities", hr); + SetErrorState(media::VideoCaptureError:: + kWinDirectShowFailedToGetCaptureDeviceCapabilities, + FROM_HERE, "Failed to get capture device capabilities", hr); return; } if (media_type->formattype == FORMAT_VideoInfo) { @@ -560,7 +566,9 @@ // Order the capture device to use this format. hr = stream_config->SetFormat(media_type.get()); if (FAILED(hr)) { - SetErrorState(FROM_HERE, "Failed to set capture device output format", hr); + SetErrorState(media::VideoCaptureError:: + kWinDirectShowFailedToSetCaptureDeviceOutputFormat, + FROM_HERE, "Failed to set capture device output format", hr); return; } capture_format_ = found_capability.supported_format; @@ -578,20 +586,26 @@ } if (FAILED(hr)) { - SetErrorState(FROM_HERE, "Failed to connect the Capture graph.", hr); + SetErrorState( + media::VideoCaptureError::kWinDirectShowFailedToConnectTheCaptureGraph, + FROM_HERE, "Failed to connect the Capture graph.", hr); return; } hr = media_control_->Pause(); if (FAILED(hr)) { - SetErrorState(FROM_HERE, "Failed to pause the Capture device", hr); + SetErrorState( + media::VideoCaptureError::kWinDirectShowFailedToPauseTheCaptureDevice, + FROM_HERE, "Failed to pause the Capture device", hr); return; } // Start capturing. hr = media_control_->Run(); if (FAILED(hr)) { - SetErrorState(FROM_HERE, "Failed to start the Capture device.", hr); + SetErrorState( + media::VideoCaptureError::kWinDirectShowFailedToStartTheCaptureDevice, + FROM_HERE, "Failed to start the Capture device.", hr); return; } @@ -606,7 +620,9 @@ HRESULT hr = media_control_->Stop(); if (FAILED(hr)) { - SetErrorState(FROM_HERE, "Failed to stop the capture graph.", hr); + SetErrorState( + media::VideoCaptureError::kWinDirectShowFailedToStopTheCaptureGraph, + FROM_HERE, "Failed to stop the capture graph.", hr); return; } @@ -928,12 +944,13 @@ } } -void VideoCaptureDeviceWin::SetErrorState(const base::Location& from_here, +void VideoCaptureDeviceWin::SetErrorState(media::VideoCaptureError error, + const base::Location& from_here, const std::string& reason, HRESULT hr) { DCHECK(thread_checker_.CalledOnValidThread()); DLOG_IF_FAILED_WITH_HRESULT(reason, hr); state_ = kError; - client_->OnError(from_here, reason); + client_->OnError(error, from_here, reason); } } // namespace media
diff --git a/media/capture/video/win/video_capture_device_win.h b/media/capture/video/win/video_capture_device_win.h index 53f52de..dbf7b959 100644 --- a/media/capture/video/win/video_capture_device_win.h +++ b/media/capture/video/win/video_capture_device_win.h
@@ -108,7 +108,8 @@ bool CreateCapabilityMap(); void SetAntiFlickerInCaptureFilter(const VideoCaptureParams& params); - void SetErrorState(const base::Location& from_here, + void SetErrorState(media::VideoCaptureError error, + const base::Location& from_here, const std::string& reason, HRESULT hr);
diff --git a/media/capture/video_capture_types.h b/media/capture/video_capture_types.h index cc7a5c42..e5509bf 100644 --- a/media/capture/video_capture_types.h +++ b/media/capture/video_capture_types.h
@@ -60,6 +60,128 @@ kMailboxHolder }; +// WARNING: Do not change the values assigned to the entries. They are used for +// UMA logging. +enum class VideoCaptureError { + kNone = 0, + kVideoCaptureControllerInvalidOrUnsupportedVideoCaptureParametersRequested = + 1, + kVideoCaptureControllerIsAlreadyInErrorState = 2, + kVideoCaptureManagerDeviceConnectionLost = 3, + kFrameSinkVideoCaptureDeviceAleradyEndedOnFatalError = 4, + kFrameSinkVideoCaptureDeviceEncounteredFatalError = 5, + kV4L2FailedToOpenV4L2DeviceDriverFile = 6, + kV4L2ThisIsNotAV4L2VideoCaptureDevice = 7, + kV4L2FailedToFindASupportedCameraFormat = 8, + kV4L2FailedToSetVideoCaptureFormat = 9, + kV4L2UnsupportedPixelFormat = 10, + kV4L2FailedToSetCameraFramerate = 11, + kV4L2ErrorRequestingMmapBuffers = 12, + kV4L2AllocateBufferFailed = 13, + kV4L2VidiocStreamonFailed = 14, + kV4L2VidiocStreamoffFailed = 15, + kV4L2FailedToVidiocReqbufsWithCount0 = 16, + kV4L2PollFailed = 17, + kV4L2MultipleContinuousTimeoutsWhileReadPolling = 18, + kV4L2FailedToDequeueCaptureBuffer = 19, + kV4L2FailedToEnqueueCaptureBuffer = 20, + kSingleClientVideoCaptureHostLostConnectionToDevice = 21, + kSingleClientVideoCaptureDeviceLaunchAborted = 22, + kDesktopCaptureDeviceWebrtcDesktopCapturerHasFailed = 23, + kFileVideoCaptureDeviceCouldNotOpenVideoFile = 24, + kDeviceCaptureLinuxFailedToCreateVideoCaptureDelegate = 25, + kErrorFakeDeviceIntentionallyEmittingErrorEvent = 26, + kDeviceClientTooManyFramesDropped = 27, + kDeviceClientTooManyFramesDroppedY16 = 28, + kDeviceMediaToMojoAdapterEncounteredUnsupportedBufferType = 29, + kVideoCaptureManagerProcessDeviceStartQueueDeviceInfoNotFound = 30, + kInProcessDeviceLauncherFailedToCreateDeviceInstance = 31, + kServiceDeviceLauncherLostConnectionToDeviceFactoryDuringDeviceStart = 32, + kServiceDeviceLauncherServiceRespondedWithDeviceNotFound = 33, + kServiceDeviceLauncherConnectionLostWhileWaitingForCallback = 34, + kIntentionalErrorRaisedByUnitTest = 35, + kCrosHalV3FailedToStartDeviceThread = 36, + kCrosHalV3DeviceDelegateMojoConnectionError = 37, + kCrosHalV3DeviceDelegateFailedToGetCameraInfo = 38, + kCrosHalV3DeviceDelegateMissingSensorOrientationInfo = 39, + kCrosHalV3DeviceDelegateFailedToOpenCameraDevice = 40, + kCrosHalV3DeviceDelegateFailedToInitializeCameraDevice = 41, + kCrosHalV3DeviceDelegateFailedToConfigureStreams = 42, + kCrosHalV3DeviceDelegateWrongNumberOfStreamsConfigured = 43, + kCrosHalV3DeviceDelegateFailedToGetDefaultRequestSettings = 44, + kCrosHalV3BufferManagerHalRequestedTooManyBuffers = 45, + kCrosHalV3BufferManagerFailedToCreateGpuMemoryBuffer = 46, + kCrosHalV3BufferManagerFailedToMapGpuMemoryBuffer = 47, + kCrosHalV3BufferManagerUnsupportedVideoPixelFormat = 48, + kCrosHalV3BufferManagerFailedToDupFd = 49, + kCrosHalV3BufferManagerFailedToWrapGpuMemoryHandle = 50, + kCrosHalV3BufferManagerFailedToRegisterBuffer = 51, + kCrosHalV3BufferManagerProcessCaptureRequestFailed = 52, + kCrosHalV3BufferManagerInvalidPendingResultId = 53, + kCrosHalV3BufferManagerReceivedDuplicatedPartialMetadata = 54, + kCrosHalV3BufferManagerIncorrectNumberOfOutputBuffersReceived = 55, + kCrosHalV3BufferManagerInvalidTypeOfOutputBuffersReceived = 56, + kCrosHalV3BufferManagerReceivedMultipleResultBuffersForFrame = 57, + kCrosHalV3BufferManagerUnknownStreamInCamera3NotifyMsg = 58, + kCrosHalV3BufferManagerReceivedInvalidShutterTime = 59, + kCrosHalV3BufferManagerFatalDeviceError = 60, + kCrosHalV3BufferManagerReceivedFrameIsOutOfOrder = 61, + kCrosHalV3BufferManagerFailedToUnwrapReleaseFenceFd = 62, + kCrosHalV3BufferManagerSyncWaitOnReleaseFenceTimedOut = 63, + kCrosHalV3BufferManagerInvalidJpegBlob = 64, + kAndroidFailedToAllocate = 65, + kAndroidFailedToStartCapture = 66, + kAndroidFailedToStopCapture = 67, + kAndroidApi1CameraErrorCallbackReceived = 68, + kAndroidApi2CameraDeviceErrorReceived = 69, + kAndroidApi2CaptureSessionConfigureFailed = 70, + kAndroidApi2ImageReaderUnexpectedImageFormat = 71, + kAndroidApi2ImageReaderSizeDidNotMatchImageSize = 72, + kAndroidApi2ErrorRestartingPreview = 73, + kAndroidScreenCaptureUnsupportedFormat = 74, + kAndroidScreenCaptureFailedToStartCaptureMachine = 75, + kAndroidScreenCaptureTheUserDeniedScreenCapture = 76, + kAndroidScreenCaptureFailedToStartScreenCapture = 77, + kWinDirectShowCantGetCaptureFormatSettings = 78, + kWinDirectShowFailedToGetNumberOfCapabilities = 79, + kWinDirectShowFailedToGetCaptureDeviceCapabilities = 80, + kWinDirectShowFailedToSetCaptureDeviceOutputFormat = 81, + kWinDirectShowFailedToConnectTheCaptureGraph = 82, + kWinDirectShowFailedToPauseTheCaptureDevice = 83, + kWinDirectShowFailedToStartTheCaptureDevice = 84, + kWinDirectShowFailedToStopTheCaptureGraph = 85, + kWinMediaFoundationEngineIsNull = 86, + kWinMediaFoundationEngineGetSourceFailed = 87, + kWinMediaFoundationFillPhotoCapabilitiesFailed = 88, + kWinMediaFoundationFillVideoCapabilitiesFailed = 89, + kWinMediaFoundationNoVideoCapabilityFound = 90, + kWinMediaFoundationGetAvailableDeviceMediaTypeFailed = 91, + kWinMediaFoundationSetCurrentDeviceMediaTypeFailed = 92, + kWinMediaFoundationEngineGetSinkFailed = 93, + kWinMediaFoundationSinkQueryCapturePreviewInterfaceFailed = 94, + kWinMediaFoundationSinkRemoveAllStreamsFailed = 95, + kWinMediaFoundationCreateSinkVideoMediaTypeFailed = 96, + kWinMediaFoundationConvertToVideoSinkMediaTypeFailed = 97, + kWinMediaFoundationSinkAddStreamFailed = 98, + kWinMediaFoundationSinkSetSampleCallbackFailed = 99, + kWinMediaFoundationEngineStartPreviewFailed = 100, + kWinMediaFoundationGetMediaEventStatusFailed = 101, + kMacSetCaptureDeviceFailed = 102, + kMacCouldNotStartCaptureDevice = 103, + kMacReceivedFrameWithUnexpectedResolution = 104, + kMacUpdateCaptureResolutionFailed = 105, + kMacDeckLinkDeviceIdNotFoundInTheSystem = 106, + kMacDeckLinkErrorQueryingInputInterface = 107, + kMacDeckLinkErrorCreatingDisplayModeIterator = 108, + kMacDeckLinkCouldNotFindADisplayMode = 109, + kMacDeckLinkCouldNotSelectTheVideoFormatWeLike = 110, + kMacDeckLinkCouldNotStartCapturing = 111, + kMacDeckLinkUnsupportedPixelFormat = 112, + kMacAvFoundationReceivedAVCaptureSessionRuntimeErrorNotification = 113, + kAndroidApi2ErrorConfiguringCamera = 114, + kMaxValue = 114 +}; + // Assert that the int:frequency mapping is correct. static_assert(static_cast<int>(PowerLineFrequency::FREQUENCY_DEFAULT) == 0, "static_cast<int>(FREQUENCY_DEFAULT) must equal 0.");
diff --git a/media/renderers/paint_canvas_video_renderer.cc b/media/renderers/paint_canvas_video_renderer.cc index 2e057b81..87ad624 100644 --- a/media/renderers/paint_canvas_video_renderer.cc +++ b/media/renderers/paint_canvas_video_renderer.cc
@@ -79,6 +79,28 @@ DISALLOW_IMPLICIT_CONSTRUCTORS(SyncTokenClientImpl); }; +sk_sp<SkImage> YUVGrBackendTexturesToSkImage(GrContext* gr_context, + gfx::ColorSpace video_color_space, + VideoPixelFormat video_format, + GrBackendTexture* textures) { + // TODO(hubbe): This should really default to rec709. + // https://crbug.com/828599 + SkYUVColorSpace color_space = kRec601_SkYUVColorSpace; + video_color_space.ToSkYUVColorSpace(&color_space); + + switch (video_format) { + case PIXEL_FORMAT_NV12: + return SkImage::MakeFromNV12TexturesCopy( + gr_context, color_space, textures, kTopLeft_GrSurfaceOrigin); + case PIXEL_FORMAT_I420: + return SkImage::MakeFromYUVTexturesCopy(gr_context, color_space, textures, + kTopLeft_GrSurfaceOrigin); + default: + NOTREACHED(); + return nullptr; + } +} + sk_sp<SkImage> NewSkImageFromVideoFrameYUVTextures( const VideoFrame* video_frame, const Context3D& context_3d) { @@ -145,19 +167,10 @@ GrMipMapped::kNo, source_textures[2]), }; - // TODO(hubbe): This should really default to rec709. - // https://crbug.com/828599 - SkYUVColorSpace color_space = kRec601_SkYUVColorSpace; - video_frame->ColorSpace().ToSkYUVColorSpace(&color_space); + sk_sp<SkImage> img = YUVGrBackendTexturesToSkImage( + context_3d.gr_context, video_frame->ColorSpace(), video_frame->format(), + textures); - sk_sp<SkImage> img; - if (video_frame->format() == PIXEL_FORMAT_NV12) { - img = SkImage::MakeFromNV12TexturesCopy(context_3d.gr_context, color_space, - textures, kTopLeft_GrSurfaceOrigin); - } else { - img = SkImage::MakeFromYUVTexturesCopy(context_3d.gr_context, color_space, - textures, kTopLeft_GrSurfaceOrigin); - } for (size_t i = 0; i < video_frame->NumTextures(); ++i) { gl->BindTexture(source_textures[i].fTarget, source_textures[i].fID); gl->TexParameteri(source_textures[i].fTarget, GL_TEXTURE_MIN_FILTER, @@ -222,6 +235,46 @@ kRGBA_8888_SkColorType); } +void VideoFrameCopyTextureOrSubTexture(gpu::gles2::GLES2Interface* gl, + const gfx::Size& coded_size, + const gfx::Rect& visible_rect, + GLuint source_texture, + unsigned int target, + unsigned int texture, + unsigned int internal_format, + unsigned int format, + unsigned int type, + int level, + bool premultiply_alpha, + bool flip_y) { + // The video is stored in a unmultiplied format, so premultiply if necessary. + // Application itself needs to take care of setting the right |flip_y| + // value down to get the expected result. + // "flip_y == true" means to reverse the video orientation while + // "flip_y == false" means to keep the intrinsic orientation. + if (visible_rect != gfx::Rect(coded_size)) { + // Must reallocate the destination texture and copy only a sub-portion. + + // There should always be enough data in the source texture to + // cover this copy. + DCHECK_LE(visible_rect.width(), coded_size.width()); + DCHECK_LE(visible_rect.height(), coded_size.height()); + + gl->BindTexture(target, texture); + gl->TexImage2D(target, level, internal_format, visible_rect.width(), + visible_rect.height(), 0, format, type, nullptr); + gl->CopySubTextureCHROMIUM(source_texture, 0, target, texture, level, 0, 0, + visible_rect.x(), visible_rect.y(), + visible_rect.width(), visible_rect.height(), + flip_y, premultiply_alpha, false); + + } else { + gl->CopyTextureCHROMIUM(source_texture, 0, target, texture, level, + internal_format, type, flip_y, premultiply_alpha, + false); + } +} + } // anonymous namespace // Generates an RGB image from a VideoFrame. Convert YUV to RGB plain on GPU. @@ -842,36 +895,10 @@ gl->WaitSyncTokenCHROMIUM(mailbox_holder.sync_token.GetConstData()); uint32_t source_texture = gl->CreateAndConsumeTextureCHROMIUM(mailbox_holder.mailbox.name); - - // The video is stored in a unmultiplied format, so premultiply - // if necessary. - // Application itself needs to take care of setting the right |flip_y| - // value down to get the expected result. - // "flip_y == true" means to reverse the video orientation while - // "flip_y == false" means to keep the intrinsic orientation. - if (video_frame->visible_rect().size() != video_frame->coded_size()) { - // Must reallocate the destination texture and copy only a sub-portion. - gfx::Rect dest_rect = video_frame->visible_rect(); -#if DCHECK_IS_ON() - // There should always be enough data in the source texture to - // cover this copy. - DCHECK_LE(dest_rect.width(), video_frame->coded_size().width()); - DCHECK_LE(dest_rect.height(), video_frame->coded_size().height()); -#endif - gl->BindTexture(target, texture); - gl->TexImage2D(target, level, internal_format, dest_rect.width(), - dest_rect.height(), 0, format, type, nullptr); - gl->CopySubTextureCHROMIUM(source_texture, 0, target, texture, level, 0, 0, - dest_rect.x(), dest_rect.y(), dest_rect.width(), - dest_rect.height(), flip_y, premultiply_alpha, - false); - - } else { - gl->CopyTextureCHROMIUM(source_texture, 0, target, texture, level, - internal_format, type, flip_y, premultiply_alpha, - false); - } - + VideoFrameCopyTextureOrSubTexture(gl, video_frame->coded_size(), + video_frame->visible_rect(), source_texture, + target, texture, internal_format, format, + type, level, premultiply_alpha, flip_y); gl->DeleteTextures(1, &source_texture); gl->Flush(); @@ -948,6 +975,119 @@ return true; } +bool PaintCanvasVideoRenderer::CopyVideoFrameYUVDataToGLTexture( + const Context3D& context_3d, + gpu::gles2::GLES2Interface* destination_gl, + const scoped_refptr<VideoFrame>& video_frame, + unsigned int target, + unsigned int texture, + unsigned int internal_format, + unsigned int format, + unsigned int type, + int level, + bool premultiply_alpha, + bool flip_y) { + if (!context_3d.gr_context) { + return false; + } + + if (!video_frame || !video_frame->IsMappable()) { + return false; + } + + if (video_frame->format() != media::PIXEL_FORMAT_I420) { + return false; + } + // Could handle NV12 here as well. See NewSkImageFromVideoFrameYUVTextures. + + static constexpr size_t kNumPlanes = 3; + DCHECK_EQ(video_frame->NumPlanes(video_frame->format()), kNumPlanes); + // Y,U,V GPU-side SkImages. (These must outlive the yuv_textures). + sk_sp<SkImage> yuv_images[kNumPlanes]{}; + // Y,U,V GPU textures from those SkImages. + // (A GrBackendTexture is a non-owned reference to the SkImage's texture.) + GrBackendTexture yuv_textures[kNumPlanes]{}; + + // Upload the whole coded image area (not visible rect). + gfx::Size y_tex_size = video_frame->coded_size(); + gfx::Size uv_tex_size((y_tex_size.width() + 1) / 2, + (y_tex_size.height() + 1) / 2); + + for (size_t plane = 0; plane < kNumPlanes; ++plane) { + const uint8_t* data = video_frame->data(plane); + int plane_stride = video_frame->stride(plane); + + bool is_y_plane = plane == media::VideoFrame::kYPlane; + gfx::Size tex_size = is_y_plane ? y_tex_size : uv_tex_size; + int data_size = plane_stride * (tex_size.height() - 1) + tex_size.width(); + + // Create a CPU-side SkImage from the channel. + sk_sp<SkData> sk_data = SkData::MakeWithoutCopy(data, data_size); + DCHECK(sk_data); + SkImageInfo image_info = + SkImageInfo::Make(tex_size.width(), tex_size.height(), + kGray_8_SkColorType, kUnknown_SkAlphaType); + sk_sp<SkImage> plane_image_cpu = + SkImage::MakeRasterData(image_info, sk_data, plane_stride); + DCHECK(plane_image_cpu); + + // Upload the CPU-side SkImage into a GPU-side SkImage. + // (Note the original video_frame data is no longer used after this point.) + yuv_images[plane] = + plane_image_cpu->makeTextureImage(context_3d.gr_context, nullptr); + DCHECK(yuv_images[plane]); + + // Extract the backend texture from the GPU-side image. + yuv_textures[plane] = yuv_images[plane]->getBackendTexture(false); + } + + // Decode 3 GPU-side Y,U,V SkImages into a GPU-side RGB SkImage. + sk_sp<SkImage> yuv_image = YUVGrBackendTexturesToSkImage( + context_3d.gr_context, video_frame->ColorSpace(), video_frame->format(), + yuv_textures); + if (!yuv_image) { + return false; + } + + GrGLTextureInfo src_texture_info{}; + yuv_image->getBackendTexture(false).getGLTextureInfo(&src_texture_info); + + gpu::gles2::GLES2Interface* source_gl = context_3d.gl; + gpu::MailboxHolder mailbox_holder; + mailbox_holder.texture_target = src_texture_info.fTarget; + source_gl->ProduceTextureDirectCHROMIUM(src_texture_info.fID, + mailbox_holder.mailbox.name); + + // Wait for mailbox creation on source context before consuming it and + // copying from it on the consumer context. + source_gl->GenUnverifiedSyncTokenCHROMIUM( + mailbox_holder.sync_token.GetData()); + + destination_gl->WaitSyncTokenCHROMIUM( + mailbox_holder.sync_token.GetConstData()); + uint32_t intermediate_texture = + destination_gl->CreateAndConsumeTextureCHROMIUM( + mailbox_holder.mailbox.name); + VideoFrameCopyTextureOrSubTexture( + destination_gl, video_frame->coded_size(), video_frame->visible_rect(), + intermediate_texture, target, texture, internal_format, format, type, + level, premultiply_alpha, flip_y); + destination_gl->DeleteTextures(1, &intermediate_texture); + + // Wait for destination context to consume mailbox before deleting it in + // source context. + gpu::SyncToken dest_sync_token; + destination_gl->GenUnverifiedSyncTokenCHROMIUM(dest_sync_token.GetData()); + source_gl->WaitSyncTokenCHROMIUM(dest_sync_token.GetConstData()); + + // video_frame->UpdateReleaseSyncToken is not necessary since the video frame + // data we used was CPU-side (IsMappable) to begin with. If there were any + // textures, we didn't use them. + + // The temporary SkImages should be automatically cleaned up here. + return true; +} + bool PaintCanvasVideoRenderer::TexImage2D( unsigned target, unsigned texture,
diff --git a/media/renderers/paint_canvas_video_renderer.h b/media/renderers/paint_canvas_video_renderer.h index d6b559c..d732111 100644 --- a/media/renderers/paint_canvas_video_renderer.h +++ b/media/renderers/paint_canvas_video_renderer.h
@@ -87,7 +87,7 @@ // |level|, |internal_format|, |type| specify target texture |texture|. // The format of |video_frame| must be VideoFrame::NATIVE_TEXTURE. // |context_3d| has a GrContext that may be used during the copy. - // CorrectLastImageDimensions() insures that the source texture will be + // CorrectLastImageDimensions() ensures that the source texture will be // cropped to |visible_rect|. Returns true on success. bool CopyVideoFrameTexturesToGLTexture( const Context3D& context_3d, @@ -102,6 +102,26 @@ bool premultiply_alpha, bool flip_y); + // Copy the CPU-side YUV contents of |video_frame| to texture |texture| in + // context |destination_gl|. + // |level|, |internal_format|, |type| specify target texture |texture|. + // The format of |video_frame| must be mappable. + // |context_3d| has a GrContext that may be used during the copy. + // CorrectLastImageDimensions() ensures that the source texture will be + // cropped to |visible_rect|. Returns true on success. + bool CopyVideoFrameYUVDataToGLTexture( + const Context3D& context_3d, + gpu::gles2::GLES2Interface* destination_gl, + const scoped_refptr<VideoFrame>& video_frame, + unsigned int target, + unsigned int texture, + unsigned int internal_format, + unsigned int format, + unsigned int type, + int level, + bool premultiply_alpha, + bool flip_y); + // Calls texImage2D where the texture image data source is the contents of // |video_frame|. Texture |texture| needs to be created and bound to |target| // before this call and the binding is active upon return.
diff --git a/net/http/transport_security_state_static.json b/net/http/transport_security_state_static.json index 874ba71d..1a72ce4 100644 --- a/net/http/transport_security_state_static.json +++ b/net/http/transport_security_state_static.json
@@ -69,6 +69,12 @@ "GTSCA1O1", "GlobalSignRootCA_R2" ], + "bad_static_spki_hashes": [ + "GlobalSignRootCA", + "GlobalSignExtendedValidationCA", + "GlobalSignExtendedValidationCA_G2", + "GlobalSignExtendedValidationCA_SHA256_G2" + ], "report_uri": "http://clients3.google.com/cert_upload_json" }, {
diff --git a/net/http/transport_security_state_static.pins b/net/http/transport_security_state_static.pins index 8415ee28..9f41460 100644 --- a/net/http/transport_security_state_static.pins +++ b/net/http/transport_security_state_static.pins
@@ -1260,6 +1260,92 @@ TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg== -----END CERTIFICATE----- +GlobalSignExtendedValidationCA +-----BEGIN CERTIFICATE----- +MIIEmDCCA4CgAwIBAgILBAAAAAABIg08FMUwDQYJKoZIhvcNAQEFBQAwTDEgMB4G +A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNp +Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDkwNjIzMTIwMDAwWhcNMjExMjE1 +MDcwMDAwWjBiMR8wHQYDVQQLExZFeHRlbmRlZCBWYWxpZGF0aW9uIENBMRMwEQYD +VQQKEwpHbG9iYWxTaWduMSowKAYDVQQDEyFHbG9iYWxTaWduIEV4dGVuZGVkIFZh +bGlkYXRpb24gQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC1Emt6 +QwnnRLFD0fgyHn2XJOtkPy/ieGsyjWyyRakXgmd/EWGtkLNGhEAjYVDxE70u/758 +XoXH2Q0c9e5Ecde4j4W2DkbMSSM1ITsl+lAtS33NK1Q/j+opI+qTDvyqhzbEZtcO +c/Xc8P0H+cGPeqBI397N2xkYMMrYg/F5rDaKn6jA0onrYKTtKlXFFQxjK8cLfjHO +wZsr+oalY032uubczjUhZs9YHMjzqi+My80kugG9J73V72nVdaHiorih7oivdX9f +8tIyEHc1H2n5AmKEf4onD3/6tr6Zcq59rJtyD1jDy8gStbiA4cCxwNHRhjX8cXwg +Lva4p7D8hCA2NoaZAgMBAAGjggFjMIIBXzAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0T +AQH/BAgwBgEB/wIBADBGBgNVHSAEPzA9MDsGBFUdIAAwMzAxBggrBgEFBQcCARYl +aHR0cDovL3d3dy5nbG9iYWxzaWduLm5ldC9yZXBvc2l0b3J5LzAdBgNVHQ4EFgQU +NLH5yYxrNUTMCGkK7uOjuVy/FuAwNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2Ny +bC5nbG9iYWxzaWduLm5ldC9yb290LXIyLmNybDBEBggrBgEFBQcBAQQ4MDYwNAYI +KwYBBQUHMAGGKGh0dHA6Ly9vY3NwLmdsb2JhbHNpZ24uY29tL0V4dGVuZGVkU1NM +Q0EwEQYJYIZIAYb4QgEBBAQDAgIEMCAGA1UdJQQZMBcGCisGAQQBgjcKAwMGCWCG +SAGG+EIEATAfBgNVHSMEGDAWgBSb4gdXZxwewGoG3lm0mi3f3BmGLjANBgkqhkiG +9w0BAQUFAAOCAQEAjptrWhnUYSEbidPudkEgnfANTeTyobGM8M5TaPLpLOJpzRcX +DLD+ad0jK8fZIn2OL45stDHsNOPH4vXNWAr1/FMi84Lm3E61MSI9ucfqTPybZokJ +XkrXdUttuVMS/2eqvhhaoqfFGO7TMZAgnUoWpqF8ro9C2AM47BslE+8MVdZ/Duvj +koUnTO2IngpODIlcvrUcr5HhGZzE3CMjtKjfEjkNW5gg0byMyBnAUHb1sfwX3cB3 +8KkEYSNuf2VuS9UN811ZObhHzTyPr5TCkUJ+BK2ZPQm/6x+ujNsCr7Zeh7n09LWg +cfeRNrdGKOurYGly9fYFM9G083hngPWK0N477g== +-----END CERTIFICATE----- + +GlobalSignExtendedValidationCA_G2 +-----BEGIN CERTIFICATE----- +MIIEhjCCA26gAwIBAgILBAAAAAABL07hXdQwDQYJKoZIhvcNAQEFBQAwTDEgMB4G +A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNp +Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMTEwNDEzMTAwMDAwWhcNMjIwNDEz +MTAwMDAwWjBZMQswCQYDVQQGEwJCRTEZMBcGA1UEChMQR2xvYmFsU2lnbiBudi1z +YTEvMC0GA1UEAxMmR2xvYmFsU2lnbiBFeHRlbmRlZCBWYWxpZGF0aW9uIENBIC0g +RzIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDNoUbMUpq4pbR/WNnN +2EugcgyXW6aIIMO5PUbc0FxSMPb6WU+FX7DbiLSpXysjSKyr9ZJ4FLYyD/tcaoVb +AJDgu2X1WvlPZ37HbCnsk8ArysRe2LDb1r4/mwvAj6ldrvcAAqT8umYROHf+IyAl +VRDFvYK5TLFoxuJwe4NcE2fBofN8C6iZmtDimyUxyCuNQPZSY7GgrVou9Xk2bTUs +Dt0F5NDiB0i3KF4r1VjVbNAMoQFGAVqPxq9kx1UBXeHRxmxQJaAFrQCrDI1la93r +wnJUyQ88ABeHIu/buYZ4FlGud9mmKE3zWI2DZ7k0JZscUYBR84OSaqOuR5rW5Isb +wO2xAgMBAAGjggFaMIIBVjAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB +/wIBADAdBgNVHQ4EFgQUsLBK/Rx1KPgcYaoT9vrBkD1rFqMwRwYDVR0gBEAwPjA8 +BgRVHSAAMDQwMgYIKwYBBQUHAgEWJmh0dHBzOi8vd3d3Lmdsb2JhbHNpZ24uY29t +L3JlcG9zaXRvcnkvMDYGA1UdHwQvMC0wK6ApoCeGJWh0dHA6Ly9jcmwuZ2xvYmFs +c2lnbi5uZXQvcm9vdC1yMi5jcmwwRAYIKwYBBQUHAQEEODA2MDQGCCsGAQUFBzAB +hihodHRwOi8vb2NzcC5nbG9iYWxzaWduLmNvbS9FeHRlbmRlZFNTTENBMCkGA1Ud +JQQiMCAGCCsGAQUFBwMBBggrBgEFBQcDAgYKKwYBBAGCNwoDAzAfBgNVHSMEGDAW +gBSb4gdXZxwewGoG3lm0mi3f3BmGLjANBgkqhkiG9w0BAQUFAAOCAQEAL0m28rZa +pJWrnlrpK4KbzJBrfHRFIOde2Mcj7ig1sTVlKqVR4FU/9oNntOQ2KbDa7JeVqYoF +o0X+Iy5SiLQfEICt0oufo1+oxetz3nmIQZgz7qdgGLFGyUAQB5yPClLJExoGbqCb +LTr2rk/no1E1KlsYBRLlUdy2NmLz4aQP++TPw5S/EauhWTEB8MxT7I9j12yW00gq +iiPtRVaoZkHqAblH7qFHDBTxI+Egc8p9UHxkOFejj0qcm+ltRc9Ea01gIEBxJbVG +qmwIft/I+shWKpLLg7h5CZctXqEBzgbttJfJBNxB7+BPNk3kQHNG7BESfIhbNCYl +TercGL7FG81kwA== +-----END CERTIFICATE----- + +GlobalSignExtendedValidationCA_SHA256_G2 +-----BEGIN CERTIFICATE----- +MIIEXTCCA0WgAwIBAgILBAAAAAABRE7wSlUwDQYJKoZIhvcNAQELBQAwTDEgMB4G +A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNp +Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMTQwMjIwMTAwMDAwWhcNMjExMjE1 +MDgwMDAwWjBiMQswCQYDVQQGEwJCRTEZMBcGA1UEChMQR2xvYmFsU2lnbiBudi1z +YTE4MDYGA1UEAxMvR2xvYmFsU2lnbiBFeHRlbmRlZCBWYWxpZGF0aW9uIENBIC0g +U0hBMjU2IC0gRzIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCj6qHS +w0nl9xxdr8OSQq+KPNzvTOYvXwwrn4pQMGbvTshPIUr25/JOG4xTV7CeyFv3uEZV +sxrtwmr+9BvsSEYOj+D74JEZ35kYby5Rr9r2mspkb5lUEHTqPMiqgE1DN/vIpH8F +nTeSvZgANVqvu1t0FQ68vMbpt4bn7q5NSwRMK6C0ZUi4wzrNdbs3yUrAARHZvz8V +hmAZazQgRvWGZg8k9Mxin5+eHf0QpJle8EHrsJT/LLM21usdpxdf385qd8eaxDJj +pwat8xIbnTByWQvrcusq0nd7kXfbAPzYb/Uv2HrFDDqge16Q852EWcgB2ZE3VuU6 +U5OtYEknJdnh2oLXAgMBAAGjggEoMIIBJDAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0T +AQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQU2kB3Q2Uc+P6n4/Rkgj5NQxMiMQIwRwYD +VR0gBEAwPjA8BgRVHSAAMDQwMgYIKwYBBQUHAgEWJmh0dHBzOi8vd3d3Lmdsb2Jh +bHNpZ24uY29tL3JlcG9zaXRvcnkvMDYGA1UdHwQvMC0wK6ApoCeGJWh0dHA6Ly9j +cmwuZ2xvYmFsc2lnbi5uZXQvcm9vdC1yMi5jcmwwPQYIKwYBBQUHAQEEMTAvMC0G +CCsGAQUFBzABhiFodHRwOi8vb2NzcC5nbG9iYWxzaWduLmNvbS9yb290cjIwHwYD +VR0jBBgwFoAUm+IHV2ccHsBqBt5ZtJot39wZhi4wDQYJKoZIhvcNAQELBQADggEB +AEDvEpCDdJaK+Tq6m1lKM9PvTBMrtZHLyZbtbvVsZPHGhLJGWVpYglLxNKBUQWQg +q9hXO9QUdHEYNswTwcdwwPVFZg5xroevkpTrcUAJ9Mx39xuThYpKrjOF5nSu9RCm +PslZg8P5XJb5KPc0e+k4xpE8T3FYdf7hVnV2zUDEFUA5qUH9ZBAPl4UH6Hlk0FtN +TJsnl9NzXpJ+H0jiyrkFl07vLBxrTYpfeFOVzQI5wi/maU/2cdGZtX9tIN5Dj9sA +G6M7N97RP23ztpB2Haydb4RPJJQJduCdqE33TTePpC9fS0HkSRaXzHtsrxHKllQJ +iyRRrl3tovG7UxBNl/oadwM= +-----END CERTIFICATE----- + GlobalSignRootCA_R3 -----BEGIN CERTIFICATE----- MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4G
diff --git a/net/third_party/quic/platform/impl/quic_file_utils_impl.h b/net/third_party/quic/platform/impl/quic_file_utils_impl.h index 9bee4f7..779498d 100644 --- a/net/third_party/quic/platform/impl/quic_file_utils_impl.h +++ b/net/third_party/quic/platform/impl/quic_file_utils_impl.h
@@ -5,7 +5,6 @@ #include "base/files/file_enumerator.h" #include "base/files/file_util.h" -#include "net/http/http_util.h" #include "net/third_party/quic/platform/api/quic_string.h" #include "net/third_party/quic/platform/impl/quic_file_utils_impl.h"
diff --git a/net/third_party/quic/tools/quic_simple_server_stream.h b/net/third_party/quic/tools/quic_simple_server_stream.h index 226210b..a8a0269 100644 --- a/net/third_party/quic/tools/quic_simple_server_stream.h +++ b/net/third_party/quic/tools/quic_simple_server_stream.h
@@ -6,9 +6,7 @@ #define NET_THIRD_PARTY_QUIC_TOOLS_QUIC_SIMPLE_SERVER_STREAM_H_ #include "base/macros.h" -#include "net/http/http_response_headers.h" #include "net/third_party/quic/core/http/quic_spdy_server_stream_base.h" -#include "net/third_party/quic/core/http/quic_spdy_stream.h" #include "net/third_party/quic/core/quic_packets.h" #include "net/third_party/quic/platform/api/quic_string_piece.h" #include "net/third_party/quic/tools/quic_backend_response.h"
diff --git a/net/third_party/spdy/core/spdy_test_utils.h b/net/third_party/spdy/core/spdy_test_utils.h index 69e7bb4..4b8adcd 100644 --- a/net/third_party/spdy/core/spdy_test_utils.h +++ b/net/third_party/spdy/core/spdy_test_utils.h
@@ -11,7 +11,6 @@ #include <map> #include <memory> -#include "net/spdy/server_push_delegate.h" #include "net/test/gtest_util.h" #include "net/third_party/spdy/core/spdy_bug_tracker.h" #include "net/third_party/spdy/core/spdy_header_block.h"
diff --git a/remoting/android/java/res/menu/desktop_actionbar.xml b/remoting/android/java/res/menu/desktop_actionbar.xml index e5df5f9..617768e 100644 --- a/remoting/android/java/res/menu/desktop_actionbar.xml +++ b/remoting/android/java/res/menu/desktop_actionbar.xml
@@ -27,6 +27,10 @@ <item android:id="@+id/actionbar_send_ctrl_alt_del" android:title="@string/send_ctrl_alt_del" app:showAsAction="withText"/> + <item android:id="@+id/resize_to_client" + android:checkable="true" + android:title="@string/resize_to_client" + app:showAsAction="never|withText"/> <item android:id="@+id/actionbar_disconnect" android:title="@string/disconnect_myself_button" app:showAsAction="withText"/>
diff --git a/remoting/android/java/src/org/chromium/chromoting/ChromotingUtil.java b/remoting/android/java/src/org/chromium/chromoting/ChromotingUtil.java index 3c7796d..592649c0 100644 --- a/remoting/android/java/src/org/chromium/chromoting/ChromotingUtil.java +++ b/remoting/android/java/src/org/chromium/chromoting/ChromotingUtil.java
@@ -12,6 +12,7 @@ import android.graphics.drawable.Drawable; import android.net.Uri; import android.support.v4.content.ContextCompat; +import android.util.DisplayMetrics; import android.util.TypedValue; import android.view.Menu; import android.view.MenuItem; @@ -93,4 +94,16 @@ public static boolean openUrl(Activity parentActivity, Uri uri) { return startActivitySafely(parentActivity, new Intent(Intent.ACTION_VIEW, uri)); } + + /** + * Converts a measurement in px to dp (density independent pixel). + * + * @param metrics The metrics used for conversion. + * @param value The value in px to be converted. + * @return The converted result in dp. + */ + public static int pxToDp(DisplayMetrics metrics, int value) { + // +0.5f to round up the result. + return (int) (value / metrics.density + 0.5f); + } }
diff --git a/remoting/android/java/src/org/chromium/chromoting/Desktop.java b/remoting/android/java/src/org/chromium/chromoting/Desktop.java index 8019814..37dc380 100644 --- a/remoting/android/java/src/org/chromium/chromoting/Desktop.java +++ b/remoting/android/java/src/org/chromium/chromoting/Desktop.java
@@ -15,6 +15,7 @@ import android.support.v7.app.ActionBar.OnMenuVisibilityListener; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; +import android.util.DisplayMetrics; import android.view.DisplayCutout; import android.view.KeyEvent; import android.view.Menu; @@ -55,6 +56,7 @@ /** Preference used to track the last input mode selected by the user. */ private static final String PREFERENCE_INPUT_MODE = "input_mode"; + private static final String PREFERENCE_RESIZE_TO_CLIENT = "resize_to_client"; /** The amount of time to wait to hide the ActionBar after user input is seen. */ private static final int ACTIONBAR_AUTO_HIDE_DELAY_MS = 3000; @@ -76,6 +78,9 @@ /** Indicates whether a Soft Input UI (such as a keyboard) is visible. */ private boolean mSoftInputVisible = false; + /** Indicates whether resize-to-client is enabled. */ + private boolean mResizeToClientEnabled = false; + /** Holds the scheduled task object which will be called to hide the ActionBar. */ private Runnable mActionBarAutoHideTask; @@ -154,6 +159,7 @@ mActivityLifecycleListener.onActivityCreated(this, savedInstanceState); mInputMode = getInitialInputModeValue(); + mResizeToClientEnabled = getStoredResizeToClientEnabled(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { attachSystemUiResizeListener(); @@ -283,6 +289,8 @@ // Wait to set the input mode until after the default tinting has been applied. setInputMode(mInputMode); + setResizeToClientEnabled(mResizeToClientEnabled); + // Keyboard state must be set after the keyboard icon has been added to the menu. setKeyboardState(getResources().getConfiguration()); @@ -352,6 +360,26 @@ new InputModeChangedEventParameter(mInputMode, mHostTouchCapability)); } + private boolean getStoredResizeToClientEnabled() { + return getPreferences(MODE_PRIVATE).getBoolean(PREFERENCE_RESIZE_TO_CLIENT, false); + } + + private void setResizeToClientEnabled(boolean resizeToClientEnabled) { + mResizeToClientEnabled = resizeToClientEnabled; + Menu menu = mToolbar.getMenu(); + MenuItem resizeToClientMenuItem = menu.findItem(R.id.resize_to_client); + resizeToClientMenuItem.setChecked(mResizeToClientEnabled); + if (mResizeToClientEnabled != getStoredResizeToClientEnabled()) { + getPreferences(MODE_PRIVATE) + .edit() + .putBoolean(PREFERENCE_RESIZE_TO_CLIENT, mResizeToClientEnabled) + .apply(); + } + if (mResizeToClientEnabled) { + sendPreferredHostResolution(); + } + } + @Override public void onCapabilitiesChanged(List<String> newCapabilities) { if (newCapabilities.contains(Capabilities.TOUCH_CAPABILITY)) { @@ -600,6 +628,9 @@ mInjector.sendCtrlAltDel(); return true; } + if (id == R.id.resize_to_client) { + setResizeToClientEnabled(!item.isChecked()); + } if (id == R.id.actionbar_help) { HelpSingleton.getInstance().launchHelp(this, HelpContext.DESKTOP); return true; @@ -670,6 +701,25 @@ } /** + * Sends preferred resolution to the host that matches the aspect ratio of the screen. This is + * calculated by the size of the DesktopView minus the safe insets. + * This method does nothing if resize-to-client has not been enabled by the user. + */ + public void sendPreferredHostResolution() { + if (!mResizeToClientEnabled) { + return; + } + + Rect safeInsets = getSafeInsets(); + int safeAreaWidth = mRemoteHostDesktop.getWidth() - safeInsets.left - safeInsets.right; + int safeAreaHeight = mRemoteHostDesktop.getHeight() - safeInsets.top - safeInsets.bottom; + DisplayMetrics metrics = getResources().getDisplayMetrics(); + safeAreaWidth = ChromotingUtil.pxToDp(metrics, safeAreaWidth); + safeAreaHeight = ChromotingUtil.pxToDp(metrics, safeAreaHeight); + mClient.sendClientResolution(safeAreaWidth, safeAreaHeight, metrics.density); + } + + /** * Called once when a keyboard key is pressed, then again when that same key is released. This * is not guaranteed to be notified of all soft keyboard events: certain keyboards might not * call it at all, while others might skip it in certain situations (e.g. swipe input).
diff --git a/remoting/android/java/src/org/chromium/chromoting/DesktopCanvas.java b/remoting/android/java/src/org/chromium/chromoting/DesktopCanvas.java index 4cb9970..e48a51c 100644 --- a/remoting/android/java/src/org/chromium/chromoting/DesktopCanvas.java +++ b/remoting/android/java/src/org/chromium/chromoting/DesktopCanvas.java
@@ -173,6 +173,9 @@ return; } + // Reset to identity so that screen dimensions and image dimensions match up. + mRenderData.transform.reset(); + float widthRatio = getSafeScreenWidth() / mRenderData.imageWidth; float heightRatio = getSafeScreenHeight() / mRenderData.imageHeight; float screenToImageScale = Math.max(widthRatio, heightRatio);
diff --git a/remoting/android/java/src/org/chromium/chromoting/TouchInputHandler.java b/remoting/android/java/src/org/chromium/chromoting/TouchInputHandler.java index c2a7e78..f160987 100644 --- a/remoting/android/java/src/org/chromium/chromoting/TouchInputHandler.java +++ b/remoting/android/java/src/org/chromium/chromoting/TouchInputHandler.java
@@ -389,6 +389,8 @@ mPanGestureBounds = new Rect( mEdgeSlopInPx, mEdgeSlopInPx, width - mEdgeSlopInPx, height - mEdgeSlopInPx); resizeImageToFitScreen(); + + mDesktop.sendPreferredHostResolution(); } private void handleHostSizeChanged(int width, int height) {
diff --git a/remoting/android/java/src/org/chromium/chromoting/jni/Client.java b/remoting/android/java/src/org/chromium/chromoting/jni/Client.java index 6b6a0a7a..48c3505 100644 --- a/remoting/android/java/src/org/chromium/chromoting/jni/Client.java +++ b/remoting/android/java/src/org/chromium/chromoting/jni/Client.java
@@ -292,6 +292,22 @@ nativeSendExtensionMessage(mNativeJniClient, type, data); } + /** + * Sends client resolution to the host so that the host can resize itself to fit the client + * without showing letterboxes. + * + * @param dipsWidth The width of the screen in density independent pixels. + * @param dipsHeight The height of the screen in density independent pixels. + * @param density The pixel density of the screen. + */ + public void sendClientResolution(int dipsWidth, int dipsHeight, float density) { + if (!mConnected) { + return; + } + + nativeSendClientResolution(mNativeJniClient, dipsWidth, dipsHeight, density); + } + private native long nativeInit(); private native void nativeDestroy(long nativeJniClient); @@ -336,4 +352,8 @@ /** Passes extension message to the native code. */ private native void nativeSendExtensionMessage(long nativeJniClient, String type, String data); + + /** Sends client resolution to the host. */ + private native void nativeSendClientResolution( + long nativeJniClient, int dipsWidth, int dipsHeight, float scale); }
diff --git a/remoting/client/chromoting_session.cc b/remoting/client/chromoting_session.cc index f9e457d..0074fbd1 100644 --- a/remoting/client/chromoting_session.cc +++ b/remoting/client/chromoting_session.cc
@@ -100,7 +100,7 @@ void SendKeyEvent(int usb_key_code, bool key_down); void SendTextEvent(const std::string& text); void SendTouchEvent(const protocol::TouchEvent& touch_event); - void SendClientResolution(int dips_width, int dips_height, int scale); + void SendClientResolution(int dips_width, int dips_height, float scale); void EnableVideoChannel(bool enable); void SendClientMessage(const std::string& type, const std::string& data); @@ -275,7 +275,7 @@ void ChromotingSession::Core::SendClientResolution(int dips_width, int dips_height, - int scale) { + float scale) { DCHECK(network_task_runner()->BelongsToCurrentThread()); protocol::ClientResolution client_resolution; client_resolution.set_dips_width(dips_width); @@ -708,7 +708,7 @@ void ChromotingSession::SendClientResolution(int dips_width, int dips_height, - int scale) { + float scale) { RunCoreTaskOnNetworkThread(FROM_HERE, &Core::SendClientResolution, dips_width, dips_height, scale); }
diff --git a/remoting/client/chromoting_session.h b/remoting/client/chromoting_session.h index ff84cf8..f45f93a 100644 --- a/remoting/client/chromoting_session.h +++ b/remoting/client/chromoting_session.h
@@ -118,7 +118,7 @@ // Sends the provided touch event payload to the host. void SendTouchEvent(const protocol::TouchEvent& touch_event); - void SendClientResolution(int dips_width, int dips_height, int scale); + void SendClientResolution(int dips_width, int dips_height, float scale); // Enables or disables the video channel. void EnableVideoChannel(bool enable);
diff --git a/remoting/client/jni/jni_client.cc b/remoting/client/jni/jni_client.cc index 41f3512..987281e 100644 --- a/remoting/client/jni/jni_client.cc +++ b/remoting/client/jni/jni_client.cc
@@ -287,6 +287,15 @@ ConvertJavaStringToUTF8(env, data)); } +void JniClient::SendClientResolution( + JNIEnv* env, + const base::android::JavaParamRef<jobject>& caller, + jint dips_width, + jint dips_height, + jfloat scale) { + session_->SendClientResolution(dips_width, dips_height, scale); +} + void JniClient::Destroy(JNIEnv* env, const JavaParamRef<jobject>& caller) { delete this; }
diff --git a/remoting/client/jni/jni_client.h b/remoting/client/jni/jni_client.h index 76528fe..7dc889c 100644 --- a/remoting/client/jni/jni_client.h +++ b/remoting/client/jni/jni_client.h
@@ -145,6 +145,12 @@ const base::android::JavaParamRef<jstring>& type, const base::android::JavaParamRef<jstring>& data); + void SendClientResolution(JNIEnv* env, + const base::android::JavaParamRef<jobject>& caller, + jint dips_width, + jint dips_height, + jfloat scale); + // Deletes this object. void Destroy(JNIEnv* env, const base::android::JavaParamRef<jobject>& caller);
diff --git a/remoting/resources/remoting_strings.grd b/remoting/resources/remoting_strings.grd index 45cd19a..9646d51 100644 --- a/remoting/resources/remoting_strings.grd +++ b/remoting/resources/remoting_strings.grd
@@ -1166,7 +1166,7 @@ <message desc="Label for button to reconnect to the previous Me2Me host. This button appears on the 'session-finished' page." name="IDS_RECONNECT"> Reconnect </message> - <message desc="Button for enabling or disabling the 'resize-to-client' functionality, whereby the host desktop is resized to match the client size as closely as possible." name="IDS_RESIZE_TO_CLIENT"> + <message desc="Button for enabling or disabling the 'resize-to-client' functionality, whereby the host desktop is resized to match the client size as closely as possible." name="IDS_RESIZE_TO_CLIENT" formatter_data="android_java"> Resize desktop to fit </message> <message desc="Label for button to retry connecting to a Me2Me host, after failing to connect to that host. This button appears on the 'session-finished' page." name="IDS_RETRY">
diff --git a/services/network/public/mojom/url_loader_factory.mojom b/services/network/public/mojom/url_loader_factory.mojom index 432de1c..139ad39 100644 --- a/services/network/public/mojom/url_loader_factory.mojom +++ b/services/network/public/mojom/url_loader_factory.mojom
@@ -10,7 +10,7 @@ const uint32 kURLLoadOptionNone = 0; // Sends the net::SSLInfo struct in OnReceiveResponse. const uint32 kURLLoadOptionSendSSLInfoWithResponse = 1; -// Enables mime sniffing. NOTE: this is only used with the network service. +// Enables mime sniffing. const uint32 kURLLoadOptionSniffMimeType = 2; // Indicates that execution is blocking on the completion of the request. const uint32 kURLLoadOptionSynchronous = 4;
diff --git a/services/video_capture/device_media_to_mojo_adapter.cc b/services/video_capture/device_media_to_mojo_adapter.cc index abfd571..24b3f452 100644 --- a/services/video_capture/device_media_to_mojo_adapter.cc +++ b/services/video_capture/device_media_to_mojo_adapter.cc
@@ -64,7 +64,9 @@ requested_settings.buffer_type != media::VideoCaptureBufferType::kSharedMemoryViaRawFileDescriptor) { // Buffer types other than shared memory are not supported. - media_receiver->OnError(); + media_receiver->OnError( + media::VideoCaptureError:: + kDeviceMediaToMojoAdapterEncounteredUnsupportedBufferType); return; }
diff --git a/services/video_capture/public/cpp/receiver_media_to_mojo_adapter.cc b/services/video_capture/public/cpp/receiver_media_to_mojo_adapter.cc index b78bb671..a8bade97 100644 --- a/services/video_capture/public/cpp/receiver_media_to_mojo_adapter.cc +++ b/services/video_capture/public/cpp/receiver_media_to_mojo_adapter.cc
@@ -52,8 +52,8 @@ receiver_->OnBufferRetired(buffer_id); } -void ReceiverMediaToMojoAdapter::OnError() { - receiver_->OnError(); +void ReceiverMediaToMojoAdapter::OnError(media::VideoCaptureError error) { + receiver_->OnError(error); } void ReceiverMediaToMojoAdapter::OnLog(const std::string& message) {
diff --git a/services/video_capture/public/cpp/receiver_media_to_mojo_adapter.h b/services/video_capture/public/cpp/receiver_media_to_mojo_adapter.h index 6cd81147..af34e4c0 100644 --- a/services/video_capture/public/cpp/receiver_media_to_mojo_adapter.h +++ b/services/video_capture/public/cpp/receiver_media_to_mojo_adapter.h
@@ -27,7 +27,7 @@ mojom::ScopedAccessPermissionPtr access_permission, media::mojom::VideoFrameInfoPtr frame_info) override; void OnBufferRetired(int32_t buffer_id) override; - void OnError() override; + void OnError(media::VideoCaptureError error) override; void OnLog(const std::string& message) override; void OnStarted() override; void OnStartedUsingGpuDecode() override;
diff --git a/services/video_capture/public/mojom/receiver.mojom b/services/video_capture/public/mojom/receiver.mojom index 7c3ff55..95807f6 100644 --- a/services/video_capture/public/mojom/receiver.mojom +++ b/services/video_capture/public/mojom/receiver.mojom
@@ -15,7 +15,7 @@ ScopedAccessPermission access_permission, media.mojom.VideoFrameInfo frame_info); OnBufferRetired(int32 buffer_id); - OnError(); + OnError(media.mojom.VideoCaptureError error); OnLog(string message); OnStarted(); OnStartedUsingGpuDecode();
diff --git a/services/video_capture/receiver_mojo_to_media_adapter.cc b/services/video_capture/receiver_mojo_to_media_adapter.cc index 4212430b..8f67704 100644 --- a/services/video_capture/receiver_mojo_to_media_adapter.cc +++ b/services/video_capture/receiver_mojo_to_media_adapter.cc
@@ -47,8 +47,8 @@ receiver_->OnBufferRetired(buffer_id); } -void ReceiverMojoToMediaAdapter::OnError() { - receiver_->OnError(); +void ReceiverMojoToMediaAdapter::OnError(media::VideoCaptureError error) { + receiver_->OnError(error); } void ReceiverMojoToMediaAdapter::OnLog(const std::string& message) {
diff --git a/services/video_capture/receiver_mojo_to_media_adapter.h b/services/video_capture/receiver_mojo_to_media_adapter.h index 00609b4..4808ff75 100644 --- a/services/video_capture/receiver_mojo_to_media_adapter.h +++ b/services/video_capture/receiver_mojo_to_media_adapter.h
@@ -31,7 +31,7 @@ access_permission, media::mojom::VideoFrameInfoPtr frame_info) override; void OnBufferRetired(int buffer_id) override; - void OnError() override; + void OnError(media::VideoCaptureError error) override; void OnLog(const std::string& message) override; void OnStarted() override; void OnStartedUsingGpuDecode() override;
diff --git a/services/video_capture/test/mock_receiver.h b/services/video_capture/test/mock_receiver.h index d0d792a..665132d 100644 --- a/services/video_capture/test/mock_receiver.h +++ b/services/video_capture/test/mock_receiver.h
@@ -34,7 +34,7 @@ mojom::ScopedAccessPermissionPtr*, media::mojom::VideoFrameInfoPtr*)); MOCK_METHOD1(OnBufferRetired, void(int32_t)); - MOCK_METHOD0(OnError, void()); + MOCK_METHOD1(OnError, void(media::VideoCaptureError)); MOCK_METHOD1(OnLog, void(const std::string&)); MOCK_METHOD0(OnStarted, void()); MOCK_METHOD0(OnStartedUsingGpuDecode, void());
diff --git a/storage/browser/blob/blob_reader.cc b/storage/browser/blob/blob_reader.cc index 6030c23b..542dcc6 100644 --- a/storage/browser/blob/blob_reader.cc +++ b/storage/browser/blob/blob_reader.cc
@@ -14,6 +14,7 @@ #include "base/bind.h" #include "base/callback_helpers.h" +#include "base/debug/alias.h" #include "base/memory/ptr_util.h" #include "base/task/post_task.h" #include "base/time/time.h" @@ -481,7 +482,21 @@ // Do the reading. const BlobDataItem& item = *items.at(current_item_index_); + + // TODO(https://crbug.com/864351): Temporary diagnostics. + uint64_t item_offset = item.offset(); + base::debug::Alias(&item_offset); + uint64_t item_length = item.length(); + base::debug::Alias(&item_length); + int buf_bytes_remaining = read_buf_->BytesRemaining(); + base::debug::Alias(&buf_bytes_remaining); + base::debug::Alias(&bytes_to_read); + if (item.type() == BlobDataItem::Type::kBytes) { + // TODO(https://crbug.com/864351): Temporary diagnostics. + const char* item_bytes = item.bytes().data(); + base::debug::Alias(&item_bytes); + ReadBytesItem(item, bytes_to_read); return Status::DONE; }
diff --git a/storage/browser/blob/mojo_blob_reader.cc b/storage/browser/blob/mojo_blob_reader.cc index 0c4e8f06..3f11019 100644 --- a/storage/browser/blob/mojo_blob_reader.cc +++ b/storage/browser/blob/mojo_blob_reader.cc
@@ -4,6 +4,7 @@ #include "storage/browser/blob/mojo_blob_reader.h" +#include "base/debug/alias.h" #include "base/trace_event/trace_event.h" #include "net/base/io_buffer.h" #include "services/network/public/cpp/net_adapters.h" @@ -99,17 +100,28 @@ TRACE_EVENT_ASYNC_END2("Blob", "BlobReader::CountSize", this, "result", "success", "size", blob_reader_->total_size()); + // TODO(https://crbug.com/864351): Temporary diagnostics. + net::HttpByteRange pre_bounds_range = byte_range_; + base::debug::Alias(&pre_bounds_range); + // Apply the range requirement. if (!byte_range_.ComputeBounds(blob_reader_->total_size())) { NotifyCompletedAndDeleteIfNeeded(net::ERR_REQUEST_RANGE_NOT_SATISFIABLE); return; } + // TODO(https://crbug.com/864351): Temporary diagnostics. + net::HttpByteRange post_bounds_range = byte_range_; + base::debug::Alias(&post_bounds_range); + DCHECK_LE(byte_range_.first_byte_position(), byte_range_.last_byte_position() + 1); uint64_t length = base::checked_cast<uint64_t>( byte_range_.last_byte_position() - byte_range_.first_byte_position() + 1); + // TODO(https://crbug.com/864351): Temporary diagnostics. + base::debug::Alias(&length); + if (blob_reader_->SetReadRange(byte_range_.first_byte_position(), length) != BlobReader::Status::DONE) { NotifyCompletedAndDeleteIfNeeded(blob_reader_->net_error());
diff --git a/storage/browser/fileapi/file_system_operation_runner.cc b/storage/browser/fileapi/file_system_operation_runner.cc index 015889f2..41f38a6 100644 --- a/storage/browser/fileapi/file_system_operation_runner.cc +++ b/storage/browser/fileapi/file_system_operation_runner.cc
@@ -689,6 +689,11 @@ base::WeakPtr<BeginOperationScoper> scope) { OperationHandle handle; handle.id = next_operation_id_++; + + // TODO(https://crbug.com/864351): Diagnostic to determine whether OperationID + // wrap-around is occurring in the wild. + DCHECK(operations_.find(handle.id) == operations_.end()); + operations_.emplace(handle.id, std::move(operation)); handle.scope = scope; return handle;
diff --git a/testing/buildbot/chromium.android.json b/testing/buildbot/chromium.android.json index edeee07..14c0b71 100644 --- a/testing/buildbot/chromium.android.json +++ b/testing/buildbot/chromium.android.json
@@ -17103,6 +17103,7 @@ "args": [ "--shared-prefs-file=//chrome/android/shared_preference_files/test/vr_ddview_skipdon_setupcomplete.json", "--replace-system-package=com.google.vr.vrcore,//third_party/gvr-android-sdk/test-apks/vr_services/vr_services_current.apk", + "--additional-apk=//third_party/gvr-android-sdk/test-apks/vr_keyboard/vr_keyboard_current.apk", "--gs-results-bucket=chromium-result-details", "--recover-devices" ], @@ -17141,6 +17142,7 @@ "args": [ "--shared-prefs-file=//chrome/android/shared_preference_files/test/vr_enable_vr_settings_service.json", "--replace-system-package=com.google.vr.vrcore,//third_party/gvr-android-sdk/test-apks/vr_services/vr_services_current.apk", + "--additional-apk=//third_party/gvr-android-sdk/test-apks/vr_keyboard/vr_keyboard_current.apk", "--annotation=Restriction=VR_Settings_Service", "--vr-settings-service-enabled", "--gs-results-bucket=chromium-result-details", @@ -17276,6 +17278,7 @@ "args": [ "--shared-prefs-file=//chrome/android/shared_preference_files/test/vr_ddview_skipdon_setupcomplete.json", "--replace-system-package=com.google.vr.vrcore,//third_party/gvr-android-sdk/test-apks/vr_services/vr_services_current.apk", + "--additional-apk=//third_party/gvr-android-sdk/test-apks/vr_keyboard/vr_keyboard_current.apk", "--gs-results-bucket=chromium-result-details", "--recover-devices" ], @@ -17322,6 +17325,7 @@ "args": [ "--shared-prefs-file=//chrome/android/shared_preference_files/test/vr_enable_vr_settings_service.json", "--replace-system-package=com.google.vr.vrcore,//third_party/gvr-android-sdk/test-apks/vr_services/vr_services_current.apk", + "--additional-apk=//third_party/gvr-android-sdk/test-apks/vr_keyboard/vr_keyboard_current.apk", "--annotation=Restriction=VR_Settings_Service", "--vr-settings-service-enabled", "--gs-results-bucket=chromium-result-details",
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json index b607be93..9d4f873f 100644 --- a/testing/buildbot/chromium.fyi.json +++ b/testing/buildbot/chromium.fyi.json
@@ -48,6 +48,7 @@ "args": [ "--shared-prefs-file=//chrome/android/shared_preference_files/test/vr_ddview_skipdon_setupcomplete.json", "--replace-system-package=com.google.vr.vrcore,//third_party/gvr-android-sdk/test-apks/vr_services/vr_services_current.apk", + "--additional-apk=//third_party/gvr-android-sdk/test-apks/vr_keyboard/vr_keyboard_current.apk", "--gs-results-bucket=chromium-result-details", "--recover-devices" ], @@ -84,6 +85,7 @@ "args": [ "--shared-prefs-file=//chrome/android/shared_preference_files/test/vr_enable_vr_settings_service.json", "--replace-system-package=com.google.vr.vrcore,//third_party/gvr-android-sdk/test-apks/vr_services/vr_services_current.apk", + "--additional-apk=//third_party/gvr-android-sdk/test-apks/vr_keyboard/vr_keyboard_current.apk", "--annotation=Restriction=VR_Settings_Service", "--vr-settings-service-enabled", "--gs-results-bucket=chromium-result-details", @@ -296,6 +298,7 @@ "args": [ "--shared-prefs-file=src/chrome/android/shared_preference_files/test/vr_ddview_skipdon_setupcomplete.json", "--additional-apk=src/third_party/gvr-android-sdk/test-apks/vr_services/vr_services_current.apk", + "--additional-apk=//third_party/gvr-android-sdk/test-apks/vr_keyboard/vr_keyboard_current.apk", "--additional-apk=src/third_party/gvr-android-sdk/test-apks/daydream_home/daydream_home_current.apk" ], "name": "chrome_public_test_vr_apk (daydream)", @@ -305,6 +308,7 @@ "args": [ "--shared-prefs-file=//chrome/android/shared_preference_files/test/vr_ddview_skipdon_setupcomplete_o2.json", "--additional-apk=src/third_party/gvr-android-sdk/test-apks/vr_services/vr_services_current.apk", + "--additional-apk=//third_party/gvr-android-sdk/test-apks/vr_keyboard/vr_keyboard_current.apk", "--additional-apk=src/third_party/gvr-android-sdk/test-apks/daydream_home/daydream_home_current.apk" ], "name": "chrome_public_test_vr_apk (daydream, O2)", @@ -314,6 +318,7 @@ "args": [ "--shared-prefs-file=src/chrome/android/shared_preference_files/test/vr_enable_vr_settings_service.json", "--additional-apk=src/third_party/gvr-android-sdk/test-apks/vr_services/vr_services_current.apk", + "--additional-apk=//third_party/gvr-android-sdk/test-apks/vr_keyboard/vr_keyboard_current.apk", "--additional-apk=src/third_party/gvr-android-sdk/test-apks/daydream_home/daydream_home_current.apk", "--annotation=Restriction=VR_Settings_Service", "--vr-settings-service-enabled"
diff --git a/testing/buildbot/chromium.gpu.fyi.json b/testing/buildbot/chromium.gpu.fyi.json index 25fb694..acbe76d 100644 --- a/testing/buildbot/chromium.gpu.fyi.json +++ b/testing/buildbot/chromium.gpu.fyi.json
@@ -13182,6 +13182,58 @@ "--browser=release", "--passthrough", "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-angle=d3d11 --use-cmd-decoder=validating", + "--webgl-conformance-version=2.0.1", + "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "webgl2_conformance_d3d11_validating_tests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:5912-24.20.100.6025", + "os": "Windows-10", + "pool": "Chrome-GPU" + } + ], + "idempotent": false, + "shards": 20 + } + }, + { + "args": [ + "webgl_conformance", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-gl=angle --use-angle=gl --use-cmd-decoder=passthrough", + "--webgl-conformance-version=2.0.1", + "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "webgl2_conformance_gl_passthrough_tests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:5912-24.20.100.6025", + "os": "Windows-10", + "pool": "Chrome-GPU" + } + ], + "idempotent": false, + "shards": 20 + } + }, + { + "args": [ + "webgl_conformance", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", "--webgl-conformance-version=2.0.1", "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json" @@ -13847,6 +13899,58 @@ "--browser=release", "--passthrough", "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-angle=d3d11 --use-cmd-decoder=validating", + "--webgl-conformance-version=2.0.1", + "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "webgl2_conformance_d3d11_validating_tests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:5912-23.20.16.4877", + "os": "Windows-10", + "pool": "Chrome-GPU" + } + ], + "idempotent": false, + "shards": 20 + } + }, + { + "args": [ + "webgl_conformance", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", + "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc --use-gl=angle --use-angle=gl --use-cmd-decoder=passthrough", + "--webgl-conformance-version=2.0.1", + "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json" + ], + "isolate_name": "telemetry_gpu_integration_test", + "name": "webgl2_conformance_gl_passthrough_tests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "8086:5912-23.20.16.4877", + "os": "Windows-10", + "pool": "Chrome-GPU" + } + ], + "idempotent": false, + "shards": 20 + } + }, + { + "args": [ + "webgl_conformance", + "--show-stdout", + "--browser=release", + "--passthrough", + "-v", "--extra-browser-args=--enable-logging=stderr --js-flags=--expose-gc", "--webgl-conformance-version=2.0.1", "--read-abbreviated-json-results-from=../../content/test/data/gpu/webgl2_conformance_tests_output.json"
diff --git a/testing/buildbot/filters/mash.browser_tests.filter b/testing/buildbot/filters/mash.browser_tests.filter index a7cb2c3e..a9e72b2 100644 --- a/testing/buildbot/filters/mash.browser_tests.filter +++ b/testing/buildbot/filters/mash.browser_tests.filter
@@ -163,12 +163,6 @@ # Crashes in pre-login phase, probably MagnificationManager not created. -MagnificationManagerTest.* -# OutputProtection problems: -# interface_endpoint_client.cc(32) Check failed: !is_valid. The callback passed to OutputProtection::QueryStatus() was never run. -# binder_registry.h(89) Failed to locate a binder for interface: display::mojom::OutputProtection --*ECKEncryptedMediaTest.OutputProtectionTest* --OutOfProcessPPAPITest.* - # ash::FocusRingController::SetVisible() from LoginDisplayHostWebUI. -MultiAuthEnrollmentScreenTest.* -ProvisionedEnrollmentScreenTest.*
diff --git a/testing/buildbot/filters/mojo.fyi.network_content_browsertests.filter b/testing/buildbot/filters/mojo.fyi.network_content_browsertests.filter index 8edb13b..d019810 100644 --- a/testing/buildbot/filters/mojo.fyi.network_content_browsertests.filter +++ b/testing/buildbot/filters/mojo.fyi.network_content_browsertests.filter
@@ -37,6 +37,10 @@ # https://crbug.com/827318 -RenderThreadImplBrowserTest.NonResourceDispatchIPCTasksDontGoThroughScheduler +# Flaky, temporarily disabling while investigating. +# https://crbug.com/876911 +-ServiceWorkerNavigationPreloadTest.NetworkFallback + # NOTE: if adding an exclusion for an existing failure (e.g. additional test for # feature X that is already not working), please add it beside the existing # failures. Otherwise please reach out to network-service-dev@.
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl index a76fe36b..f980bdb 100644 --- a/testing/buildbot/test_suites.pyl +++ b/testing/buildbot/test_suites.pyl
@@ -106,6 +106,7 @@ 'args': [ '--shared-prefs-file=//chrome/android/shared_preference_files/test/vr_ddview_skipdon_setupcomplete.json', '--replace-system-package=com.google.vr.vrcore,//third_party/gvr-android-sdk/test-apks/vr_services/vr_services_current.apk', + '--additional-apk=//third_party/gvr-android-sdk/test-apks/vr_keyboard/vr_keyboard_current.apk', ], 'swarming': { 'dimension_sets': [ @@ -122,6 +123,7 @@ 'args': [ '--shared-prefs-file=//chrome/android/shared_preference_files/test/vr_enable_vr_settings_service.json', '--replace-system-package=com.google.vr.vrcore,//third_party/gvr-android-sdk/test-apks/vr_services/vr_services_current.apk', + '--additional-apk=//third_party/gvr-android-sdk/test-apks/vr_keyboard/vr_keyboard_current.apk', '--annotation=Restriction=VR_Settings_Service', '--vr-settings-service-enabled', ], @@ -177,6 +179,7 @@ 'args': [ '--shared-prefs-file=src/chrome/android/shared_preference_files/test/vr_ddview_skipdon_setupcomplete.json', '--additional-apk=src/third_party/gvr-android-sdk/test-apks/vr_services/vr_services_current.apk', + '--additional-apk=//third_party/gvr-android-sdk/test-apks/vr_keyboard/vr_keyboard_current.apk', '--additional-apk=src/third_party/gvr-android-sdk/test-apks/daydream_home/daydream_home_current.apk', ], 'test': 'chrome_public_test_vr_apk', @@ -185,6 +188,7 @@ 'args': [ '--shared-prefs-file=//chrome/android/shared_preference_files/test/vr_ddview_skipdon_setupcomplete_o2.json', '--additional-apk=src/third_party/gvr-android-sdk/test-apks/vr_services/vr_services_current.apk', + '--additional-apk=//third_party/gvr-android-sdk/test-apks/vr_keyboard/vr_keyboard_current.apk', '--additional-apk=src/third_party/gvr-android-sdk/test-apks/daydream_home/daydream_home_current.apk', ], 'test': 'chrome_public_test_vr_apk', @@ -193,6 +197,7 @@ 'args': [ '--shared-prefs-file=src/chrome/android/shared_preference_files/test/vr_enable_vr_settings_service.json', '--additional-apk=src/third_party/gvr-android-sdk/test-apks/vr_services/vr_services_current.apk', + '--additional-apk=//third_party/gvr-android-sdk/test-apks/vr_keyboard/vr_keyboard_current.apk', '--additional-apk=src/third_party/gvr-android-sdk/test-apks/daydream_home/daydream_home_current.apk', '--annotation=Restriction=VR_Settings_Service', '--vr-settings-service-enabled', @@ -220,7 +225,8 @@ 'chrome_public_test_vr_apk-ddready-ddview': { 'args': [ '--shared-prefs-file=//chrome/android/shared_preference_files/test/vr_ddview_skipdon_setupcomplete.json', - '--replace-system-package=com.google.vr.vrcore,//third_party/gvr-android-sdk/test-apks/vr_services/vr_services_current.apk' + '--replace-system-package=com.google.vr.vrcore,//third_party/gvr-android-sdk/test-apks/vr_services/vr_services_current.apk', + '--additional-apk=//third_party/gvr-android-sdk/test-apks/vr_keyboard/vr_keyboard_current.apk', ], 'test': 'chrome_public_test_vr_apk', }, @@ -228,6 +234,7 @@ 'args': [ '--shared-prefs-file=//chrome/android/shared_preference_files/test/vr_enable_vr_settings_service.json', '--replace-system-package=com.google.vr.vrcore,//third_party/gvr-android-sdk/test-apks/vr_services/vr_services_current.apk', + '--additional-apk=//third_party/gvr-android-sdk/test-apks/vr_keyboard/vr_keyboard_current.apk', '--annotation=Restriction=VR_Settings_Service', '--vr-settings-service-enabled', ], @@ -1494,7 +1501,7 @@ }, }, - 'gpu_fyi_only_win_nvidia_release_specific_telemetry_tests': { + 'gpu_fyi_only_win_intel_and_nvidia_release_specific_telemetry_tests': { 'webgl2_conformance_d3d11_validating_tests': { 'args': [ '--webgl-conformance-version=2.0.1', @@ -2485,6 +2492,15 @@ 'gpu_fyi_desktop_specific_gtests', ], + 'gpu_fyi_linux_intel_and_nvidia_release_telemetry_tests': [ + 'gpu_common_and_optional_telemetry_tests', + 'gpu_default_win_and_linux_specific_telemetry_tests', + 'gpu_fyi_and_optional_win_and_linux_specific_telemetry_tests', + 'gpu_fyi_only_win_linux_intel_nvidia_specific_telemetry_tests', + 'gpu_fyi_optional_and_v8_desktop_release_specific_telemetry_tests', + 'gpu_telemetry_tests', + ], + 'gpu_fyi_linux_optional_gtests': [ 'gpu_fyi_and_optional_and_win_angle_amd_gtests', 'gpu_fyi_and_optional_and_win_angle_amd_win_and_linux_specific_gtests', @@ -2543,11 +2559,12 @@ 'gpu_fyi_optional_and_v8_desktop_release_specific_telemetry_tests', ], - 'gpu_fyi_win_and_linux_intel_and_nvidia_release_telemetry_tests': [ + 'gpu_fyi_win_amd_telemetry_tests': [ 'gpu_common_and_optional_telemetry_tests', 'gpu_default_win_and_linux_specific_telemetry_tests', + 'gpu_fyi_and_optional_and_win_angle_amd_win_specific_gpu_telemetry_tests', 'gpu_fyi_and_optional_win_and_linux_specific_telemetry_tests', - 'gpu_fyi_only_win_linux_intel_nvidia_specific_telemetry_tests', + 'gpu_fyi_and_optional_win_specific_gpu_telemetry_tests', 'gpu_fyi_optional_and_v8_desktop_release_specific_telemetry_tests', 'gpu_telemetry_tests', ], @@ -2589,18 +2606,6 @@ 'gpu_win_specific_gtests', ], - 'gpu_fyi_win_nvidia_release_telemetry_tests': [ - 'gpu_common_and_optional_telemetry_tests', - 'gpu_default_win_and_linux_specific_telemetry_tests', - 'gpu_fyi_and_optional_and_win_angle_amd_win_specific_gpu_telemetry_tests', - 'gpu_fyi_and_optional_win_and_linux_specific_telemetry_tests', - 'gpu_fyi_and_optional_win_specific_gpu_telemetry_tests', - 'gpu_fyi_only_win_linux_intel_nvidia_specific_telemetry_tests', - 'gpu_fyi_only_win_nvidia_release_specific_telemetry_tests', - 'gpu_fyi_optional_and_v8_desktop_release_specific_telemetry_tests', - 'gpu_telemetry_tests', - ], - 'gpu_fyi_win_optional_gtests': [ 'gpu_default_and_optional_win_specific_gtests', 'gpu_fyi_and_optional_and_win_angle_amd_gtests', @@ -2610,12 +2615,14 @@ 'gpu_fyi_desktop_specific_gtests', ], - 'gpu_fyi_win_telemetry_tests': [ + 'gpu_fyi_win_release_telemetry_tests': [ 'gpu_common_and_optional_telemetry_tests', 'gpu_default_win_and_linux_specific_telemetry_tests', 'gpu_fyi_and_optional_and_win_angle_amd_win_specific_gpu_telemetry_tests', 'gpu_fyi_and_optional_win_and_linux_specific_telemetry_tests', 'gpu_fyi_and_optional_win_specific_gpu_telemetry_tests', + 'gpu_fyi_only_win_linux_intel_nvidia_specific_telemetry_tests', + 'gpu_fyi_only_win_intel_and_nvidia_release_specific_telemetry_tests', 'gpu_fyi_optional_and_v8_desktop_release_specific_telemetry_tests', 'gpu_telemetry_tests', ],
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl index 8ae7686..9f530cb 100644 --- a/testing/buildbot/waterfalls.pyl +++ b/testing/buildbot/waterfalls.pyl
@@ -1492,7 +1492,7 @@ }, 'test_suites': { 'gtest_tests': 'gpu_fyi_linux_release_gtests', - 'gpu_telemetry_tests': 'gpu_fyi_win_and_linux_intel_and_nvidia_release_telemetry_tests', + 'gpu_telemetry_tests': 'gpu_fyi_linux_intel_and_nvidia_release_telemetry_tests', }, }, 'Linux FYI Release (NVIDIA)': { @@ -1511,7 +1511,7 @@ 'test_suites': { 'gtest_tests': 'gpu_fyi_linux_release_gtests', 'isolated_scripts': 'gpu_fyi_and_optional_isolated_scripts', - 'gpu_telemetry_tests': 'gpu_fyi_win_and_linux_intel_and_nvidia_release_telemetry_tests', + 'gpu_telemetry_tests': 'gpu_fyi_linux_intel_and_nvidia_release_telemetry_tests', }, }, 'Linux FYI dEQP Release (Intel HD 630)': { @@ -1965,7 +1965,7 @@ }, 'test_suites': { 'gtest_tests': 'gpu_fyi_win_gtests', - 'gpu_telemetry_tests': 'gpu_fyi_win_telemetry_tests', + 'gpu_telemetry_tests': 'gpu_fyi_win_release_telemetry_tests', }, }, # TODO(kbr): "Experimental" caused too-long path names pre-LUCI. @@ -2006,7 +2006,7 @@ }, 'test_suites': { 'gtest_tests': 'gpu_fyi_win_gtests', - 'gpu_telemetry_tests': 'gpu_fyi_win_telemetry_tests', + 'gpu_telemetry_tests': 'gpu_fyi_win_release_telemetry_tests', }, }, 'Win10 FYI Release (NVIDIA)': { @@ -2026,7 +2026,7 @@ 'test_suites': { 'gtest_tests': 'gpu_fyi_win_gtests', 'isolated_scripts': 'gpu_fyi_and_optional_win_isolated_scripts', - 'gpu_telemetry_tests': 'gpu_fyi_win_nvidia_release_telemetry_tests', + 'gpu_telemetry_tests': 'gpu_fyi_win_release_telemetry_tests', }, 'use_multi_dimension_trigger_script': True, }, @@ -2115,7 +2115,7 @@ }, 'test_suites': { 'gtest_tests': 'gpu_fyi_win_gtests', - 'gpu_telemetry_tests': 'gpu_fyi_win_telemetry_tests', + 'gpu_telemetry_tests': 'gpu_fyi_win_amd_telemetry_tests', }, }, 'Win7 FYI Release (NVIDIA)': {
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index 583aee6f..10327a3 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -1422,6 +1422,21 @@ ] } ], + "DirectCompositionPreferNV12Overlays": [ + { + "platforms": [ + "windows" + ], + "experiments": [ + { + "name": "Enabled", + "enable_features": [ + "DirectCompositionPreferNV12Overlays" + ] + } + ] + } + ], "DownloadHomeMoreButton": [ { "platforms": [
diff --git a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-gen-property-trees b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-gen-property-trees index 242ee03b..3091f5b 100644 --- a/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-gen-property-trees +++ b/third_party/WebKit/LayoutTests/FlagExpectations/enable-blink-gen-property-trees
@@ -245,9 +245,6 @@ Bug(none) fast/clip/overflow-border-radius-composited-parent.html [ Failure ] Bug(none) fast/clip/overflow-border-radius-composited.html [ Failure ] -crbug.com/874675 compositing/overflow/mixed-composited-nested-sticky-overflow-scroller.html [ Failure ] -crbug.com/874675 fast/css/sticky/sticky-clip-rel-child.html [ Failure ] - # Something wrong with vertical-rl scrollbars crbug.com/853945 fast/block/positioning/vertical-rl/002.html [ Failure ] crbug.com/853945 fast/block/positioning/vertical-rl/fixed-positioning.html [ Failure ]
diff --git a/third_party/WebKit/LayoutTests/TestExpectations b/third_party/WebKit/LayoutTests/TestExpectations index b835e91..154e3e12 100644 --- a/third_party/WebKit/LayoutTests/TestExpectations +++ b/third_party/WebKit/LayoutTests/TestExpectations
@@ -2734,6 +2734,7 @@ crbug.com/875249 external/wpt/infrastructure/testdriver/bless.html [ Timeout Pass ] # ====== New tests from wpt-importer added here ====== +crbug.com/626703 external/wpt/html/rendering/non-replaced-elements/the-fieldset-element-0/fieldset-transform-translatez.html [ Failure ] crbug.com/626703 external/wpt/html/rendering/non-replaced-elements/the-fieldset-element-0/fieldset-overflow-hidden.html [ Failure ] crbug.com/626703 [ Mac10.12 ] external/wpt/webxr/xrSession_requestAnimationFrame_getDevicePose.https.html [ Failure Timeout ] crbug.com/626703 [ Mac10.10 ] external/wpt/editing/run/delete.html?2001-3000 [ Failure Timeout ] @@ -3579,7 +3580,6 @@ crbug.com/626703 external/wpt/webvtt/rendering/cues-with-video/processing-model/size_50.html [ Failure ] crbug.com/626703 external/wpt/webvtt/rendering/cues-with-video/processing-model/too_many_cues.html [ Failure ] crbug.com/626703 external/wpt/webvtt/rendering/cues-with-video/processing-model/too_many_cues_wrapped.html [ Failure ] -crbug.com/815116 external/wpt/workers/name-property.html [ Timeout Failure Pass ] crbug.com/626703 external/wpt/xhr/event-readystatechange-loaded.htm [ Failure Timeout ] crbug.com/626703 virtual/outofblink-cors/external/wpt/xhr/event-readystatechange-loaded.htm [ Failure Timeout ] crbug.com/626703 virtual/outofblink-cors-ns/external/wpt/xhr/event-readystatechange-loaded.htm [ Failure Timeout ]
diff --git a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json index 8ccf807..dece72b 100644 --- a/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json +++ b/third_party/WebKit/LayoutTests/external/WPT_BASE_MANIFEST.json
@@ -94877,6 +94877,18 @@ {} ] ], + "html/rendering/non-replaced-elements/the-fieldset-element-0/fieldset-transform-translatez.html": [ + [ + "/html/rendering/non-replaced-elements/the-fieldset-element-0/fieldset-transform-translatez.html", + [ + [ + "/html/rendering/non-replaced-elements/the-fieldset-element-0/fieldset-transform-translatez-ref.html", + "==" + ] + ], + {} + ] + ], "html/rendering/non-replaced-elements/the-fieldset-element-0/legend-float.html": [ [ "/html/rendering/non-replaced-elements/the-fieldset-element-0/legend-float.html", @@ -145709,11 +145721,6 @@ {} ] ], - "fetch/api/response/response-static-redirect-expected.txt": [ - [ - {} - ] - ], "fetch/api/response/response-trailer-expected.txt": [ [ {} @@ -154924,6 +154931,11 @@ {} ] ], + "html/rendering/non-replaced-elements/the-fieldset-element-0/fieldset-transform-translatez-ref.html": [ + [ + {} + ] + ], "html/rendering/non-replaced-elements/the-fieldset-element-0/legend-expected.txt": [ [ {} @@ -167114,6 +167126,16 @@ {} ] ], + "screen-capture/OWNERS": [ + [ + {} + ] + ], + "screen-capture/getdisplaymedia.https-expected.txt": [ + [ + {} + ] + ], "screen-orientation/META.yml": [ [ {} @@ -173254,6 +173276,11 @@ {} ] ], + "webmessaging/worker_postMessage_user_activation.js": [ + [ + {} + ] + ], "webmidi/META.yml": [ [ {} @@ -219129,6 +219156,12 @@ {} ] ], + "html/input/the-disabled-attribute/number-disabled.html": [ + [ + "/html/input/the-disabled-attribute/number-disabled.html", + {} + ] + ], "html/obsolete/requirements-for-implementations/other-elements-attributes-and-apis/document-all.html": [ [ "/html/obsolete/requirements-for-implementations/other-elements-attributes-and-apis/document-all.html", @@ -251459,6 +251492,12 @@ {} ] ], + "screen-capture/getdisplaymedia.https.html": [ + [ + "/screen-capture/getdisplaymedia.https.html", + {} + ] + ], "screen-capture/idlharness.window.js": [ [ "/screen-capture/idlharness.window.html", @@ -258849,6 +258888,12 @@ {} ] ], + "webmessaging/message-channels/user-activation.tentative.html": [ + [ + "/webmessaging/message-channels/user-activation.tentative.html", + {} + ] + ], "webmessaging/message-channels/worker.html": [ [ "/webmessaging/message-channels/worker.html", @@ -259317,6 +259362,12 @@ {} ] ], + "webmessaging/worker_postMessage_user_activation.tentative.html": [ + [ + "/webmessaging/worker_postMessage_user_activation.tentative.html", + {} + ] + ], "webmidi/idlharness.window.js": [ [ "/webmidi/idlharness.window.html", @@ -262801,129 +262852,15 @@ {} ] ], - "webxr/navigator_xr_requestDevice.https.html": [ - [ - "/webxr/navigator_xr_requestDevice.https.html", - {} - ] - ], - "webxr/navigator_xr_requestDevice_no_device.https.html": [ - [ - "/webxr/navigator_xr_requestDevice_no_device.https.html", - {} - ] - ], - "webxr/webGLCanvasContext_create_with_xrdevice.https.html": [ - [ - "/webxr/webGLCanvasContext_create_with_xrdevice.https.html", - {} - ] - ], - "webxr/webGLCanvasContext_setdevice_contextlost.https.html": [ - [ - "/webxr/webGLCanvasContext_setdevice_contextlost.https.html", - {} - ] - ], "webxr/webxr_availability.http.sub.html": [ [ "/webxr/webxr_availability.http.sub.html", {} ] ], - "webxr/xrDevice_requestSession_immersive.https.html": [ + "webxr/xrSession_exclusive_requestAnimationFrame.https.html": [ [ - "/webxr/xrDevice_requestSession_immersive.https.html", - {} - ] - ], - "webxr/xrDevice_requestSession_immersive_no_gesture.https.html": [ - [ - "/webxr/xrDevice_requestSession_immersive_no_gesture.https.html", - {} - ] - ], - "webxr/xrDevice_requestSession_immersive_unsupported.https.html": [ - [ - "/webxr/xrDevice_requestSession_immersive_unsupported.https.html", - {} - ] - ], - "webxr/xrDevice_requestSession_non_immersive_no_gesture.https.html": [ - [ - "/webxr/xrDevice_requestSession_non_immersive_no_gesture.https.html", - {} - ] - ], - "webxr/xrDevice_supportsSession_immersive.https.html": [ - [ - "/webxr/xrDevice_supportsSession_immersive.https.html", - {} - ] - ], - "webxr/xrDevice_supportsSession_immersive_unsupported.https.html": [ - [ - "/webxr/xrDevice_supportsSession_immersive_unsupported.https.html", - {} - ] - ], - "webxr/xrDevice_supportsSession_non_immersive.https.html": [ - [ - "/webxr/xrDevice_supportsSession_non_immersive.https.html", - {} - ] - ], - "webxr/xrSession_cancelAnimationFrame.https.html": [ - [ - "/webxr/xrSession_cancelAnimationFrame.https.html", - {} - ] - ], - "webxr/xrSession_cancelAnimationFrame_invalidhandle.https.html": [ - [ - "/webxr/xrSession_cancelAnimationFrame_invalidhandle.https.html", - {} - ] - ], - "webxr/xrSession_device.https.html": [ - [ - "/webxr/xrSession_device.https.html", - {} - ] - ], - "webxr/xrSession_end.https.html": [ - [ - "/webxr/xrSession_end.https.html", - {} - ] - ], - "webxr/xrSession_prevent_multiple_exclusive.https.html": [ - [ - "/webxr/xrSession_prevent_multiple_exclusive.https.html", - {} - ] - ], - "webxr/xrSession_requestAnimationFrame_callback_calls.https.html": [ - [ - "/webxr/xrSession_requestAnimationFrame_callback_calls.https.html", - {} - ] - ], - "webxr/xrSession_requestAnimationFrame_data_valid.https.html": [ - [ - "/webxr/xrSession_requestAnimationFrame_data_valid.https.html", - {} - ] - ], - "webxr/xrSession_requestAnimationFrame_getDevicePose.https.html": [ - [ - "/webxr/xrSession_requestAnimationFrame_getDevicePose.https.html", - {} - ] - ], - "webxr/xrSession_requestFrameOfReference.https.html": [ - [ - "/webxr/xrSession_requestFrameOfReference.https.html", + "/webxr/xrSession_exclusive_requestAnimationFrame.https.html", {} ] ], @@ -361282,10 +361219,6 @@ "96b1d4f58925cb9ba5a07aef28aa4b869c67f93b", "testharness" ], - "fetch/api/response/response-static-redirect-expected.txt": [ - "8b19a88f1c2251490fc85dae436b8b385b01ce1d", - "support" - ], "fetch/api/response/response-static-redirect.html": [ "235d32c0be7164d9f25cfa40988ad10096286508", "testharness" @@ -367111,11 +367044,11 @@ "testharness" ], "html/dom/elements/the-innertext-idl-attribute/getter-expected.txt": [ - "4e2a50cc4b20f83a959548a6bfbb02889c33c66c", + "195ae384846ff37afca4eab243d040943296497c", "support" ], "html/dom/elements/the-innertext-idl-attribute/getter-tests.js": [ - "0ffc6d2bf3011a376f85b45090c63de07ac023d5", + "5561288248c2955dfb57bc807bf578778e97d93a", "support" ], "html/dom/elements/the-innertext-idl-attribute/getter.html": [ @@ -371646,6 +371579,10 @@ "da39a3ee5e6b4b0d3255bfef95601890afd80709", "support" ], + "html/input/the-disabled-attribute/number-disabled.html": [ + "0144f1a84bc865982f9fd074424805a162158765", + "testharness" + ], "html/input/the-placeholder-attribute/multiline-cr.html": [ "687054d9b221998ff4c4071ccc0733faeeb129b7", "reftest" @@ -372458,6 +372395,14 @@ "ee6d5ca161811bca7826a7489f0e269041c8a5ad", "reftest" ], + "html/rendering/non-replaced-elements/the-fieldset-element-0/fieldset-transform-translatez-ref.html": [ + "329637fd6312e198937660dec52e9ff369b4e0eb", + "support" + ], + "html/rendering/non-replaced-elements/the-fieldset-element-0/fieldset-transform-translatez.html": [ + "3fbc2ebe2865fa3eb5fc80c54622ca8fa9a69a2f", + "reftest" + ], "html/rendering/non-replaced-elements/the-fieldset-element-0/legend-block-formatting-context.html": [ "80d80d4934f0ad148458c5d5494946f5c7b126c8", "testharness" @@ -404426,6 +404371,18 @@ "2148044e4034fd793687f1b54c8ad5963c5977fe", "support" ], + "screen-capture/OWNERS": [ + "3c2551daf2d8c5d504b9b2a54e68b44f20b9f642", + "support" + ], + "screen-capture/getdisplaymedia.https-expected.txt": [ + "2dc7ca0f01de0cf2d1051d59f29b8d532d3232a5", + "support" + ], + "screen-capture/getdisplaymedia.https.html": [ + "be53ffe6855f608efafcdaf2b5991fc979af8e1b", + "testharness" + ], "screen-capture/idlharness.window.js": [ "73c374fc70909fed944ef904a1a0a8312680d387", "testharness" @@ -406399,7 +406356,7 @@ "testharness" ], "service-workers/service-worker/interfaces-window.https.html": [ - "18b96c6b13d9b561e2fdb1eca32872d6596c76b0", + "469d4d803c44f0d0ee3ac19e4e7e74b469354cf8", "testharness" ], "service-workers/service-worker/invalid-blobtype.https.html": [ @@ -406415,11 +406372,11 @@ "testharness" ], "service-workers/service-worker/local-url-inherit-controller.https-expected.txt": [ - "5971cb67b8db3877cca183ab2cc95a18a202df3a", + "7efca82a0038e2e75c54b99486052b73c2de08f9", "support" ], "service-workers/service-worker/local-url-inherit-controller.https.html": [ - "e2e8258f24860cb93b71b4bb27f618b7740756bd", + "af238dadc636fc106161c3e5b90769f80c85445c", "testharness" ], "service-workers/service-worker/mime-sniffing.https.html": [ @@ -412251,7 +412208,7 @@ "testharness" ], "user-timing/measure.html": [ - "dbafe1fe5e1aa3ee5af273f295fd0d61179eece1", + "ce6ddc95ee35f970f1b250056692b4eff63f61b7", "testharness" ], "user-timing/measure_associated_with_navigation_timing.html": [ @@ -414778,6 +414735,10 @@ "6cc23ea0c48a1f2cb200c0c37ad3b3f3dfdbdde6", "testharness" ], + "webmessaging/message-channels/user-activation.tentative.html": [ + "ffe0871945f5e9746bc8e097acc72616008738a1", + "testharness" + ], "webmessaging/message-channels/worker.html": [ "25778166691434e77f361a609742a170c4f787e8", "testharness" @@ -415110,6 +415071,14 @@ "7665873355c531e009824021a2b75daaf2dd6e3f", "testharness" ], + "webmessaging/worker_postMessage_user_activation.js": [ + "1936896f6da79dd5addabee8f5c19df566f02c23", + "support" + ], + "webmessaging/worker_postMessage_user_activation.tentative.html": [ + "204f521d24cadf47cd78ff8f97503708eb63678c", + "testharness" + ], "webmidi/META.yml": [ "92d1714903f2fb2f0aa8365be451ca9cd86def9d", "support" @@ -420238,102 +420207,26 @@ "58810d4be6ad2b4d087a06dc39a203bfc377b490", "support" ], - "webxr/navigator_xr_requestDevice.https.html": [ - "e77fbaef18251e570fb44a6bd9a153f27b5b026b", - "testharness" - ], - "webxr/navigator_xr_requestDevice_no_device.https.html": [ - "c7519f0d0e07ad19eba174b8f30959f57c8fea2d", - "testharness" - ], "webxr/resources/webxr_check.html": [ "3fa96e39a073bda2e813f0b2c2411c26b73d374e", "support" ], "webxr/resources/webxr_util.js": [ - "a7527a18fb1ce0ceb463c76a2a17ae95afdc0c99", + "e145f999bb691a4d19067c75adc0f1206a63835d", "support" ], - "webxr/webGLCanvasContext_create_with_xrdevice.https.html": [ - "1ad436d9b47a4b44ebded72fc3f34fe440292459", - "testharness" - ], - "webxr/webGLCanvasContext_setdevice_contextlost.https.html": [ - "73f74fcbbd67f998de9d0383a26449e37762a2f4", - "testharness" - ], "webxr/webxr_availability.http.sub.html": [ "d8aa0ef8b7b3363fd23af2700dc6d9186201c408", "testharness" ], - "webxr/xrDevice_requestSession_immersive.https.html": [ - "fb896c22096be11e4b228386f8d29278e67b0682", - "testharness" - ], - "webxr/xrDevice_requestSession_immersive_no_gesture.https.html": [ - "c028dbf503ddd69928ac45684f64ff88d71662ad", - "testharness" - ], - "webxr/xrDevice_requestSession_immersive_unsupported.https.html": [ - "b6244a306828d220386b88278def4d4b788d0fc7", - "testharness" - ], - "webxr/xrDevice_requestSession_non_immersive_no_gesture.https.html": [ - "482a81c30043aaf1a46b436e6d71c5d526f4f3ac", - "testharness" - ], - "webxr/xrDevice_supportsSession_immersive.https.html": [ - "b75d432c7d2ece7197e489c5e3f3b4f763e0dee6", - "testharness" - ], - "webxr/xrDevice_supportsSession_immersive_unsupported.https.html": [ - "dbdfe2f95e35f5ff62eaa241c883c1552c89d8ad", - "testharness" - ], - "webxr/xrDevice_supportsSession_non_immersive.https.html": [ - "0397b0916875c9e6e853de91e706dda6c2fa83b0", - "testharness" - ], - "webxr/xrSession_cancelAnimationFrame.https.html": [ - "2c4733a61a697aedad7fade7cab5a009c54b9ac5", - "testharness" - ], - "webxr/xrSession_cancelAnimationFrame_invalidhandle.https.html": [ - "b118b9d33ddd8974a4fc4a4f751ee9de5a7d68bc", - "testharness" - ], - "webxr/xrSession_device.https.html": [ - "db59820b7b5c644fb9cee91e4423786a7bae9edb", - "testharness" - ], - "webxr/xrSession_end.https.html": [ - "e7af605d3da3c229380fe4fdcbb3768112d4f9bc", - "testharness" - ], - "webxr/xrSession_prevent_multiple_exclusive.https.html": [ - "2b35214385c9d89d14d944fea07df06af9983017", - "testharness" - ], - "webxr/xrSession_requestAnimationFrame_callback_calls.https.html": [ - "bf16488eaebed288db2e97d98ea995237eb0cf19", - "testharness" - ], - "webxr/xrSession_requestAnimationFrame_data_valid.https.html": [ - "fb0f6344840cfa8c6fe63ac4aeac5e5e65e87272", + "webxr/xrSession_exclusive_requestAnimationFrame.https.html": [ + "e75f95ee7d2751f7cbeadda9d6219bb29dbedfdc", "testharness" ], "webxr/xrSession_requestAnimationFrame_getDevicePose.https-expected.txt": [ "ca34e2b35bd96083b989b684fc1da35e299557aa", "support" ], - "webxr/xrSession_requestAnimationFrame_getDevicePose.https.html": [ - "953b97bcf4e99e814acab0e4fbc788e888d3370e", - "testharness" - ], - "webxr/xrSession_requestFrameOfReference.https.html": [ - "c3d22f4a4c69c733f0c46d3cb2396ade9059b1c5", - "testharness" - ], "workers/META.yml": [ "e10618bcfad6f80d5d983b9f4da878560b644108", "support"
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/dom/elements/the-innertext-idl-attribute/getter-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/html/dom/elements/the-innertext-idl-attribute/getter-expected.txt index e71915c..ae90cea 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/html/dom/elements/the-innertext-idl-attribute/getter-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/html/dom/elements/the-innertext-idl-attribute/getter-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 214 tests; 136 PASS, 78 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 214 tests; 140 PASS, 74 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS Simplest possible test ("<div>abc") PASS Leading whitespace removed ("<div> abc") PASS Trailing whitespace removed ("<div>abc ") @@ -47,7 +47,7 @@ PASS No removal of leading/trailing whitespace in display:none container ("<div style='display:none'> abc def ") PASS display:none child not rendered ("<div>123<span style='display:none'>abc") PASS display:none container with non-display-none target child ("<div style='display:none'><span id='target'>abc") -FAIL non-display-none child of svg ("<div id='target'>abc") assert_equals: expected "" but got "abc" +PASS non-display-none child of svg ("<div id='target'>abc") PASS display:none child of svg ("<div style='display:none' id='target'>abc") PASS child of display:none child of svg ("<div style='display:none'><div id='target'>abc") PASS display:contents container ("<div style='display:contents'>abc") @@ -80,13 +80,13 @@ PASS <iframe> contents ignored ("<iframe><div id='target'>abc") PASS <iframe> subdocument ignored ("<iframe src='data:text/html,abc'>") FAIL <audio> contents ignored ("<audio style='display:block'>abc") assert_equals: expected "" but got "abc" -FAIL <audio> contents ignored ("<audio style='display:block'><source id='target' class='poke' style='display:block'>") assert_equals: expected "" but got "abc" -PASS <audio> contents ok if display:none ("<audio style='display:block'><source id='target' class='poke' style='display:none'>") +PASS <audio> contents ok for element not being rendered ("<audio style='display:block'><source id='target' class='poke' style='display:block'>") +PASS <audio> contents ok for element not being rendered ("<audio style='display:block'><source id='target' class='poke' style='display:none'>") PASS <video> contents ignored ("<video>abc") -FAIL <video> contents ignored ("<video style='display:block'><source id='target' class='poke' style='display:block'>") assert_equals: expected "" but got "abc" -PASS <video> contents ok if display:none ("<video style='display:block'><source id='target' class='poke' style='display:none'>") +PASS <video> contents ok for element not being rendered ("<video style='display:block'><source id='target' class='poke' style='display:block'>") +PASS <video> contents ok for element not being rendered ("<video style='display:block'><source id='target' class='poke' style='display:none'>") PASS <canvas> contents ignored ("<canvas>abc") -FAIL <canvas><div id='target'> contents ignored ("<canvas><div id='target'>abc") assert_equals: expected "" but got "abc" +PASS <canvas><div id='target'> contents ok for element not being rendered ("<canvas><div id='target'>abc") PASS <img> alt text ignored ("<img alt='abc'>") PASS <img> contents ignored ("<img src='about:blank' class='poke'>") FAIL <select size='1'> contents of options preserved ("<select size='1'><option>abc</option><option>def") assert_equals: expected "abc\ndef" but got ""
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/dom/elements/the-innertext-idl-attribute/getter-tests.js b/third_party/WebKit/LayoutTests/external/wpt/html/dom/elements/the-innertext-idl-attribute/getter-tests.js index af860c9..fcd11b4 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/html/dom/elements/the-innertext-idl-attribute/getter-tests.js +++ b/third_party/WebKit/LayoutTests/external/wpt/html/dom/elements/the-innertext-idl-attribute/getter-tests.js
@@ -75,7 +75,7 @@ testText("<div style='display:none'> abc def ", " abc def ", "No removal of leading/trailing whitespace in display:none container"); testText("<div>123<span style='display:none'>abc", "123", "display:none child not rendered"); testText("<div style='display:none'><span id='target'>abc", "abc", "display:none container with non-display-none target child"); -testTextInSVG("<div id='target'>abc", "", "non-display-none child of svg"); +testTextInSVG("<div id='target'>abc", "abc", "non-display-none child of svg"); testTextInSVG("<div style='display:none' id='target'>abc", "abc", "display:none child of svg"); testTextInSVG("<div style='display:none'><div id='target'>abc", "abc", "child of display:none child of svg"); @@ -132,13 +132,13 @@ testText("<iframe><div id='target'>abc", "", "<iframe> contents ignored"); testText("<iframe src='data:text/html,abc'>", "","<iframe> subdocument ignored"); testText("<audio style='display:block'>abc", "", "<audio> contents ignored"); -testText("<audio style='display:block'><source id='target' class='poke' style='display:block'>", "", "<audio> contents ignored"); -testText("<audio style='display:block'><source id='target' class='poke' style='display:none'>", "abc", "<audio> contents ok if display:none"); +testText("<audio style='display:block'><source id='target' class='poke' style='display:block'>", "abc", "<audio> contents ok for element not being rendered"); +testText("<audio style='display:block'><source id='target' class='poke' style='display:none'>", "abc", "<audio> contents ok for element not being rendered"); testText("<video>abc", "", "<video> contents ignored"); -testText("<video style='display:block'><source id='target' class='poke' style='display:block'>", "", "<video> contents ignored"); -testText("<video style='display:block'><source id='target' class='poke' style='display:none'>", "abc", "<video> contents ok if display:none"); +testText("<video style='display:block'><source id='target' class='poke' style='display:block'>", "abc", "<video> contents ok for element not being rendered"); +testText("<video style='display:block'><source id='target' class='poke' style='display:none'>", "abc", "<video> contents ok for element not being rendered"); testText("<canvas>abc", "", "<canvas> contents ignored"); -testText("<canvas><div id='target'>abc", "", "<canvas><div id='target'> contents ignored"); +testText("<canvas><div id='target'>abc", "abc", "<canvas><div id='target'> contents ok for element not being rendered"); testText("<img alt='abc'>", "", "<img> alt text ignored"); testText("<img src='about:blank' class='poke'>", "", "<img> contents ignored");
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/input/the-disabled-attribute/number-disabled.html b/third_party/WebKit/LayoutTests/external/wpt/html/input/the-disabled-attribute/number-disabled.html new file mode 100644 index 0000000..11cb82fd --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/input/the-disabled-attribute/number-disabled.html
@@ -0,0 +1,18 @@ +<!doctype html> +<title>disabled works properly for number inputs</title> +<link rel="help" href="https://html.spec.whatwg.org/#enabling-and-disabling-form-controls:-the-disabled-attribute"> +<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1461706"> +<link rel="author" href="mailto:emilio@crisal.io" title="Emilio Cobos Álvarez"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<input type="number" disabled> +<input type="number" disabled style="-moz-appearance: textfield; -webkit-appearance: textfield"> +<script> + test(function() { + for (const element of Array.from(document.querySelectorAll('input'))) { + element.focus(); + assert_true(element.disabled); + assert_equals(document.activeElement, document.body); + } + }, "disabled works on number input regardless of appearance"); +</script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/rendering/non-replaced-elements/the-fieldset-element-0/fieldset-transform-translatez-ref.html b/third_party/WebKit/LayoutTests/external/wpt/html/rendering/non-replaced-elements/the-fieldset-element-0/fieldset-transform-translatez-ref.html new file mode 100644 index 0000000..c0db2d7 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/rendering/non-replaced-elements/the-fieldset-element-0/fieldset-transform-translatez-ref.html
@@ -0,0 +1,10 @@ +<!DOCTYPE html> +<title>Reference for Fieldset and transform: translateZ(0)</title> +<style> +fieldset { background: #eee; } +</style> +<p>It should say PASS below without anything obscuring the text.</p> + +<fieldset> + <legend>PASS</legend> +</fieldset>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/rendering/non-replaced-elements/the-fieldset-element-0/fieldset-transform-translatez.html b/third_party/WebKit/LayoutTests/external/wpt/html/rendering/non-replaced-elements/the-fieldset-element-0/fieldset-transform-translatez.html new file mode 100644 index 0000000..df30468 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/html/rendering/non-replaced-elements/the-fieldset-element-0/fieldset-transform-translatez.html
@@ -0,0 +1,16 @@ +<!DOCTYPE html> +<title>Fieldset and transform: translateZ(0)</title> +<link rel=match href=fieldset-transform-translatez-ref.html> +<style> +#outer { transform: translateZ(0); } +fieldset { background: #eee; overflow: hidden; margin: 0 0 10px; } +#inner { position: relative; } +</style> +<p>It should say PASS below without anything obscuring the text.</p> +<div id=outer> + <fieldset> + <legend> + <div id="inner">PASS</div> + </legend> + </fieldset> +</div>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/bailout-side-effects-ignore-opens-during-unload.window.js b/third_party/WebKit/LayoutTests/external/wpt/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/bailout-side-effects-ignore-opens-during-unload.window.js index 98ffba20..6b80eca 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/bailout-side-effects-ignore-opens-during-unload.window.js +++ b/third_party/WebKit/LayoutTests/external/wpt/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/bailout-side-effects-ignore-opens-during-unload.window.js
@@ -6,11 +6,19 @@ t.add_cleanup(() => iframe.remove()); iframe.src = "/common/blank.html"; iframe.onload = t.step_func(() => { - iframe.contentWindow.addEventListener(ev, t.step_func_done(() => { - const origURL = iframe.contentDocument.URL; - assertDocumentIsReadyForSideEffectsTest(iframe.contentDocument, `ignore-opens-during-unload counter is greater than 0 during ${ev} event`); - assert_equals(iframe.contentDocument.open(), iframe.contentDocument); - assertOpenHasNoSideEffects(iframe.contentDocument, origURL, `ignore-opens-during-unload counter is greater than 0 during ${ev} event`); + iframe.contentWindow.addEventListener(ev, t.step_func(() => { + // Here, the entry settings object could still be the iframe's. Delay + // it in such a way that ensures the entry settings object is the + // top-level page's, but without delaying too much that the + // ignore-opens-during-unload counter becomes decremented. A microtask + // is perfect as it's executed immediately in "clean up after running + // script". + Promise.resolve().then(t.step_func_done(() => { + const origURL = iframe.contentDocument.URL; + assertDocumentIsReadyForSideEffectsTest(iframe.contentDocument, `ignore-opens-during-unload counter is greater than 0 during ${ev} event`); + assert_equals(iframe.contentDocument.open(), iframe.contentDocument); + assertOpenHasNoSideEffects(iframe.contentDocument, origURL, `ignore-opens-during-unload counter is greater than 0 during ${ev} event`); + })); })); iframe.src = "about:blank"; });
diff --git a/third_party/WebKit/LayoutTests/external/wpt/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/bailout-side-effects-synchronous-script.window.js b/third_party/WebKit/LayoutTests/external/wpt/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/bailout-side-effects-synchronous-script.window.js index 59a750a..fb26c70 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/bailout-side-effects-synchronous-script.window.js +++ b/third_party/WebKit/LayoutTests/external/wpt/html/webappapis/dynamic-markup-insertion/opening-the-input-stream/bailout-side-effects-synchronous-script.window.js
@@ -3,11 +3,17 @@ async_test(t => { const iframe = document.body.appendChild(document.createElement("iframe")); t.add_cleanup(() => iframe.remove()); - self.testSynchronousScript = t.step_func_done(() => { - const origURL = iframe.contentDocument.URL; - assertDocumentIsReadyForSideEffectsTest(iframe.contentDocument, "active parser whose script nesting level is greater than 0"); - assert_equals(iframe.contentDocument.open(), iframe.contentDocument); - assertOpenHasNoSideEffects(iframe.contentDocument, origURL, "active parser whose script nesting level is greater than 0"); + self.testSynchronousScript = t.step_func(() => { + // Here, the entry settings object is still the iframe's. Delay it in such + // a way that makes the entry settings object the top-level page's, but + // without delaying too much that the parser becomes inactive. A microtask + // is perfect as it's executed in "clean up after running script". + Promise.resolve().then(t.step_func_done(() => { + const origURL = iframe.contentDocument.URL; + assertDocumentIsReadyForSideEffectsTest(iframe.contentDocument, "active parser whose script nesting level is greater than 0"); + assert_equals(iframe.contentDocument.open(), iframe.contentDocument); + assertOpenHasNoSideEffects(iframe.contentDocument, origURL, "active parser whose script nesting level is greater than 0"); + })); }); iframe.src = "resources/bailout-order-synchronous-script-frame.html"; }, "document.open bailout should not have any side effects (active parser whose script nesting level is greater than 0)");
diff --git a/third_party/WebKit/LayoutTests/external/wpt/resources/chromium/webxr-test.js b/third_party/WebKit/LayoutTests/external/wpt/resources/chromium/webxr-test.js index 10ed703..e5d17259 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/resources/chromium/webxr-test.js +++ b/third_party/WebKit/LayoutTests/external/wpt/resources/chromium/webxr-test.js
@@ -9,7 +9,11 @@ } simulateDeviceConnection(init_params) { - return Promise.resolve(this.mockVRService_.addDevice(init_params)); + return Promise.resolve(this.mockVRService_.addRuntime(init_params)); + } + + simulateDeviceDisconnection(device) { + this.mockVRService_.removeRuntime(device); } simulateUserActivation(callback) { @@ -30,10 +34,12 @@ } // Mocking class definitions + +// Mock service implements both the VRService and XRDevice mojo interfaces. class MockVRService { constructor() { this.bindingSet_ = new mojo.BindingSet(device.mojom.VRService); - this.devices_ = []; + this.runtimes_ = []; this.interceptor_ = new MojoInterfaceInterceptor(device.mojom.VRService.name); @@ -43,31 +49,87 @@ } // Test methods - addDevice(fakeDeviceInit) { - let device = new MockDevice(fakeDeviceInit, this); - this.devices_.push(device); + addRuntime(fakeDeviceInit) { + let runtime = new MockRuntime(fakeDeviceInit, this); + this.runtimes_.push(runtime); if (this.client_) { this.client_.onDeviceChanged(); } - return device; + return runtime; + } + + removeRuntime(runtime) { + // We have no way of distinguishing between devices, so just clear the + // entire list for now. + // TODO(http://crbug.com/873409) We also have no way right now to disconnect + // devices. + this.runtimes_ = []; } // VRService implementation. requestDevice() { - return Promise.resolve( - {device: this.devices_[0] ? this.devices_[0].getDevicePtr() : null}); + if (this.runtimes_.length > 0) { + let devicePtr = new device.mojom.XRDevicePtr(); + new mojo.Binding( + device.mojom.XRDevice, this, mojo.makeRequest(devicePtr)); + + return Promise.resolve({device: devicePtr}); + } else { + return Promise.resolve({device: null}); + } } setClient(client) { this.client_ = client; } + + // XRDevice implementation. + requestSession(sessionOptions, was_activation) { + let requests = []; + // Request a session from all the runtimes. + for (let i = 0; i < this.runtimes_.length; i++) { + requests[i] = this.runtimes_[i].requestRuntimeSession(sessionOptions); + } + + return Promise.all(requests).then((results) => { + // Find and return the first successful result. + for (let i = 0; i < results.length; i++) { + if (results[i].session) { + return results[i]; + } + } + + // If there were no successful results, returns a null session. + return {session: null}; + }); + } + + supportsSession(sessionOptions) { + let requests = []; + // Check supports on all the runtimes. + for (let i = 0; i < this.runtimes_.length; i++) { + requests[i] = this.runtimes_[i].runtimeSupportsSession(sessionOptions); + } + + return Promise.all(requests).then((results) => { + // Find and return the first successful result. + for (let i = 0; i < results.length; i++) { + if (results[i].supportsSession) { + return results[i]; + } + } + + // If there were no successful results, returns false. + return {supportsSession: false}; + }); + }; } -// Implements both XRDevice and VRMagicWindowProvider. Maintains a mock for -// XRPresentationProvider. -class MockDevice { +// Implements XRFrameDataProvider and XRPresentationProvider. Maintains a mock +// for XRPresentationProvider. +class MockRuntime { constructor(fakeDeviceInit, service) { this.sessionClient_ = new device.mojom.XRSessionClientPtr(); this.presentation_provider_ = new MockXRPresentationProvider(); @@ -86,13 +148,6 @@ } } - // Functions for setup. - getDevicePtr() { - let devicePtr = new device.mojom.XRDevicePtr(); - new mojo.Binding(device.mojom.XRDevice, this, mojo.makeRequest(devicePtr)); - return devicePtr; - } - // Test methods. setXRPresentationFrameData(poseMatrix, views) { if (poseMatrix == null) { @@ -273,9 +328,10 @@ // do not have any use for this data at present. } - // XRDevice implementation. - requestSession(sessionOptions, was_activation) { - return this.supportsSession(sessionOptions).then((result) => { + + // Utility function + requestRuntimeSession(sessionOptions) { + return this.runtimeSupportsSession(sessionOptions).then((result) => { // The JavaScript bindings convert c_style_names to camelCase names. let options = new device.mojom.XRPresentationTransportOptions(); options.transportMethod = @@ -320,7 +376,7 @@ }); } - supportsSession(options) { + runtimeSupportsSession(options) { return Promise.resolve({ supportsSession: !options.immersive || this.displayInfo_.capabilities.canPresent
diff --git a/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/interfaces-window.https.html b/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/interfaces-window.https.html index d3e85f2..85d7f646 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/interfaces-window.https.html +++ b/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/interfaces-window.https.html
@@ -51,4 +51,20 @@ idlArray.test(); }); }, 'test setup (worker registration)'); + +promise_test(t => { + const url = encodeURI(`data:text/html,<!DOCTYPE html> + <script> + parent.postMessage({ isDefined: 'serviceWorker' in navigator }, '*'); + </` + `script>`); + var p = new Promise((resolve, reject) => { + window.addEventListener('message', event => { + resolve(event.data.isDefined); + }); + }); + with_iframe(url); + return p.then(isDefined => { + assert_false(isDefined, 'navigator.serviceWorker should not be defined in iframe'); + }); +}, 'navigator.serviceWorker is not available in a data: iframe'); </script>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/local-url-inherit-controller.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/local-url-inherit-controller.https-expected.txt index 9a2bd38..829d980 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/local-url-inherit-controller.https-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/local-url-inherit-controller.https-expected.txt
@@ -3,7 +3,6 @@ FAIL Same-origin blob URL iframe should intercept fetch(). assert_equals: blob URL iframe should intercept fetch expected "intercepted" but got "Hello world\n" FAIL Same-origin blob URL worker should inherit service worker controller. promise_test: Unhandled rejection with value: "Uncaught TypeError: Cannot read property 'controller' of undefined" PASS Same-origin blob URL worker should intercept fetch(). -FAIL Data URL iframe should not inherit service worker controller. assert_equals: data URL iframe should not inherit controller expected (object) null but got (string) "Cannot read property 'controller' of undefined" PASS Data URL iframe should not intercept fetch(). FAIL Data URL worker should not inherit service worker controller. promise_test: Unhandled rejection with value: "Uncaught TypeError: Cannot read property 'controller' of undefined" FAIL Data URL worker should not intercept fetch(). assert_equals: data URL worker should not intercept fetch expected "" but got "intercepted"
diff --git a/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/local-url-inherit-controller.https.html b/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/local-url-inherit-controller.https.html index df25051b..6702abc 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/local-url-inherit-controller.https.html +++ b/third_party/WebKit/LayoutTests/external/wpt/service-workers/service-worker/local-url-inherit-controller.https.html
@@ -80,20 +80,6 @@ }, 'Same-origin blob URL worker should intercept fetch().'); promise_test(function(t) { - // Data URLs should result in an opaque origin and should probably not - // have access to a cross-origin service worker. See: - // - // https://github.com/w3c/ServiceWorker/issues/1262 - // - return doAsyncTest(t, { - scheme: 'data', - child: 'iframe', - check: 'controller', - expect: 'not inherit', - }); -}, 'Data URL iframe should not inherit service worker controller.'); - -promise_test(function(t) { return doAsyncTest(t, { scheme: 'data', child: 'iframe',
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webxr/idlharness.https.window-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/webxr/idlharness.https.window-expected.txt index a97d582..8d03a35 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/webxr/idlharness.https.window-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/webxr/idlharness.https.window-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -FAIL idl_test setup promise_test: Unhandled rejection with value: object "TypeError: Cannot read property 'requestDevice' of undefined" +PASS idl_test setup PASS Partial interface Navigator: original interface defined PASS Partial dictionary WebGLContextAttributes: original dictionary defined PASS Partial interface mixin WebGLRenderingContextBase: original interface mixin defined @@ -11,10 +11,10 @@ PASS XR interface: existence and properties of interface prototype object's @@unscopables property PASS XR interface: operation requestDevice() PASS XR interface: attribute ondevicechange -FAIL XR must be primary interface of navigator.XR assert_equals: wrong typeof object expected "object" but got "undefined" -FAIL Stringification of navigator.XR assert_equals: wrong typeof object expected "object" but got "undefined" -FAIL XR interface: navigator.XR must inherit property "requestDevice()" with the proper type assert_equals: wrong typeof object expected "object" but got "undefined" -FAIL XR interface: navigator.XR must inherit property "ondevicechange" with the proper type assert_equals: wrong typeof object expected "object" but got "undefined" +PASS XR must be primary interface of navigator.xr +PASS Stringification of navigator.xr +PASS XR interface: navigator.xr must inherit property "requestDevice()" with the proper type +PASS XR interface: navigator.xr must inherit property "ondevicechange" with the proper type PASS XRDevice interface: existence and properties of interface object PASS XRDevice interface object length PASS XRDevice interface object name @@ -23,12 +23,6 @@ PASS XRDevice interface: existence and properties of interface prototype object's @@unscopables property PASS XRDevice interface: operation supportsSession(XRSessionCreationOptions) PASS XRDevice interface: operation requestSession(XRSessionCreationOptions) -FAIL XRDevice must be primary interface of device assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: device is not defined" -FAIL Stringification of device assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: device is not defined" -FAIL XRDevice interface: device must inherit property "supportsSession(XRSessionCreationOptions)" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: device is not defined" -FAIL XRDevice interface: calling supportsSession(XRSessionCreationOptions) on device with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: device is not defined" -FAIL XRDevice interface: device must inherit property "requestSession(XRSessionCreationOptions)" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: device is not defined" -FAIL XRDevice interface: calling requestSession(XRSessionCreationOptions) on device with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: device is not defined" PASS XRSession interface: existence and properties of interface object PASS XRSession interface object length PASS XRSession interface object name @@ -54,30 +48,6 @@ FAIL XRSession interface: attribute onselect assert_true: The prototype object must have a property "onselect" expected true got false FAIL XRSession interface: attribute onselectstart assert_true: The prototype object must have a property "onselectstart" expected true got false FAIL XRSession interface: attribute onselectend assert_true: The prototype object must have a property "onselectend" expected true got false -FAIL XRSession must be primary interface of session assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: session is not defined" -FAIL Stringification of session assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: session is not defined" -FAIL XRSession interface: session must inherit property "device" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: session is not defined" -FAIL XRSession interface: session must inherit property "immersive" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: session is not defined" -FAIL XRSession interface: session must inherit property "outputContext" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: session is not defined" -FAIL XRSession interface: session must inherit property "environmentBlendMode" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: session is not defined" -FAIL XRSession interface: session must inherit property "depthNear" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: session is not defined" -FAIL XRSession interface: session must inherit property "depthFar" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: session is not defined" -FAIL XRSession interface: session must inherit property "baseLayer" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: session is not defined" -FAIL XRSession interface: session must inherit property "requestFrameOfReference(XRFrameOfReferenceType, XRFrameOfReferenceOptions)" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: session is not defined" -FAIL XRSession interface: calling requestFrameOfReference(XRFrameOfReferenceType, XRFrameOfReferenceOptions) on session with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: session is not defined" -FAIL XRSession interface: session must inherit property "getInputSources()" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: session is not defined" -FAIL XRSession interface: session must inherit property "requestAnimationFrame(XRFrameRequestCallback)" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: session is not defined" -FAIL XRSession interface: calling requestAnimationFrame(XRFrameRequestCallback) on session with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: session is not defined" -FAIL XRSession interface: session must inherit property "cancelAnimationFrame(long)" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: session is not defined" -FAIL XRSession interface: calling cancelAnimationFrame(long) on session with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: session is not defined" -FAIL XRSession interface: session must inherit property "end()" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: session is not defined" -FAIL XRSession interface: session must inherit property "onblur" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: session is not defined" -FAIL XRSession interface: session must inherit property "onfocus" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: session is not defined" -FAIL XRSession interface: session must inherit property "onresetpose" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: session is not defined" -FAIL XRSession interface: session must inherit property "onend" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: session is not defined" -FAIL XRSession interface: session must inherit property "onselect" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: session is not defined" -FAIL XRSession interface: session must inherit property "onselectstart" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: session is not defined" -FAIL XRSession interface: session must inherit property "onselectend" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: session is not defined" PASS XRFrame interface: existence and properties of interface object PASS XRFrame interface object length PASS XRFrame interface object name
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webxr/idlharness.https.window.js b/third_party/WebKit/LayoutTests/external/wpt/webxr/idlharness.https.window.js index 9576379..3e54e36 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/webxr/idlharness.https.window.js +++ b/third_party/WebKit/LayoutTests/external/wpt/webxr/idlharness.https.window.js
@@ -11,11 +11,7 @@ async idl_array => { idl_array.add_objects({ Navigator: ['navigator'], - XR: ['navigator.XR'], - XRDevice: ['device'], - XRSession: ['session'], + XR: ['navigator.xr'], }); - self.device = await navigator.XR.requestDevice(); - self.session = await device.requestSession(); } );
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webxr/interfaces.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/webxr/interfaces.https-expected.txt deleted file mode 100644 index 22b5ad2..0000000 --- a/third_party/WebKit/LayoutTests/external/wpt/webxr/interfaces.https-expected.txt +++ /dev/null
@@ -1,157 +0,0 @@ -This is a testharness.js-based test. -PASS Test IDL implementation of WebXR API -PASS Partial interface Navigator: original interface defined -PASS Partial dictionary WebGLContextAttributes: original dictionary defined -PASS Partial interface mixin WebGLRenderingContextBase: original interface mixin defined -PASS XR interface: existence and properties of interface object -PASS XR interface object length -PASS XR interface object name -PASS XR interface: existence and properties of interface prototype object -PASS XR interface: existence and properties of interface prototype object's "constructor" property -PASS XR interface: existence and properties of interface prototype object's @@unscopables property -PASS XR interface: operation requestDevice() -PASS XR interface: attribute ondevicechange -PASS XRDevice interface: existence and properties of interface object -PASS XRDevice interface object length -PASS XRDevice interface object name -PASS XRDevice interface: existence and properties of interface prototype object -PASS XRDevice interface: existence and properties of interface prototype object's "constructor" property -PASS XRDevice interface: existence and properties of interface prototype object's @@unscopables property -PASS XRDevice interface: operation supportsSession(XRSessionCreationOptions) -PASS XRDevice interface: operation requestSession(XRSessionCreationOptions) -PASS XRSession interface: existence and properties of interface object -PASS XRSession interface object length -PASS XRSession interface object name -PASS XRSession interface: existence and properties of interface prototype object -PASS XRSession interface: existence and properties of interface prototype object's "constructor" property -PASS XRSession interface: existence and properties of interface prototype object's @@unscopables property -PASS XRSession interface: attribute device -PASS XRSession interface: attribute immersive -PASS XRSession interface: attribute outputContext -PASS XRSession interface: attribute depthNear -PASS XRSession interface: attribute depthFar -PASS XRSession interface: attribute baseLayer -PASS XRSession interface: operation requestFrameOfReference(XRFrameOfReferenceType, XRFrameOfReferenceOptions) -PASS XRSession interface: operation requestAnimationFrame(XRFrameRequestCallback) -PASS XRSession interface: operation cancelAnimationFrame(long) -PASS XRSession interface: operation end() -PASS XRSession interface: attribute onblur -PASS XRSession interface: attribute onfocus -PASS XRSession interface: attribute onresetpose -PASS XRSession interface: attribute onend -PASS XRFrame interface: existence and properties of interface object -PASS XRFrame interface object length -PASS XRFrame interface object name -PASS XRFrame interface: existence and properties of interface prototype object -PASS XRFrame interface: existence and properties of interface prototype object's "constructor" property -PASS XRFrame interface: existence and properties of interface prototype object's @@unscopables property -PASS XRFrame interface: attribute views -PASS XRFrame interface: operation getDevicePose(XRCoordinateSystem) -FAIL XRCoordinateSystem interface: existence and properties of interface object assert_equals: prototype of XRCoordinateSystem is not EventTarget expected function "function EventTarget() { [native code] }" but got function "function () { [native code] }" -PASS XRCoordinateSystem interface object length -PASS XRCoordinateSystem interface object name -FAIL XRCoordinateSystem interface: existence and properties of interface prototype object assert_equals: prototype of XRCoordinateSystem.prototype is not EventTarget.prototype expected object "[object EventTarget]" but got object "[object Object]" -PASS XRCoordinateSystem interface: existence and properties of interface prototype object's "constructor" property -PASS XRCoordinateSystem interface: existence and properties of interface prototype object's @@unscopables property -PASS XRCoordinateSystem interface: operation getTransformTo(XRCoordinateSystem) -PASS XRFrameOfReference interface: existence and properties of interface object -PASS XRFrameOfReference interface object length -PASS XRFrameOfReference interface object name -PASS XRFrameOfReference interface: existence and properties of interface prototype object -PASS XRFrameOfReference interface: existence and properties of interface prototype object's "constructor" property -PASS XRFrameOfReference interface: existence and properties of interface prototype object's @@unscopables property -PASS XRFrameOfReference interface: attribute bounds -PASS XRFrameOfReference interface: attribute emulatedHeight -FAIL XRFrameOfReference interface: attribute onboundschange assert_true: The prototype object must have a property "onboundschange" expected true got false -PASS XRStageBounds interface: existence and properties of interface object -PASS XRStageBounds interface object length -PASS XRStageBounds interface object name -PASS XRStageBounds interface: existence and properties of interface prototype object -PASS XRStageBounds interface: existence and properties of interface prototype object's "constructor" property -PASS XRStageBounds interface: existence and properties of interface prototype object's @@unscopables property -PASS XRStageBounds interface: attribute geometry -PASS XRStageBoundsPoint interface: existence and properties of interface object -PASS XRStageBoundsPoint interface object length -PASS XRStageBoundsPoint interface object name -PASS XRStageBoundsPoint interface: existence and properties of interface prototype object -PASS XRStageBoundsPoint interface: existence and properties of interface prototype object's "constructor" property -PASS XRStageBoundsPoint interface: existence and properties of interface prototype object's @@unscopables property -PASS XRStageBoundsPoint interface: attribute x -PASS XRStageBoundsPoint interface: attribute z -PASS XRView interface: existence and properties of interface object -PASS XRView interface object length -PASS XRView interface object name -PASS XRView interface: existence and properties of interface prototype object -PASS XRView interface: existence and properties of interface prototype object's "constructor" property -PASS XRView interface: existence and properties of interface prototype object's @@unscopables property -PASS XRView interface: attribute eye -PASS XRView interface: attribute projectionMatrix -PASS XRViewport interface: existence and properties of interface object -PASS XRViewport interface object length -PASS XRViewport interface object name -PASS XRViewport interface: existence and properties of interface prototype object -PASS XRViewport interface: existence and properties of interface prototype object's "constructor" property -PASS XRViewport interface: existence and properties of interface prototype object's @@unscopables property -PASS XRViewport interface: attribute x -PASS XRViewport interface: attribute y -PASS XRViewport interface: attribute width -PASS XRViewport interface: attribute height -PASS XRDevicePose interface: existence and properties of interface object -PASS XRDevicePose interface object length -PASS XRDevicePose interface object name -PASS XRDevicePose interface: existence and properties of interface prototype object -PASS XRDevicePose interface: existence and properties of interface prototype object's "constructor" property -PASS XRDevicePose interface: existence and properties of interface prototype object's @@unscopables property -PASS XRDevicePose interface: attribute poseModelMatrix -PASS XRDevicePose interface: operation getViewMatrix(XRView) -PASS XRLayer interface: existence and properties of interface object -PASS XRLayer interface object length -PASS XRLayer interface object name -PASS XRLayer interface: existence and properties of interface prototype object -PASS XRLayer interface: existence and properties of interface prototype object's "constructor" property -PASS XRLayer interface: existence and properties of interface prototype object's @@unscopables property -PASS XRWebGLLayer interface: existence and properties of interface object -PASS XRWebGLLayer interface object length -PASS XRWebGLLayer interface object name -PASS XRWebGLLayer interface: existence and properties of interface prototype object -PASS XRWebGLLayer interface: existence and properties of interface prototype object's "constructor" property -PASS XRWebGLLayer interface: existence and properties of interface prototype object's @@unscopables property -PASS XRWebGLLayer interface: attribute context -PASS XRWebGLLayer interface: attribute antialias -PASS XRWebGLLayer interface: attribute depth -PASS XRWebGLLayer interface: attribute stencil -PASS XRWebGLLayer interface: attribute alpha -PASS XRWebGLLayer interface: attribute multiview -PASS XRWebGLLayer interface: attribute framebuffer -PASS XRWebGLLayer interface: attribute framebufferWidth -PASS XRWebGLLayer interface: attribute framebufferHeight -PASS XRWebGLLayer interface: operation getViewport(XRView) -PASS XRWebGLLayer interface: operation requestViewportScaling(double) -PASS XRPresentationContext interface: existence and properties of interface object -PASS XRPresentationContext interface object length -PASS XRPresentationContext interface object name -PASS XRPresentationContext interface: existence and properties of interface prototype object -PASS XRPresentationContext interface: existence and properties of interface prototype object's "constructor" property -PASS XRPresentationContext interface: existence and properties of interface prototype object's @@unscopables property -PASS XRPresentationContext interface: attribute canvas -PASS XRSessionEvent interface: existence and properties of interface object -PASS XRSessionEvent interface object length -PASS XRSessionEvent interface object name -PASS XRSessionEvent interface: existence and properties of interface prototype object -PASS XRSessionEvent interface: existence and properties of interface prototype object's "constructor" property -PASS XRSessionEvent interface: existence and properties of interface prototype object's @@unscopables property -PASS XRSessionEvent interface: attribute session -FAIL XRCoordinateSystemEvent interface: existence and properties of interface object assert_own_property: self does not have own property "XRCoordinateSystemEvent" expected property "XRCoordinateSystemEvent" missing -FAIL XRCoordinateSystemEvent interface object length assert_own_property: self does not have own property "XRCoordinateSystemEvent" expected property "XRCoordinateSystemEvent" missing -FAIL XRCoordinateSystemEvent interface object name assert_own_property: self does not have own property "XRCoordinateSystemEvent" expected property "XRCoordinateSystemEvent" missing -FAIL XRCoordinateSystemEvent interface: existence and properties of interface prototype object assert_own_property: self does not have own property "XRCoordinateSystemEvent" expected property "XRCoordinateSystemEvent" missing -FAIL XRCoordinateSystemEvent interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "XRCoordinateSystemEvent" expected property "XRCoordinateSystemEvent" missing -FAIL XRCoordinateSystemEvent interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "XRCoordinateSystemEvent" expected property "XRCoordinateSystemEvent" missing -FAIL XRCoordinateSystemEvent interface: attribute coordinateSystem assert_own_property: self does not have own property "XRCoordinateSystemEvent" expected property "XRCoordinateSystemEvent" missing -PASS WebGLRenderingContext interface: operation setCompatibleXRDevice(XRDevice) -PASS Navigator interface: attribute xr -PASS Navigator interface: navigator must inherit property "xr" with the proper type -PASS WorkerGlobalScope interface: existence and properties of interface object -PASS WorkerNavigator interface: existence and properties of interface object -Harness: the test ran to completion. -
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webxr/navigator_xr_requestDevice.https.html b/third_party/WebKit/LayoutTests/external/wpt/webxr/navigator_xr_requestDevice.https.html new file mode 100644 index 0000000..c51dd8db --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/webxr/navigator_xr_requestDevice.https.html
@@ -0,0 +1,19 @@ +<!DOCTYPE html> +<body> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + <script src="resources/webxr_util.js"></script> + + <script> + xr_promise_test("navigator.xr.requestDevice returns a device", (t) => { + return XRTest.simulateDeviceConnection({ supportsImmersive: true }) + .then( (controller) => { return navigator.xr.requestDevice() }) + .then( (device) => { + t.step(() => { + assert_true(device != null); + assert_true(device instanceof XRDevice); + }); + }); + }); + </script> +</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webxr/navigator_xr_requestDevice_no_device.https.html b/third_party/WebKit/LayoutTests/external/wpt/webxr/navigator_xr_requestDevice_no_device.https.html new file mode 100644 index 0000000..3cd149b --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/webxr/navigator_xr_requestDevice_no_device.https.html
@@ -0,0 +1,12 @@ +<!DOCTYPE html> +<body> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + <script src="resources/webxr_util.js"></script> + + <script> + promise_test( (t) => { + return promise_rejects(t, 'NotFoundError', navigator.xr.requestDevice()); + }, "navigator.xr.requestDevice properly rejects when there are 0 devices"); + </script> +</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webxr/resources/webxr_util.js b/third_party/WebKit/LayoutTests/external/wpt/webxr/resources/webxr_util.js index eaa7887..d73cf8d 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/webxr/resources/webxr_util.js +++ b/third_party/WebKit/LayoutTests/external/wpt/webxr/resources/webxr_util.js
@@ -7,7 +7,7 @@ // // --enable-blink-features=MojoJS,MojoJSTest -function xr_promise_test(func, name, properties) { +function xr_promise_test(name, func, properties) { promise_test(async (t) => { // Perform any required test setup: @@ -20,6 +20,74 @@ }, name, properties); } +// A test function which runs through the common steps of requesting a session. +// Calls the passed in test function with the session, the controller for the +// device, and the test object. +// Requires a webglCanvas on the page. +function xr_session_promise_test( + name, func, fakeDeviceInit, sessionOptions, properties) { + let testDevice; + let testDeviceController; + let testSession; + + const webglCanvas = document.getElementsByTagName('canvas')[0]; + if (!webglCanvas) { + promise_test(async (t) => { + Promise.reject('xr_session_promise_test requires a canvas on the page!'); + }, name, properties); + } + let gl = webglCanvas.getContext('webgl', {alpha: false, antialias: false}); + + xr_promise_test( + name, + (t) => + XRTest.simulateDeviceConnection(fakeDeviceInit) + .then((controller) => { + testDeviceController = controller; + return navigator.xr.requestDevice(); + }) + .then((device) => { + testDevice = device; + return gl.setCompatibleXRDevice(device); + }) + .then(() => new Promise((resolve, reject) => { + // Perform the session request in a user gesture. + XRTest.simulateUserActivation(() => { + testDevice.requestSession(sessionOptions) + .then((session) => { + testSession = session; + // Session must have a baseLayer or frame requests + // will be ignored. + session.baseLayer = new XRWebGLLayer(session, gl); + resolve(func(session, testDeviceController, t)); + }) + .catch((err) => { + reject( + 'Session with params ' + + JSON.stringify(sessionOptions) + + ' was rejected on device ' + + JSON.stringify(fakeDeviceInit) + + ' with error: ' + err); + }); + }); + })) + .then(() => { + // Cleanup system state. + testSession.end().catch(() => {}); + XRTest.simulateDeviceDisconnection(testDevice); + }), + properties); +} + +// A utility function to create an output context as required by non-immersive +// sessions. +// https://immersive-web.github.io/webxr/#xrsessioncreationoptions-interface +function getOutputContext() { + let outputCanvas = document.createElement('canvas'); + document.body.appendChild(outputCanvas); + return outputCanvas.getContext('xrpresent'); +} + // This functions calls a callback with each API object as specified // by https://immersive-web.github.io/webxr/spec/latest/, allowing // checks to be made on all ojects. @@ -59,8 +127,13 @@ let chain = Promise.resolve(); ['/gen/layout_test_data/mojo/public/js/mojo_bindings.js', - '/gen/ui/gfx/geometry/mojo/geometry.mojom.js', '/gen/mojo/public/mojom/base/time.mojom.js', + '/gen/gpu/ipc/common/mailbox_holder.mojom.js', + '/gen/gpu/ipc/common/sync_token.mojom.js', + '/gen/ui/display/mojo/display.mojom.js', + '/gen/ui/gfx/geometry/mojo/geometry.mojom.js', + '/gen/ui/gfx/mojo/gpu_fence_handle.mojom.js', + '/gen/ui/gfx/mojo/transform.mojom.js', '/gen/device/vr/public/mojom/vr_service.mojom.js', '/resources/chromium/webxr-test.js', '/resources/testdriver.js', '/resources/testdriver-vendor.js',
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webxr/webGLCanvasContext_create_with_xrdevice.https.html b/third_party/WebKit/LayoutTests/external/wpt/webxr/webGLCanvasContext_create_with_xrdevice.https.html new file mode 100644 index 0000000..94731cc --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/webxr/webGLCanvasContext_create_with_xrdevice.https.html
@@ -0,0 +1,27 @@ +<!DOCTYPE html> +<body> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + <script src="resources/webxr_util.js"></script> + <canvas id="webgl-canvas"></canvas> + <script> + xr_promise_test("webglCanvasContext can be created with an XRDevice", + (t) => { + return XRTest.simulateDeviceConnection({ supportsImmersive:true }) + .then( (controller) => { return navigator.xr.requestDevice() }) + .then( (device) => { + webglCanvas = document.getElementById('webgl-canvas'); + gl = webglCanvas.getContext('webgl', {compatibleXRDevice: device}); + assert_equals(gl.getContextAttributes().compatibleXRDevice, device); + + // Check that an offscreen context behaves no different. + let offscreenCanvas = document.createElement('canvas'); + let offscreenGl = webglCanvas.getContext( + 'webgl', {compatibleXRDevice: device}); + assert_equals( + offscreenGl.getContextAttributes().compatibleXRDevice, device); + }); + }); + + </script> +</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webxr/webGLCanvasContext_setdevice_contextlost.https.html b/third_party/WebKit/LayoutTests/external/wpt/webxr/webGLCanvasContext_setdevice_contextlost.https.html new file mode 100644 index 0000000..25f9869b --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/webxr/webGLCanvasContext_setdevice_contextlost.https.html
@@ -0,0 +1,24 @@ +<!DOCTYPE html> +<body> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + <script src="resources/webxr_util.js"></script> + <canvas id="webgl-canvas"></canvas> + <script> + + xr_promise_test( + "A lost webglCanvasContext should not be able to set device", + (t) => { + return XRTest.simulateDeviceConnection({ supportsImmersive:true }) + .then( (controller) => { return navigator.xr.requestDevice() }) + .then( (device) => { + webglCanvas = document.getElementById('webgl-canvas'); + gl = webglCanvas.getContext('webgl', {compatibleXRDevice: device}); + gl.getExtension('WEBGL_lose_context').loseContext(); + return promise_rejects(t, 'InvalidStateError', + gl.setCompatibleXRDevice(device)); + }); + }); + + </script> +</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webxr/xrDevice_requestSession_immersive.https.html b/third_party/WebKit/LayoutTests/external/wpt/webxr/xrDevice_requestSession_immersive.https.html new file mode 100644 index 0000000..e9e7b9bc --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/webxr/xrDevice_requestSession_immersive.https.html
@@ -0,0 +1,14 @@ +<!DOCTYPE html> +<body> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + <script src="resources/webxr_util.js"></script> + <canvas></canvas> + <script> + xr_session_promise_test( + "Tests requestSession resolves when supported", + (session) => { + assert_not_equals(session, null); + }, { supportsImmersive:true }, { immersive: true }); + </script> +</body> \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webxr/xrDevice_requestSession_immersive_no_gesture.https.html b/third_party/WebKit/LayoutTests/external/wpt/webxr/xrDevice_requestSession_immersive_no_gesture.https.html new file mode 100644 index 0000000..9f0f5f3 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/webxr/xrDevice_requestSession_immersive_no_gesture.https.html
@@ -0,0 +1,16 @@ +<!DOCTYPE html> +<body> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + <script src="resources/webxr_util.js"></script> + <script> + xr_promise_test( + "Requesting immersive session outside of a user gesture rejects", + (t) => { + return XRTest.simulateDeviceConnection({ supportsImmersive:true }) + .then( (controller) => { return navigator.xr.requestDevice() }) + .then( (device) => promise_rejects( + t, 'SecurityError', device.requestSession({ immersive: true }))); + }); + </script> +</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webxr/xrDevice_requestSession_immersive_unsupported.https.html b/third_party/WebKit/LayoutTests/external/wpt/webxr/xrDevice_requestSession_immersive_unsupported.https.html new file mode 100644 index 0000000..e0d2688e --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/webxr/xrDevice_requestSession_immersive_unsupported.https.html
@@ -0,0 +1,23 @@ +<!DOCTYPE html> +<body> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + <script src="resources/webxr_util.js"></script> + <script> + xr_promise_test( + "Requesting an immersive session when unsupported rejects", + (t) => { + return XRTest.simulateDeviceConnection({ supportsImmersive:false }) + .then( (controller) => { return navigator.xr.requestDevice() }) + .then( (magicWindowOnlyDevice) => new Promise((resolve) => { + XRTest.simulateUserActivation( () => { + resolve(promise_rejects( + t, + "NotSupportedError", + magicWindowOnlyDevice.requestSession({ immersive: true }) + )) + }); + })); + }); + </script> +</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webxr/xrDevice_requestSession_non_immersive_no_gesture.https.html b/third_party/WebKit/LayoutTests/external/wpt/webxr/xrDevice_requestSession_non_immersive_no_gesture.https.html new file mode 100644 index 0000000..1634dfe --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/webxr/xrDevice_requestSession_non_immersive_no_gesture.https.html
@@ -0,0 +1,19 @@ +<!DOCTYPE html> +<body> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + <script src="resources/webxr_util.js"></script> + <script> + xr_promise_test( + "Requesting non-immersive session outside of a user gesture succeeds", + (t) => { + return XRTest.simulateDeviceConnection({ supportsImmersive:false }) + .then( (controller) => { return navigator.xr.requestDevice(); }) + .then( (device) => device.requestSession({ + immersive: false, + outputContext: getOutputContext() + })) + .then( (session) => { assert_not_equals(session, null); }); + }); + </script> +</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webxr/xrDevice_supportsSession_immersive.https.html b/third_party/WebKit/LayoutTests/external/wpt/webxr/xrDevice_supportsSession_immersive.https.html new file mode 100644 index 0000000..3ca5eb11 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/webxr/xrDevice_supportsSession_immersive.https.html
@@ -0,0 +1,15 @@ +<!DOCTYPE html> +<body> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + <script src="resources/webxr_util.js"></script> + <script> + xr_promise_test( + "supportsSession resolves when immersive options supported", + () => { + return XRTest.simulateDeviceConnection({ supportsImmersive:true }) + .then( (controller) => { return navigator.xr.requestDevice() }) + .then( (device) => device.supportsSession({ immersive: true })); + }); + </script> +</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webxr/xrDevice_supportsSession_immersive_unsupported.https.html b/third_party/WebKit/LayoutTests/external/wpt/webxr/xrDevice_supportsSession_immersive_unsupported.https.html new file mode 100644 index 0000000..0c1dd258 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/webxr/xrDevice_supportsSession_immersive_unsupported.https.html
@@ -0,0 +1,21 @@ +<!DOCTYPE html> +<body> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + <script src="resources/webxr_util.js"></script> + <script> + xr_promise_test( + "supportsSession rejects when options not supported", + (t) => { + return XRTest.simulateDeviceConnection({ supportsImmersive:false }) + .then( (controller) => { return navigator.xr.requestDevice() }) + .then( (device) => { + return promise_rejects( + t, + "NotSupportedError", + device.supportsSession({ immersive: true }) + ); + }); + }); + </script> +</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webxr/xrDevice_supportsSession_non_immersive.https.html b/third_party/WebKit/LayoutTests/external/wpt/webxr/xrDevice_supportsSession_non_immersive.https.html new file mode 100644 index 0000000..535b0bc --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/webxr/xrDevice_supportsSession_non_immersive.https.html
@@ -0,0 +1,23 @@ +<!DOCTYPE html> +<body> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + <script src="resources/webxr_util.js"></script> + <script> + xr_promise_test( + "supportsSession resolves when non-immersive options supported", + (t) => { + return XRTest.simulateDeviceConnection({ supportsImmersive:true }) + .then( (controller) => { return navigator.xr.requestDevice() }) + .then( (device) => { + // Non-immersive sessions without a outputContext should not be supported. + promise_rejects(t, 'NotSupportedError', device.supportsSession()); + + // Non-immersive sessions with an outputContext should be supported. + return device.supportsSession({ + outputContext: getOutputContext() + }); + }); + }); + </script> +</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webxr/xrSession_cancelAnimationFrame.https.html b/third_party/WebKit/LayoutTests/external/wpt/webxr/xrSession_cancelAnimationFrame.https.html new file mode 100644 index 0000000..26c0e95 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/webxr/xrSession_cancelAnimationFrame.https.html
@@ -0,0 +1,58 @@ +<!DOCTYPE html> +<body> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + <script src="resources/webxr_util.js"></script> + <canvas></canvas> + + <script> + let immersiveTestName = "XRSession requestAnimationFrame callbacks can be " + + "unregistered with cancelAnimationFrame for immersive sessions"; + let nonImmersiveTestName = "XRSession requestAnimationFrame callbacks can be " + + "unregistered with cancelAnimationFrame for non-immersive sessions"; + + let fakeDeviceInitParams = { supportsImmersive:true }; + + let immersiveSessionOptions = { immersive: true }; + let nonImmersiveSessionOptions = { outputContext: getOutputContext() }; + + let testFunction = (session) => new Promise((resolve, reject) => { + + // Schedule and immediately cancel animation frame + session.cancelAnimationFrame(session.requestAnimationFrame( + (time, vrFrame) => { reject("Cancelled frame callback was called"); })); + + let counter = 0; + let handle; + function onFrame(time, vrFrame) { + // Cancel the second animation frame. + if (handle != 0) { + session.cancelAnimationFrame(handle); + handle = 0; + } + + // Run a few more animation frames to be sure that the cancelled frame isn't + // going to call. + counter++; + if (counter >= 4) { + // Ok, we're done here. + resolve(); + } else { + session.requestAnimationFrame(onFrame); + } + } + + // Schedule two animation frame and cancel one during on animation frame. + session.requestAnimationFrame(onFrame); + handle = session.requestAnimationFrame( + (time, vrFrame) => { reject("Cancelled frame callback was called"); }); + }); + + xr_session_promise_test(immersiveTestName, testFunction, + fakeDeviceInitParams, immersiveSessionOptions); + xr_session_promise_test(nonImmersiveTestName, testFunction, + fakeDeviceInitParams, nonImmersiveSessionOptions); + + </script> +</body> +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webxr/xrSession_cancelAnimationFrame_invalidhandle.https.html b/third_party/WebKit/LayoutTests/external/wpt/webxr/xrSession_cancelAnimationFrame_invalidhandle.https.html new file mode 100644 index 0000000..4f4b8dfe --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/webxr/xrSession_cancelAnimationFrame_invalidhandle.https.html
@@ -0,0 +1,45 @@ +<!DOCTYPE html> +<body> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + <script src="resources/webxr_util.js"></script> + <canvas></canvas> + <script> + let immersiveTestName = "XRSession cancelAnimationFrame does not have unexpected " + + "behavior when given invalid handles on immersive testSession"; + let nonImmersiveTestName = "XRSession cancelAnimationFrame does not have unexpected " + + "behavior when given invalid handles on non-immersive testSession"; + + let fakeDeviceInitParams = { supportsImmersive:true }; + + let immersiveSessionOptions = { immersive: true }; + let nonImmersiveSessionOptions = { outputContext: getOutputContext() }; + + let testFunction = (testSession) => new Promise((resolve) => { + let counter = 0; + + function onFrame(time, vrFrame) { + if(counter <= 10) { + testSession.requestAnimationFrame(onFrame); + } else { + resolve(); + } + counter++; + } + + let handle = testSession.requestAnimationFrame(onFrame); + testSession.cancelAnimationFrame(0); + testSession.cancelAnimationFrame(-1); + testSession.cancelAnimationFrame(handle + 1); + testSession.cancelAnimationFrame(handle - 1); + testSession.cancelAnimationFrame(0.5); + testSession.cancelAnimationFrame(null); + }); + + xr_session_promise_test( + immersiveTestName, testFunction, fakeDeviceInitParams, immersiveSessionOptions); + xr_session_promise_test( + nonImmersiveTestName, testFunction, fakeDeviceInitParams, nonImmersiveSessionOptions); + + </script> +</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webxr/xrSession_device.https.html b/third_party/WebKit/LayoutTests/external/wpt/webxr/xrSession_device.https.html new file mode 100644 index 0000000..0b482f5 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/webxr/xrSession_device.https.html
@@ -0,0 +1,24 @@ +<!DOCTYPE html> +<body> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + <script src="resources/webxr_util.js"></script> + <canvas></canvas> + + <script> + xr_promise_test("Requested session has device set", + (t) => { + return XRTest.simulateDeviceConnection({ supportsImmersive:true }) + .then( (controller) => { return navigator.xr.requestDevice() }) + .then( (device) => new Promise((resolve) => { + XRTest.simulateUserActivation( () => { + resolve(device.requestSession({ immersive: true }).then( (session) => { + assert_true(session.immersive); + assert_equals(session.device, device); + })); + }); + })); + }); + </script> +</body> +
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webxr/xrSession_end.https.html b/third_party/WebKit/LayoutTests/external/wpt/webxr/xrSession_end.https.html new file mode 100644 index 0000000..69bbda8 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/webxr/xrSession_end.https.html
@@ -0,0 +1,38 @@ +<!DOCTYPE html> +<body> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + <script src="resources/webxr_util.js"></script> + <canvas></canvas> + + <script> + const immersivetestName = "end event fires when immersive session ends"; + const nonimmersiveTestName = "end event fires when non-immersive session ends"; + let watcherDone = new Event("watcherdone"); + const fakeDeviceInitParams = { supportsImmersive:true }; + + const immersiveSessionOptions = { immersive: true }; + const nonImmersiveSessionOptions = { outputContext: getOutputContext() }; + + let testFunction = function(session, testDeviceController, t) { + let eventWatcher = new EventWatcher(t, session, ["end", "watcherdone"]); + let eventPromise = eventWatcher.wait_for(["end", "watcherdone"]); + + function onSessionEnd(event) { + t.step( () => { + assert_equals(event.session, session); + session.dispatchEvent(watcherDone); + }); + } + session.addEventListener("end", onSessionEnd, false); + session.end(); + + return eventPromise; + }; + + xr_session_promise_test(immersivetestName, testFunction, + fakeDeviceInitParams, immersiveSessionOptions); + xr_session_promise_test(nonimmersiveTestName, testFunction, + fakeDeviceInitParams, nonImmersiveSessionOptions); + </script> +</body> \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webxr/xrSession_exclusive_requestAnimationFrame.https.html b/third_party/WebKit/LayoutTests/external/wpt/webxr/xrSession_exclusive_requestAnimationFrame.https.html deleted file mode 100644 index 010ab0b1..0000000 --- a/third_party/WebKit/LayoutTests/external/wpt/webxr/xrSession_exclusive_requestAnimationFrame.https.html +++ /dev/null
@@ -1,91 +0,0 @@ -<!DOCTYPE html> -<body> - <script src=/resources/testharness.js></script> - <script src=/resources/testharnessreport.js></script> - <script src="resources/webxr_util.js"></script> - <canvas id="webgl-canvas"></canvas> - - <script> - - const identityMatrix = new Float32Array([ - 1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1 - ]); - - const rightFakeXRViewInit = - {eye:"right", projectionMatrix: identityMatrix, viewMatrix: identityMatrix}; - - const leftFakeXRViewInit = - {eye:"left", projectionMatrix: identityMatrix, viewMatrix: identityMatrix}; - - const immersiveFakeXRDeviceInit = { supportsImmersive:true }; - - const webglCanvas = document.getElementById('webgl-canvas'); - let gl = webglCanvas.getContext('webgl', { alpha: false, antialias: false }); - - let testDevice; - let testDeviceController; - let testSession; - - xr_promise_test( - (t) => XRTest.simulateDeviceConnection(immersiveFakeXRDeviceInit) - .then((controller) => { - testDeviceController = controller; - return navigator.xr.requestDevice(); - }) - .then((device) => { - testDevice = device; - return gl.setCompatibleXRDevice(device); - }) - .then(() => new Promise((resolve, reject) => { - // Perform the session request in a user gesture. - XRTest.simulateUserActivation(() => { - testDevice.requestSession({ immersive: true }) - .then((session) => { - testSession = session; - return session.requestFrameOfReference('eye-level'); - }) - .then((frameOfRef) => { - // Session must have a baseLayer or frame requests will be ignored. - testSession.baseLayer = new XRWebGLLayer(testSession, gl); - - function onFrame(time, xrFrame) { - assert_true(xrFrame instanceof XRFrame); - - assert_not_equals(xrFrame.views, null); - assert_equals(xrFrame.views.length, 2); - - let devicePose = xrFrame.getDevicePose(frameOfRef); - - assert_not_equals(devicePose, null); - for(let i = 0; i < identityMatrix.length; i++) { - assert_equals(devicePose.poseModelMatrix[i], identityMatrix[i]); - } - - assert_not_equals(devicePose.getViewMatrix(xrFrame.views[0]), null); - assert_equals(devicePose.getViewMatrix(xrFrame.views[0]).length, 16); - assert_not_equals(devicePose.getViewMatrix(xrFrame.views[1]), null); - assert_equals(devicePose.getViewMatrix(xrFrame.views[1]).length, 16); - - // Test does not complete until the returned promise resolves. - resolve(); - } - - testDeviceController.setXRPresentationFrameData( - identityMatrix, - [rightFakeXRViewInit, leftFakeXRViewInit] - ); - - testSession.requestAnimationFrame(onFrame); - }).catch((err) => { - reject("Session was rejected with error: "+err); - }); - }); - }) - ), - "RequestAnimationFrame resolves with good data" - ); - </script> -</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webxr/xrSession_prevent_multiple_exclusive.https.html b/third_party/WebKit/LayoutTests/external/wpt/webxr/xrSession_prevent_multiple_exclusive.https.html new file mode 100644 index 0000000..ff3eaef --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/webxr/xrSession_prevent_multiple_exclusive.https.html
@@ -0,0 +1,43 @@ +<!DOCTYPE html> +<body> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + <script src="resources/webxr_util.js"></script> + <canvas></canvas> + + <script> + xr_promise_test( + "Test prevention of multiple simultaneous immersive sessions", + (t) => { + return XRTest.simulateDeviceConnection({ supportsImmersive:true }) + .then( (controller) => { return navigator.xr.requestDevice() }) + .then( (device) => new Promise((resolve) => { + XRTest.simulateUserActivation( () => { + resolve(device.requestSession({ immersive: true }) + .then( (session) => new Promise((resolve) => { + XRTest.simulateUserActivation( () => { + // Requesting a second immersive session from a device that already + // has an active immersive session should fail. Immersive sessions + // should take up the users entire view, and therefore it should + // be impossible for a user to be engaged with more than one. + resolve(promise_rejects( + t, + "InvalidStateError", + device.requestSession({ immersive: true }) + ).then( () => { + // End the immersive session and try again. Now the immersive + // session creation should succeed. + return session.end().then( () => new Promise((resolve) => { + XRTest.simulateUserActivation( () => { + resolve(device.requestSession({ immersive: true })); + }); + })); + })); + }); + }))); + }); + })); + }); + + </script> +</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webxr/xrSession_requestAnimationFrame_callback_calls.https.html b/third_party/WebKit/LayoutTests/external/wpt/webxr/xrSession_requestAnimationFrame_callback_calls.https.html new file mode 100644 index 0000000..48dc887 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/webxr/xrSession_requestAnimationFrame_callback_calls.https.html
@@ -0,0 +1,35 @@ +<!DOCTYPE html> +<body> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + <script src="resources/webxr_util.js"></script> + <canvas></canvas> + + <script> + let immersiveTestName = "XRSession requestAnimationFrame calls the " + + "provided callback for an immersive session"; + let nonImmersiveTestName = "XRSession requestAnimationFrame calls the " + + "provided callback a non-immersive session"; + + let fakeDeviceInitParams = { supportsImmersive:true }; + + let immersiveSessionOptions = { immersive: true }; + let nonImmersiveSessionOptions = { outputContext: getOutputContext() }; + + let testFunction = (testSession) => new Promise((resolve) => { + function onFrame(time, xrFrame) { + assert_true(xrFrame instanceof XRFrame); + // Test does not complete until the returned promise resolves. + resolve(); + } + + testSession.requestAnimationFrame(onFrame); + }); + + xr_session_promise_test(immersiveTestName, testFunction, + fakeDeviceInitParams, immersiveSessionOptions); + xr_session_promise_test(nonImmersiveTestName, testFunction, + fakeDeviceInitParams, nonImmersiveSessionOptions); + + </script> +</body> \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webxr/xrSession_requestAnimationFrame_data_valid.https.html b/third_party/WebKit/LayoutTests/external/wpt/webxr/xrSession_requestAnimationFrame_data_valid.https.html new file mode 100644 index 0000000..702932a --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/webxr/xrSession_requestAnimationFrame_data_valid.https.html
@@ -0,0 +1,75 @@ +<!DOCTYPE html> +<body> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + <script src="resources/webxr_util.js"></script> + <canvas></canvas> + + <script> + const testName = "RequestAnimationFrame resolves with good data"; + + const identityMatrix = new Float32Array([ + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1 + ]); + + const rightFakeXRViewInit = { + eye:"right", + projectionMatrix: identityMatrix, + viewMatrix: identityMatrix + }; + + const leftFakeXRViewInit = { + eye:"left", + projectionMatrix: identityMatrix, + viewMatrix: identityMatrix + }; + + const fakeDeviceInitOptions = { supportsImmersive:true }; + const sessionOptions = { immersive:true }; + + let testSession; + + let testFunction = function(session, testDeviceController) { + testSession = session; + return session.requestFrameOfReference('eye-level') + .then((frameOfRef) => new Promise((resolve) => { + + function onFrame(time, xrFrame) { + assert_true(xrFrame instanceof XRFrame); + + assert_not_equals(xrFrame.views, null); + assert_equals(xrFrame.views.length, 2); + + let devicePose = xrFrame.getDevicePose(frameOfRef); + + assert_not_equals(devicePose, null); + for(let i = 0; i < identityMatrix.length; i++) { + assert_equals(devicePose.poseModelMatrix[i], identityMatrix[i]); + } + + assert_not_equals(devicePose.getViewMatrix(xrFrame.views[0]), null); + assert_equals(devicePose.getViewMatrix(xrFrame.views[0]).length, 16); + assert_not_equals(devicePose.getViewMatrix(xrFrame.views[1]), null); + assert_equals(devicePose.getViewMatrix(xrFrame.views[1]).length, 16); + + // Test does not complete until the returned promise resolves. + resolve(); + } + + testDeviceController.setXRPresentationFrameData( + identityMatrix, + [rightFakeXRViewInit, leftFakeXRViewInit] + ); + + testSession.requestAnimationFrame(onFrame); + }) + ); + } + + xr_session_promise_test( + testName, testFunction, fakeDeviceInitOptions, sessionOptions); + </script> +</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webxr/xrSession_requestAnimationFrame_getDevicePose.https-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/webxr/xrSession_requestAnimationFrame_getDevicePose.https-expected.txt deleted file mode 100644 index 2eb1e952..0000000 --- a/third_party/WebKit/LayoutTests/external/wpt/webxr/xrSession_requestAnimationFrame_getDevicePose.https-expected.txt +++ /dev/null
@@ -1,5 +0,0 @@ -This is a testharness.js-based test. -PASS XRFrame getDevicePose updates on the next frame for immersive sessions -FAIL XRFrame getDevicePose updates on the next frame for non-immersive sessions assert_equals: expected null but got object "[object XRDevicePose]" -Harness: the test ran to completion. -
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webxr/xrSession_requestAnimationFrame_getDevicePose.https.html b/third_party/WebKit/LayoutTests/external/wpt/webxr/xrSession_requestAnimationFrame_getDevicePose.https.html new file mode 100644 index 0000000..195e653 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/webxr/xrSession_requestAnimationFrame_getDevicePose.https.html
@@ -0,0 +1,79 @@ +<!DOCTYPE html> +<body> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + <script src="resources/webxr_util.js"></script> + <canvas></canvas> + + <script> + + let immersiveTestName = + "XRFrame getDevicePose updates on the next frame for immersive sessions"; + let nonImmersiveTestName = + "XRFrame getDevicePose updates on the next frame for non-immersive sessions"; + + let fakeDeviceInitParams = { supportsImmersive: true }; + + let immersiveSessionOptions = { immersive: true }; + let nonImmersiveSessionOptions = { outputContext: getOutputContext() }; + + // Valid matrices for when we don't care about specific values + const validPoseMatrix = [0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1]; + const validProjectionMatrix = [1, 0, 0, 0, 0, 1, 0, 0, 3, 2, -1, -1, 0, 0, -0.2, 0]; + const validViewMatrix = [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 4, 3, 2, 1]; + + let testFunction = function(session, fakeDeviceController, t) { + return session.requestFrameOfReference("eye-level") + .then((frameOfRef) => new Promise((resolve, reject) => { + let counter = 0; + function onFrame(time, vrFrame) { + session.requestAnimationFrame(onFrame); + if (counter == 0) { + t.step( () => { + // Expecting to not get a pose since none has been supplied + assert_equals(vrFrame.getDevicePose(frameOfRef), null); + + fakeDeviceController.setXRPresentationFrameData( + validPoseMatrix, [{ + eye:"left", + projectionMatrix: validProjectionMatrix, + viewMatrix: validViewMatrix + }, { + eye:"right", + projectionMatrix: validProjectionMatrix, + viewMatrix: validViewMatrix + }]); + + // Check that pose does not update pose within the same frame. + assert_equals(vrFrame.getDevicePose(frameOfRef), null); + }); + } else { + t.step( () => { + let pose = vrFrame.getDevicePose(frameOfRef); + assert_not_equals(pose, null); + + let poseMatrix = pose.poseModelMatrix; + assert_not_equals(poseMatrix, null); + + for(let i = 0; i < poseMatrix.length; i++) { + assert_equals(poseMatrix[i], validPoseMatrix[i]); + } + }); + + // Finished. + resolve(); + } + counter++; + } + + session.requestAnimationFrame(onFrame); + })); + }; + + xr_session_promise_test(nonImmersiveTestName, testFunction, + fakeDeviceInitParams, nonImmersiveSessionOptions); + xr_session_promise_test(immersiveTestName, testFunction, + fakeDeviceInitParams, immersiveSessionOptions); + + </script> +</body>
diff --git a/third_party/WebKit/LayoutTests/external/wpt/webxr/xrSession_requestFrameOfReference.https.html b/third_party/WebKit/LayoutTests/external/wpt/webxr/xrSession_requestFrameOfReference.https.html new file mode 100644 index 0000000..ea75876 --- /dev/null +++ b/third_party/WebKit/LayoutTests/external/wpt/webxr/xrSession_requestFrameOfReference.https.html
@@ -0,0 +1,49 @@ +<!DOCTYPE html> +<body> + <script src=/resources/testharness.js></script> + <script src=/resources/testharnessreport.js></script> + <script src="resources/webxr_util.js"></script> + <canvas></canvas> + <script> + + let immersiveTestName = + "Immersive XRSession requestFrameOfReference returns expected objects"; + let nonImmersiveTestName = + "Non-immersive XRSession requestFrameOfReference returns expected objects"; + + let fakeDeviceInitParams = { supportsImmersive: true }; + + let immersiveSessionOptions = { immersive: true }; + let nonImmersiveSessionOptions = { outputContext: getOutputContext() }; + + let testFunction = function(session, fakeDeviceController, t) { + return promise_rejects(t, new TypeError(), session.requestFrameOfReference("foo")) + .then(() => Promise.all([ + session.requestFrameOfReference("head-model").then( (frameOfRef) => { + assert_true(frameOfRef instanceof XRCoordinateSystem, + "head-model frameOfRef is not correct type."); + assert_true(frameOfRef instanceof XRFrameOfReference, + "head-model frameOfRef is not correct type."); + }), + session.requestFrameOfReference("eye-level").then( (frameOfRef) => { + assert_true(frameOfRef instanceof XRCoordinateSystem, + "eye-level frameOfRef is not correct type."); + assert_true(frameOfRef instanceof XRFrameOfReference, + "eye-level frameOfRef is not correct type."); + }), + session.requestFrameOfReference("stage").then( (frameOfRef) => { + assert_true(frameOfRef instanceof XRCoordinateSystem, + "stage frameOfRef is not correct type."); + assert_true(frameOfRef instanceof XRFrameOfReference, + "stage frameOfRef is not correct type."); + }) + ])); + }; + + xr_session_promise_test( + immersiveTestName, testFunction, fakeDeviceInitParams, immersiveSessionOptions); + xr_session_promise_test( + nonImmersiveTestName, testFunction, fakeDeviceInitParams, nonImmersiveSessionOptions); + + </script> +</body> \ No newline at end of file
diff --git a/third_party/WebKit/LayoutTests/external/wpt/workers/interfaces.worker-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/workers/interfaces.worker-expected.txt index 12a7eec..80841e38 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/workers/interfaces.worker-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/workers/interfaces.worker-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 161 tests; 149 PASS, 12 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 161 tests; 151 PASS, 10 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS EventTarget interface: existence and properties of interface object PASS EventTarget interface object length PASS EventTarget interface object name @@ -47,7 +47,7 @@ PASS DedicatedWorkerGlobalScope interface: internal [[SetPrototypeOf]] method of interface prototype object - setting to its original value via Reflect.setPrototypeOf should return true PASS DedicatedWorkerGlobalScope interface: existence and properties of interface prototype object's "constructor" property PASS DedicatedWorkerGlobalScope interface: existence and properties of interface prototype object's @@unscopables property -FAIL DedicatedWorkerGlobalScope interface: attribute name assert_own_property: The global object must have a property "name" expected property "name" missing +PASS DedicatedWorkerGlobalScope interface: attribute name PASS DedicatedWorkerGlobalScope interface: operation postMessage(any, [object Object]) PASS DedicatedWorkerGlobalScope interface: operation close() PASS DedicatedWorkerGlobalScope interface: attribute onmessage @@ -60,7 +60,7 @@ PASS DedicatedWorkerGlobalScope interface: internal [[SetPrototypeOf]] method of global platform object - setting to its original value via Reflect.setPrototypeOf should return true PASS DedicatedWorkerGlobalScope must be primary interface of self PASS Stringification of self -FAIL DedicatedWorkerGlobalScope interface: self must inherit property "name" with the proper type assert_own_property: expected property "name" missing +PASS DedicatedWorkerGlobalScope interface: self must inherit property "name" with the proper type PASS DedicatedWorkerGlobalScope interface: self must inherit property "postMessage(any, [object Object])" with the proper type PASS DedicatedWorkerGlobalScope interface: calling postMessage(any, [object Object]) on self with too few arguments must throw TypeError PASS DedicatedWorkerGlobalScope interface: self must inherit property "close()" with the proper type
diff --git a/third_party/WebKit/LayoutTests/external/wpt/workers/name-property-expected.txt b/third_party/WebKit/LayoutTests/external/wpt/workers/name-property-expected.txt index b5b6cb2..0c142db 100644 --- a/third_party/WebKit/LayoutTests/external/wpt/workers/name-property-expected.txt +++ b/third_party/WebKit/LayoutTests/external/wpt/workers/name-property-expected.txt
@@ -1,5 +1,9 @@ This is a testharness.js-based test. -FAIL name property value for DedicatedWorkerGlobalScope assert_true: property exists on the global expected true got false +PASS name property value for DedicatedWorkerGlobalScope +PASS name property is replaceable for DedicatedWorkerGlobalScope +PASS Declaring name as an accidental global must not cause a harness error for DedicatedWorkerGlobalScope FAIL name property value for SharedWorkerGlobalScope assert_equals: expected "my name" but got "[object Object]" +FAIL name property is replaceable for SharedWorkerGlobalScope Cannot assign to read only property 'name' of object '#<SharedWorkerGlobalScope>' +FAIL name-as-accidental-global Uncaught TypeError: Cannot assign to read only property 'name' of object '#<SharedWorkerGlobalScope>' Harness: the test ran to completion.
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/tracing/timeline-gpu-tasks-expected.txt b/third_party/WebKit/LayoutTests/http/tests/devtools/tracing/timeline-gpu-tasks-expected.txt new file mode 100644 index 0000000..c4d9058 --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/tracing/timeline-gpu-tasks-expected.txt
@@ -0,0 +1,4 @@ +Tests the Timeline events for GPUTask + +Found GPUTask events: true +
diff --git a/third_party/WebKit/LayoutTests/http/tests/devtools/tracing/timeline-gpu-tasks.js b/third_party/WebKit/LayoutTests/http/tests/devtools/tracing/timeline-gpu-tasks.js new file mode 100644 index 0000000..7b2a7aa --- /dev/null +++ b/third_party/WebKit/LayoutTests/http/tests/devtools/tracing/timeline-gpu-tasks.js
@@ -0,0 +1,24 @@ +// 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. + +(async function() { + TestRunner.addResult(`Tests the Timeline events for GPUTask\n`); + await TestRunner.loadModule('performance_test_runner'); + await TestRunner.showPanel('timeline'); + await TestRunner.evaluateInPagePromise(` + async function performActions() { + const gl = document.createElement('canvas').getContext('webgl'); + return gl.getParameter(gl.MAX_VIEWPORT_DIMS); + } + `); + + await PerformanceTestRunner.invokeAsyncWithTimeline('performActions'); + + const tracingModel = PerformanceTestRunner.tracingModel(); + const hasGPUTasks = tracingModel.sortedProcesses().some(p => p.sortedThreads().some(t => t.events().some( + event => event.name === TimelineModel.TimelineModel.RecordType.GPUTask))); + TestRunner.addResult(`Found GPUTask events: ${hasGPUTasks}`); + + TestRunner.completeTest(); +})();
diff --git a/third_party/WebKit/LayoutTests/http/tests/loading/sxg/resources/fallback-to-another-sxg.sxg b/third_party/WebKit/LayoutTests/http/tests/loading/sxg/resources/fallback-to-another-sxg.sxg index 7d5b892..9577748 100644 --- a/third_party/WebKit/LayoutTests/http/tests/loading/sxg/resources/fallback-to-another-sxg.sxg +++ b/third_party/WebKit/LayoutTests/http/tests/loading/sxg/resources/fallback-to-another-sxg.sxg Binary files differ
diff --git a/third_party/WebKit/LayoutTests/http/tests/loading/sxg/resources/sxg-cert-not-found.sxg b/third_party/WebKit/LayoutTests/http/tests/loading/sxg/resources/sxg-cert-not-found.sxg index 1a403d1..bcc218d 100644 --- a/third_party/WebKit/LayoutTests/http/tests/loading/sxg/resources/sxg-cert-not-found.sxg +++ b/third_party/WebKit/LayoutTests/http/tests/loading/sxg/resources/sxg-cert-not-found.sxg Binary files differ
diff --git a/third_party/WebKit/LayoutTests/http/tests/loading/sxg/resources/sxg-invalid-validity-url.sxg b/third_party/WebKit/LayoutTests/http/tests/loading/sxg/resources/sxg-invalid-validity-url.sxg index 992571b..ed2a3d7 100644 --- a/third_party/WebKit/LayoutTests/http/tests/loading/sxg/resources/sxg-invalid-validity-url.sxg +++ b/third_party/WebKit/LayoutTests/http/tests/loading/sxg/resources/sxg-invalid-validity-url.sxg Binary files differ
diff --git a/third_party/WebKit/LayoutTests/http/tests/loading/sxg/resources/sxg-location.sxg b/third_party/WebKit/LayoutTests/http/tests/loading/sxg/resources/sxg-location.sxg index 79f90912..e65a0db2 100644 --- a/third_party/WebKit/LayoutTests/http/tests/loading/sxg/resources/sxg-location.sxg +++ b/third_party/WebKit/LayoutTests/http/tests/loading/sxg/resources/sxg-location.sxg Binary files differ
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/timeline/tracing-process-filter-expected.txt b/third_party/WebKit/LayoutTests/inspector-protocol/timeline/tracing-process-filter-expected.txt index 6f0712c..76ab560 100644 --- a/third_party/WebKit/LayoutTests/inspector-protocol/timeline/tracing-process-filter-expected.txt +++ b/third_party/WebKit/LayoutTests/inspector-protocol/timeline/tracing-process-filter-expected.txt
@@ -2,5 +2,5 @@ Recording started Another page Tracing complete -There should be just 2 processes (browser and renderer): 2 +There should be just 3 processes (browser, GPU, and renderer): 3
diff --git a/third_party/WebKit/LayoutTests/inspector-protocol/timeline/tracing-process-filter.js b/third_party/WebKit/LayoutTests/inspector-protocol/timeline/tracing-process-filter.js index f81444e..c43f871 100644 --- a/third_party/WebKit/LayoutTests/inspector-protocol/timeline/tracing-process-filter.js +++ b/third_party/WebKit/LayoutTests/inspector-protocol/timeline/tracing-process-filter.js
@@ -16,7 +16,7 @@ const pids = new Set(); for (const event of events) pids.add(event.pid); - testRunner.log(`There should be just 2 processes (browser and renderer): ${pids.size}`); + testRunner.log(`There should be just 3 processes (browser, GPU, and renderer): ${pids.size}`); testRunner.completeTest(); })
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/stable/webexposed/global-interface-listing-platform-specific-expected.txt b/third_party/WebKit/LayoutTests/platform/linux/virtual/stable/webexposed/global-interface-listing-platform-specific-expected.txt similarity index 100% copy from third_party/WebKit/LayoutTests/platform/win/virtual/stable/webexposed/global-interface-listing-platform-specific-expected.txt copy to third_party/WebKit/LayoutTests/platform/linux/virtual/stable/webexposed/global-interface-listing-platform-specific-expected.txt
diff --git a/third_party/WebKit/LayoutTests/platform/win7/virtual/stable/webexposed/OWNERS b/third_party/WebKit/LayoutTests/platform/win7/virtual/stable/webexposed/OWNERS new file mode 100644 index 0000000..d0b8610 --- /dev/null +++ b/third_party/WebKit/LayoutTests/platform/win7/virtual/stable/webexposed/OWNERS
@@ -0,0 +1,5 @@ +set noparent + +# Web-exposed API changes may require approval from blink API OWNERS. +# See http://www.chromium.org/blink#new-features for details. +file://third_party/blink/API_OWNERS
diff --git a/third_party/WebKit/LayoutTests/platform/win/virtual/stable/webexposed/global-interface-listing-platform-specific-expected.txt b/third_party/WebKit/LayoutTests/platform/win7/virtual/stable/webexposed/global-interface-listing-platform-specific-expected.txt similarity index 100% rename from third_party/WebKit/LayoutTests/platform/win/virtual/stable/webexposed/global-interface-listing-platform-specific-expected.txt rename to third_party/WebKit/LayoutTests/platform/win7/virtual/stable/webexposed/global-interface-listing-platform-specific-expected.txt
diff --git a/third_party/WebKit/LayoutTests/shadow-dom/imperative-api-slotchange.html b/third_party/WebKit/LayoutTests/shadow-dom/imperative-api-slotchange.html new file mode 100644 index 0000000..ebbe18f --- /dev/null +++ b/third_party/WebKit/LayoutTests/shadow-dom/imperative-api-slotchange.html
@@ -0,0 +1,95 @@ +<!DOCTYPE html> +<script src="../resources/testharness.js"></script> +<script src="../resources/testharnessreport.js"></script> +<script src="resources/shadow-dom.js"></script> + +<div id="test1"> + <div id="host1"> + <template id="shadowroot" data-mode="open" data-slotting="manual"> + <slot id="s1" name="slot1"></slot> + <slot id="s2" name="slot2"></slot> + </template> + <div id="c1"></div> + <div id="c2"></div> + </div> +</div> + +<script> +function doneIfSlotChange(slots, test) { + let fired = new Set(); + for (let slot of slots) { + slot.addEventListener('slotchange', test.step_func((e) => { + assert_false(fired.has(slot.id)); + fired.add(slot.id); + if (fired.size == slots.length) { + test.done(); + } + })) + } +} + +async_test((test) => { + let n = createTestTree(test1); + assert_array_equals(n.s2.assignedNodes(), []); + n.s2.assign([n.c2]); + assert_array_equals(n.s2.assignedNodes(), [n.c2]); + + setTimeout(function () { + doneIfSlotChange([n.s1,n.s2], test); + + assert_array_equals(n.s2.assignedNodes(), [n.c2]); + n.s1.assign([n.c2]); + assert_array_equals(n.s2.assignedNodes(), []); + },1); +}, 'slotchange event: assign a child to a host.'); + +async_test((test) => { + let n = createTestTree(test1); + assert_array_equals(n.s1.assignedNodes(), []); + let d1 = document.createElement('div'); + n.s1.assign([d1]); + assert_array_equals(n.s1.assignedNodes(), []); + + setTimeout(function () { + doneIfSlotChange([n.s1], test); + n.host1.appendChild(d1); + },1); +}, 'slotchange event: Append a child to a host.'); + +async_test((test) => { + let n = createTestTree(test1); + assert_array_equals(n.s1.assignedNodes(), []); + n.s1.assign([n.c1]); + assert_array_equals(n.s1.assignedNodes(), [n.c1]); + + setTimeout(function () { + doneIfSlotChange([n.s1], test); + n.c1.remove(); + },1); +}, 'slotchange event: Remove a child to a host.'); + +async_test((test) => { + let n = createTestTree(test1); + n.s1.assign([n.c1]); + n.s2.assign([n.c1]); + + setTimeout(function () { + doneIfSlotChange([n.s2], test); + n.s1.remove(); + },1); +}, 'slotchange event: Remove a slot from a shadow tree.'); + +async_test((test) => { + let n = createTestTree(test1); + n.s1.assign([n.c1]); + let slot = document.createElement('slot'); + slot.assign([n.c1]) + assert_array_equals(slot.assignedNodes(), []); + + setTimeout(function () { + doneIfSlotChange([slot,n.s1], test); + n.shadowroot.insertBefore(slot, n.s1); + assert_array_equals(n.s1.assignedNodes(), []); + },1); +}, 'slotchange event: Insert a slot before another slot.'); +</script>
diff --git a/third_party/WebKit/LayoutTests/shadow-dom/resources/shadow-dom.js b/third_party/WebKit/LayoutTests/shadow-dom/resources/shadow-dom.js index 51bb0240..c9f2545 100644 --- a/third_party/WebKit/LayoutTests/shadow-dom/resources/shadow-dom.js +++ b/third_party/WebKit/LayoutTests/shadow-dom/resources/shadow-dom.js
@@ -76,6 +76,10 @@ if (template.getAttribute('data-mode') === 'v0') { // For legacy Shadow DOM shadowRoot = parent.createShadowRoot(); + } else if (template.getAttribute('data-slotting') === 'manual') { + shadowRoot = + parent.attachShadow({mode: template.getAttribute('data-mode'), + slotting: 'manual'}); } else { shadowRoot = parent.attachShadow({mode: template.getAttribute('data-mode')});
diff --git a/third_party/WebKit/LayoutTests/virtual/service-worker-servicification/http/tests/serviceworker/register-error-messages-expected.txt b/third_party/WebKit/LayoutTests/virtual/service-worker-servicification/http/tests/serviceworker/register-error-messages-expected.txt deleted file mode 100644 index 7ff8e78..0000000 --- a/third_party/WebKit/LayoutTests/virtual/service-worker-servicification/http/tests/serviceworker/register-error-messages-expected.txt +++ /dev/null
@@ -1,18 +0,0 @@ -This is a testharness.js-based test. -PASS Registering same scope as the script directory without the last slash -PASS Registration scope outside the script directory -PASS Registration scope outside domain -PASS Registering script outside domain -PASS Registering non-existent script -PASS Registering invalid chunked encoding script -FAIL Registering script with no MIME type assert_equals: expected "Failed to register a ServiceWorker: The script does not have a MIME type." but got "Failed to register a ServiceWorker: The script has an unsupported MIME type ('text/plain')." -PASS Registering script with bad MIME type -PASS Registering redirected script -PASS Registering script including parse error -PASS Registering script including undefined error -PASS Registering script including uncaught exception -PASS Registering script importing malformed script -PASS Registering script importing non-existent script -PASS Script URL including URL-encoded slash -Harness: the test ran to completion. -
diff --git a/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-dedicated-worker-expected.txt b/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-dedicated-worker-expected.txt index 6082c67..d47395dc 100644 --- a/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-dedicated-worker-expected.txt +++ b/third_party/WebKit/LayoutTests/virtual/stable/webexposed/global-interface-listing-dedicated-worker-expected.txt
@@ -2565,6 +2565,7 @@ [Worker] [GLOBAL OBJECT] [Worker] attribute console [Worker] attribute internals +[Worker] getter name [Worker] getter onmessage [Worker] getter onmessageerror [Worker] method close @@ -2574,6 +2575,7 @@ [Worker] method webkitRequestFileSystemSync [Worker] method webkitResolveLocalFileSystemSyncURL [Worker] method webkitResolveLocalFileSystemURL +[Worker] setter name [Worker] setter onmessage [Worker] setter onmessageerror PASS successfullyParsed is true
diff --git a/third_party/WebKit/LayoutTests/vr/resources/vr-test-utils.js b/third_party/WebKit/LayoutTests/vr/resources/vr-test-utils.js index 4ade3cc..42224d7 100644 --- a/third_party/WebKit/LayoutTests/vr/resources/vr-test-utils.js +++ b/third_party/WebKit/LayoutTests/vr/resources/vr-test-utils.js
@@ -1,13 +1,17 @@ 'use strict'; MockVRService.prototype.setListeningForActivate = function(client) { - for (let i = 0; i < this.devices_.length; i++) { - this.devices_[i].displayClient_ = client; + for (let i = 0; i < this.runtimes_.length; i++) { + this.runtimes_[i].displayClient_ = client; } }; +MockVRService.prototype.getImmersiveVRDisplayInfo = function() { + return Promise.resolve( + {info: this.runtimes_[0] ? this.runtimes_[0].displayInfo_ : null}); +}; -MockDevice.prototype.setPose = function(pose) { +MockRuntime.prototype.setPose = function(pose) { if (pose == null) { this.pose_ = null; } else { @@ -30,14 +34,10 @@ } }; -MockDevice.prototype.forceActivate = function(reason) { +MockRuntime.prototype.forceActivate = function(reason) { this.displayClient_.onActivate(reason); }; -MockDevice.prototype.getImmersiveVRDisplayInfo = function() { - return Promise.resolve({info: this.displayInfo_}); -}; - function vr_test(func, vrDisplays, name, properties) { let chain = Promise.resolve(); let firstDeviceController;
diff --git a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-dedicated-worker-expected.txt b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-dedicated-worker-expected.txt index cfe8fe63..d7e20b2 100644 --- a/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-dedicated-worker-expected.txt +++ b/third_party/WebKit/LayoutTests/webexposed/global-interface-listing-dedicated-worker-expected.txt
@@ -3552,6 +3552,7 @@ [Worker] [GLOBAL OBJECT] [Worker] attribute console [Worker] attribute internals +[Worker] getter name [Worker] getter onmessage [Worker] getter onmessageerror [Worker] method close @@ -3561,6 +3562,7 @@ [Worker] method webkitRequestFileSystemSync [Worker] method webkitResolveLocalFileSystemSyncURL [Worker] method webkitResolveLocalFileSystemURL +[Worker] setter name [Worker] setter onmessage [Worker] setter onmessageerror PASS successfullyParsed is true
diff --git a/third_party/WebKit/LayoutTests/xr/events_session_end.html b/third_party/WebKit/LayoutTests/xr/events_session_end.html deleted file mode 100644 index a1092f4..0000000 --- a/third_party/WebKit/LayoutTests/xr/events_session_end.html +++ /dev/null
@@ -1,42 +0,0 @@ -<!DOCTYPE html> -<script src="../resources/testharness.js"></script> -<script src="../resources/testharnessreport.js"></script> -<script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script> -<script src="file:///gen/device/vr/public/mojom/vr_service.mojom.js"></script> -<script src="../external/wpt/resources/chromium/webxr-test.js"></script> -<script src="../xr/resources/xr-test-utils.js"></script> -<canvas id="webgl-canvas"></canvas> - -<script> - -let testName = "Test end fires when session ends"; - -let watcherDone = new Event("watcherdone"); - -let fakeDeviceInitParams = { supportsImmersive:true }; - -let requestSessionOptions = [ - { immersive: true }, - { outputContext: getOutputContext() } -]; - -let testFunction = function(session, t) { - let eventWatcher = new EventWatcher(t, session, ["end", "watcherdone"]); - let eventPromise = eventWatcher.wait_for(["end", "watcherdone"]); - - function onSessionEnd(event) { - t.step( () => { - assert_equals(event.session, session); - session.dispatchEvent(watcherDone); - }); - } - session.addEventListener("end", onSessionEnd, false); - session.end(); - - return eventPromise; -}; - -xr_session_promise_test( - testFunction, fakeDeviceInitParams, requestSessionOptions, testName); - -</script>
diff --git a/third_party/WebKit/LayoutTests/xr/exclusive_requestFrame_called.html b/third_party/WebKit/LayoutTests/xr/exclusive_requestFrame_called.html deleted file mode 100644 index cdebdb8..0000000 --- a/third_party/WebKit/LayoutTests/xr/exclusive_requestFrame_called.html +++ /dev/null
@@ -1,37 +0,0 @@ -<!DOCTYPE html> -<script src="../resources/testharness.js"></script> -<script src="../resources/testharnessreport.js"></script> -<script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script> -<script src="file:///gen/device/vr/public/mojom/vr_service.mojom.js"></script> -<script src="../external/wpt/resources/chromium/webxr-test.js"></script> -<script src="../xr/resources/xr-test-utils.js"></script> -<canvas id="webgl-canvas"></canvas> - -<script> -let testName = "XRSession requestAnimationFrame properly calls the provided " - + "callback"; - -let fakeDeviceInitParams = { supportsImmersive:true }; - -let requestSessionOptions = [ - { immersive: true }, - { outputContext: getOutputContext() } -]; - -let testFunction = (session) => new Promise((resolve) => { - // Session must have a baseLayer or frame requests will be ignored. - session.baseLayer = new XRWebGLLayer(session, gl); - - function onFrame(time, xrFrame) { - assert_true(xrFrame instanceof XRFrame); - // Test does not complete until the returned promise resolves. - resolve(); - } - - session.requestAnimationFrame(onFrame); -}); - -xr_session_promise_test( - testFunction, fakeDeviceInitParams, requestSessionOptions, testName); - -</script>
diff --git a/third_party/WebKit/LayoutTests/xr/exclusive_requestFrame_invalidhandle.html b/third_party/WebKit/LayoutTests/xr/exclusive_requestFrame_invalidhandle.html deleted file mode 100644 index 7e9b66eb..0000000 --- a/third_party/WebKit/LayoutTests/xr/exclusive_requestFrame_invalidhandle.html +++ /dev/null
@@ -1,52 +0,0 @@ -<!DOCTYPE html> -<script src="../resources/testharness.js"></script> -<script src="../resources/testharnessreport.js"></script> - -<script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script> -<script src="file:///gen/device/vr/public/mojom/vr_service.mojom.js"></script> -<script src="../external/wpt/resources/chromium/webxr-test.js"></script> -<script src="../xr/resources/xr-test-utils.js"></script> -<canvas id="webgl-canvas"></canvas> - -<script> -let testName = "XRSession cancelAnimationFrame does not have unexpected " - + "behavior when given invalid handles"; - -let fakeDeviceInitParams = { supportsImmersive:true }; - -let requestSessionOptions = [ - { immersive: true }, - { outputContext: getOutputContext() } -]; - -let testFunction = (session) => new Promise((resolve) => { - // Session must have a baseLayer or frame requests will be ignored. - session.baseLayer = new XRWebGLLayer(session, gl); - - let counter = 0; - - function onFrame(time, vrFrame) { - // Intentionally session.requestAnimationFrame at the beginning, ensuring that - // there's an outstanding callback when the test completes. This is to make - // sure it doesn't cause any unexpected behavior like it did with - // crbug.com/679401 - session.requestAnimationFrame(onFrame); - if (counter > 10) { - resolve(); - } - counter++; - } - - let handle = session.requestAnimationFrame(onFrame); - session.cancelAnimationFrame(0); - session.cancelAnimationFrame(-1); - session.cancelAnimationFrame(handle + 1); - session.cancelAnimationFrame(handle - 1); - session.cancelAnimationFrame(0.5); - session.cancelAnimationFrame(null); -}); - -xr_session_promise_test( - testFunction, fakeDeviceInitParams, requestSessionOptions, testName); - -</script>
diff --git a/third_party/WebKit/LayoutTests/xr/exclusive_requestFrame_unregister.html b/third_party/WebKit/LayoutTests/xr/exclusive_requestFrame_unregister.html deleted file mode 100644 index 5cdbfce..0000000 --- a/third_party/WebKit/LayoutTests/xr/exclusive_requestFrame_unregister.html +++ /dev/null
@@ -1,60 +0,0 @@ -<!DOCTYPE html> -<script src="../resources/testharness.js"></script> -<script src="../resources/testharnessreport.js"></script> -<script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script> -<script src="file:///gen/device/vr/public/mojom/vr_service.mojom.js"></script> -<script src="../external/wpt/resources/chromium/webxr-test.js"></script> -<script src="../xr/resources/xr-test-utils.js"></script> -<canvas id="webgl-canvas"></canvas> - -<script> -let testName = "XRSession requestAnimationFrame callbacks can be unregistered " - + "with cancelAnimationFrame"; - -let fakeDeviceInitParams = { supportsImmersive:true }; - -let requestSessionOptions = [ - { immersive: true }, - { outputContext: getOutputContext() } -]; - -let testFunction = (session) => new Promise((resolve, reject) => { - // Session must have a baseLayer or frame requests will be ignored. - session.baseLayer = new XRWebGLLayer(session, gl); - - function onFrameBad(time, vrFrame) { - reject("Unregistered callback was called"); - } - - let counter = 0; - let handle2 = 0; - function onFrameGood(time, vrFrame) { - counter++; - if (counter >= 4) { - resolve(); - // Intentionally don't return immediately so that session.requestAnimationFrame - // gets called again to make sure it doesn't cause unexpected behavior - // like in crbug.com/679401 - } - session.requestAnimationFrame(onFrameGood); - - if (handle2 != 0) { - // The first time we enter this callback the callback associated with - // handle2 will have already been queued to execute immediately after - // this callback returns. Ensure that cancelAnimationFrame works even in that - // scenario. - session.cancelAnimationFrame(handle2); - handle2 = 0; - } - } - - let handle = session.requestAnimationFrame(onFrameBad); - session.cancelAnimationFrame(handle); - session.requestAnimationFrame(onFrameGood); - handle2 = session.requestAnimationFrame(onFrameBad); -}); - -xr_session_promise_test( - testFunction, fakeDeviceInitParams, requestSessionOptions, testName); - -</script>
diff --git a/third_party/WebKit/LayoutTests/xr/getDevicePose_oneframeupdate.html b/third_party/WebKit/LayoutTests/xr/getDevicePose_oneframeupdate.html deleted file mode 100644 index 43885bd..0000000 --- a/third_party/WebKit/LayoutTests/xr/getDevicePose_oneframeupdate.html +++ /dev/null
@@ -1,76 +0,0 @@ -<!DOCTYPE html> -<script src="../resources/testharness.js"></script> -<script src="../resources/testharnessreport.js"></script> -<script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script> -<script src="file:///gen/device/vr/public/mojom/vr_service.mojom.js"></script> -<script src="../external/wpt/resources/chromium/webxr-test.js"></script> -<script src="../xr/resources/xr-test-utils.js"></script> -<script src="../xr/resources/test-constants.js"></script> -<canvas id="webgl-canvas"></canvas> - -<script> - -let testName = "XRFrame getDevicePose updates on the next frame"; - -let fakeDeviceInitParams = { supportsImmersive: true }; - -let requestSessionOptions = [ - { immersive: true }, - { outputContext: getOutputContext() } -]; - -let testFunction = function(session, t, fakeDeviceController) { - // Session must have a baseLayer or else frame requests will be ignored. - session.baseLayer = new XRWebGLLayer(session, gl); - - return session.requestFrameOfReference("eye-level") - .then((frameOfRef) => new Promise((resolve, reject) => { - let counter = 0; - function onFrame(time, vrFrame) { - session.requestAnimationFrame(onFrame); - if (counter == 0) { - t.step( () => { - // Expecting to not get a pose since none has been supplied - assert_equals(vrFrame.getDevicePose(frameOfRef), null); - - // Need to have a valid pose or input event's don't process. - fakeDeviceController.setXRPresentationFrameData( - VALID_POSE_MATRIX, [{ - eye:"left", - projectionMatrix: VALID_PROJECTION_MATRIX, - viewMatrix: VALID_VIEW_MATRIX - }, { - eye:"right", - projectionMatrix: VALID_PROJECTION_MATRIX, - viewMatrix: VALID_VIEW_MATRIX - }]); - - // Check that pose does not update pose within the same frame. - assert_equals(vrFrame.getDevicePose(frameOfRef), null); - }); - } else { - t.step( () => { - // Check that pose was updated. - let pose = vrFrame.getDevicePose(frameOfRef); - assert_not_equals(pose, null); - - let poseMatrix = pose.poseModelMatrix; - assert_not_equals(poseMatrix, null); - - assert_matrices_approx_equal(poseMatrix, VALID_POSE_MATRIX); - }); - - // Finished. - resolve(); - } - counter++; - } - - session.requestAnimationFrame(onFrame); - })); -}; - -xr_session_promise_test( - testFunction, fakeDeviceInitParams, requestSessionOptions, testName); - -</script>
diff --git a/third_party/WebKit/LayoutTests/xr/requestDevice_with_device.html b/third_party/WebKit/LayoutTests/xr/requestDevice_with_device.html deleted file mode 100644 index 6cf7d5f7..0000000 --- a/third_party/WebKit/LayoutTests/xr/requestDevice_with_device.html +++ /dev/null
@@ -1,22 +0,0 @@ -<!DOCTYPE html> -<script src="../resources/testharness.js"></script> -<script src="../resources/testharnessreport.js"></script> -<script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script> -<script src="file:///gen/device/vr/public/mojom/vr_service.mojom.js"></script> -<script src="../external/wpt/resources/chromium/webxr-test.js"></script> -<script src="../xr/resources/xr-test-utils.js"></script> -<script src="../xr/resources/test-constants.js"></script> -<script> - -promise_test((t) => { - return XRTest.simulateDeviceConnection({ supportsImmersive: true }) - .then( (controller) => { return navigator.xr.requestDevice() }) - .then( (device) => { - t.step(() => { - assert_true(device != null); - assert_true(device instanceof XRDevice); - }); - }); -}, "navigator.xr.requestDevice properly returns a single device"); - -</script>
diff --git a/third_party/WebKit/LayoutTests/xr/requestDevice_without_device.html b/third_party/WebKit/LayoutTests/xr/requestDevice_without_device.html deleted file mode 100644 index b273a87..0000000 --- a/third_party/WebKit/LayoutTests/xr/requestDevice_without_device.html +++ /dev/null
@@ -1,15 +0,0 @@ -<!DOCTYPE html> -<script src="../resources/testharness.js"></script> -<script src="../resources/testharnessreport.js"></script> -<script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script> -<script src="file:///gen/device/vr/public/mojom/vr_service.mojom.js"></script> -<script src="../external/wpt/resources/chromium/webxr-test.js"></script> -<script src="../xr/resources/xr-test-utils.js"></script> -<script src="../xr/resources/test-constants.js"></script> -<script> - -promise_test( (t) => { - return promise_rejects(t, 'NotFoundError', navigator.xr.requestDevice()); -}, "navigator.xr.requestDevice properly rejects when there are 0 devices"); - -</script>
diff --git a/third_party/WebKit/LayoutTests/xr/resources/xr-internal-device-mocking.js b/third_party/WebKit/LayoutTests/xr/resources/xr-internal-device-mocking.js index bd429a1..19bf18c 100644 --- a/third_party/WebKit/LayoutTests/xr/resources/xr-internal-device-mocking.js +++ b/third_party/WebKit/LayoutTests/xr/resources/xr-internal-device-mocking.js
@@ -4,9 +4,9 @@ * for interal tests. The main mocked objects are found in * ../external/wpt/resources/chromium/webxr-test.js. */ -MockDevice.prototype.base_getFrameData = MockDevice.prototype.getFrameData; +MockRuntime.prototype.base_getFrameData = MockRuntime.prototype.getFrameData; -MockDevice.prototype.getFrameData = function() { +MockRuntime.prototype.getFrameData = function() { return this.base_getFrameData().then((result) => { if (result.frameData && result.frameData.pose && this.input_sources_) { let input_states = []; @@ -21,7 +21,7 @@ }); }; -MockDevice.prototype.addInputSource = function(source) { +MockRuntime.prototype.addInputSource = function(source) { if (!this.input_sources_) { this.input_sources_ = []; this.next_input_source_index_ = 1; @@ -32,7 +32,7 @@ this.input_sources_.push(source); }; -MockDevice.prototype.removeInputSource = function(source) { +MockRuntime.prototype.removeInputSource = function(source) { if (!this.input_sources_) return; @@ -44,11 +44,11 @@ } }; -MockDevice.prototype.setHitTestResults = function(results) { +MockRuntime.prototype.setHitTestResults = function(results) { this.hittest_results_ = results; }; -MockDevice.prototype.requestHitTest = function(ray) { +MockRuntime.prototype.requestHitTest = function(ray) { var hit_results = this.hittest_results_; if (!hit_results) { var hit = new device.mojom.XRHitResult(); @@ -58,13 +58,13 @@ return Promise.resolve(hit_results); }; -MockDevice.prototype.setResetPose = function(to) { +MockRuntime.prototype.setResetPose = function(to) { if (this.pose_) { this.pose_.poseReset = to; } }; -MockDevice.prototype.setStageTransform = function(value) { +MockRuntime.prototype.setStageTransform = function(value) { if (value) { if (!this.displayInfo_.stageParameters) { this.displayInfo_.stageParameters = { @@ -82,11 +82,11 @@ this.sessionClient_.onChanged(this.displayInfo_); }; -MockDevice.prototype.getSubmitFrameCount = function() { +MockRuntime.prototype.getSubmitFrameCount = function() { return this.presentation_provider_.submit_frame_count_; }; -MockDevice.prototype.getMissingFrameCount = function() { +MockRuntime.prototype.getMissingFrameCount = function() { return this.presentation_provider_.missing_frame_count_; };
diff --git a/third_party/WebKit/LayoutTests/xr/resources/xr-test-utils.js b/third_party/WebKit/LayoutTests/xr/resources/xr-test-utils.js index 94e338d..23f29f15 100644 --- a/third_party/WebKit/LayoutTests/xr/resources/xr-test-utils.js +++ b/third_party/WebKit/LayoutTests/xr/resources/xr-test-utils.js
@@ -48,11 +48,11 @@ return func(session, t, fakeDeviceController); }) .then(() => { - // End the session. Silence any errors - // generated if the session was already ended. - // TODO(offenwanger): This throw error when a - // session is already ended is not defined by - // the spec. + // End the session. Silence any errors generated if the + // session was already ended. + // TODO(bajones): Throwing an error when a session is + // already ended is not defined by the spec. This + // should be defined or removed. testSession.end().catch(() => {}); fakeDeviceController.setXRPresentationFrameData(null); }) @@ -210,9 +210,6 @@ } } -// TODO(offenwanger): eventSender cannot be used with WPTs. Find another way to -// fake use gestures. -// https://chromium.googlesource.com/chromium/src/+/lkgr/docs/testing/web_platform_tests.md#tests-that-require-testing-apis function runWithUserGesture(fn) { function thunk() { document.removeEventListener('keypress', thunk, false);
diff --git a/third_party/WebKit/LayoutTests/xr/webGLCanvasContext_create_with_xr_device.html b/third_party/WebKit/LayoutTests/xr/webGLCanvasContext_create_with_xr_device.html deleted file mode 100644 index 9edcc75..0000000 --- a/third_party/WebKit/LayoutTests/xr/webGLCanvasContext_create_with_xr_device.html +++ /dev/null
@@ -1,29 +0,0 @@ -<!DOCTYPE html> -<script src="../resources/testharness.js"></script> -<script src="../resources/testharnessreport.js"></script> -<script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script> -<script src="file:///gen/device/vr/public/mojom/vr_service.mojom.js"></script> -<script src="../external/wpt/resources/chromium/webxr-test.js"></script> -<script src="../xr/resources/xr-test-utils.js"></script> -<script src="../xr/resources/test-constants.js"></script> -<canvas id="webgl-canvas"></canvas> - -<script> - - -promise_test( (t) => { - return XRTest.simulateDeviceConnection({ supportsImmersive:true }) - .then( (controller) => { return navigator.xr.requestDevice() }) - .then( (device) => { - webglCanvas = document.getElementById('webgl-canvas'); - gl = webglCanvas.getContext('webgl', {compatibleXRDevice: device}); - assert_equals(gl.getContextAttributes().compatibleXRDevice, device); - - // Check that an offscreen context behaves no different. - let offscreenCanvas = document.createElement('canvas'); - let offscreenGl = webglCanvas.getContext('webgl', {compatibleXRDevice: device}); - assert_equals(offscreenGl.getContextAttributes().compatibleXRDevice, device); - }); -}, "A webglCanvasContext created with an XRDevice has that device set"); - -</script>
diff --git a/third_party/WebKit/LayoutTests/xr/webGLCanvasContext_set_device_lost_context.html b/third_party/WebKit/LayoutTests/xr/webGLCanvasContext_set_device_lost_context.html deleted file mode 100644 index 47c7c99..0000000 --- a/third_party/WebKit/LayoutTests/xr/webGLCanvasContext_set_device_lost_context.html +++ /dev/null
@@ -1,25 +0,0 @@ -<!DOCTYPE html> -<script src="../resources/testharness.js"></script> -<script src="../resources/testharnessreport.js"></script> -<script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script> -<script src="file:///gen/device/vr/public/mojom/vr_service.mojom.js"></script> -<script src="../external/wpt/resources/chromium/webxr-test.js"></script> -<script src="../xr/resources/xr-test-utils.js"></script> -<script src="../xr/resources/test-constants.js"></script> -<canvas id="webgl-canvas"></canvas> - -<script> - -promise_test( (t) => { - return XRTest.simulateDeviceConnection({ supportsImmersive:true }) - .then( (controller) => { return navigator.xr.requestDevice() }) - .then( (device) => { - webglCanvas = document.getElementById('webgl-canvas'); - gl = webglCanvas.getContext('webgl', {compatibleXRDevice: device}); - gl.getExtension('WEBGL_lose_context').loseContext(); - return promise_rejects(t, 'InvalidStateError', - gl.setCompatibleXRDevice(device)); - }); -}, "A lost webglCanvasContext should not be able to set device"); - -</script>
diff --git a/third_party/WebKit/LayoutTests/xr/xrDevice_requestSession_exclusive_no_gesture.html b/third_party/WebKit/LayoutTests/xr/xrDevice_requestSession_exclusive_no_gesture.html deleted file mode 100644 index 2f1d5ad5..0000000 --- a/third_party/WebKit/LayoutTests/xr/xrDevice_requestSession_exclusive_no_gesture.html +++ /dev/null
@@ -1,19 +0,0 @@ -<!DOCTYPE html> -<script src="../resources/testharness.js"></script> -<script src="../resources/testharnessreport.js"></script> -<script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script> -<script src="file:///gen/device/vr/public/mojom/vr_service.mojom.js"></script> -<script src="../external/wpt/resources/chromium/webxr-test.js"></script> -<script src="../xr/resources/xr-test-utils.js"></script> -<script src="../xr/resources/test-constants.js"></script> -<canvas id="webgl-canvas"></canvas> - -<script> - -promise_test( (t) => { - return XRTest.simulateDeviceConnection({ supportsImmersive:true }) - .then( (controller) => { return navigator.xr.requestDevice() }) - .then( (device) => promise_rejects( - t, 'SecurityError', device.requestSession({ immersive: true }))); -}, "request immersive session outside of a user gesture rejects"); -</script>
diff --git a/third_party/WebKit/LayoutTests/xr/xrDevice_requestSession_exclusive_supported.html b/third_party/WebKit/LayoutTests/xr/xrDevice_requestSession_exclusive_supported.html deleted file mode 100644 index e3a3a99..0000000 --- a/third_party/WebKit/LayoutTests/xr/xrDevice_requestSession_exclusive_supported.html +++ /dev/null
@@ -1,18 +0,0 @@ -<!DOCTYPE html> -<script src="../resources/testharness.js"></script> -<script src="../resources/testharnessreport.js"></script> -<script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script> -<script src="file:///gen/device/vr/public/mojom/vr_service.mojom.js"></script> -<script src="../external/wpt/resources/chromium/webxr-test.js"></script> -<script src="../xr/resources/xr-test-utils.js"></script> -<script src="../xr/resources/test-constants.js"></script> -<canvas id="webgl-canvas"></canvas> - -<script> - - -xr_session_promise_test( (session) => { - assert_not_equals(session, null); -}, { supportsImmersive:true }, [{ immersive: true }], -"requestSession for an immersive session with a user gesture resolves"); -</script>
diff --git a/third_party/WebKit/LayoutTests/xr/xrDevice_requestSession_exclusive_unsupported.html b/third_party/WebKit/LayoutTests/xr/xrDevice_requestSession_exclusive_unsupported.html deleted file mode 100644 index f41ce4c..0000000 --- a/third_party/WebKit/LayoutTests/xr/xrDevice_requestSession_exclusive_unsupported.html +++ /dev/null
@@ -1,26 +0,0 @@ -<!DOCTYPE html> -<script src="../resources/testharness.js"></script> -<script src="../resources/testharnessreport.js"></script> -<script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script> -<script src="file:///gen/device/vr/public/mojom/vr_service.mojom.js"></script> -<script src="../external/wpt/resources/chromium/webxr-test.js"></script> -<script src="../xr/resources/xr-test-utils.js"></script> -<script src="../xr/resources/test-constants.js"></script> -<canvas id="webgl-canvas"></canvas> - -<script> -promise_test( (t) => { - return XRTest.simulateDeviceConnection({ supportsImmersive:false }) - .then( (controller) => { return navigator.xr.requestDevice() }) - .then( (magicWindowOnlyDevice) => new Promise((resolve) => { - runWithUserGesture( () => { - resolve(promise_rejects( - t, - "NotSupportedError", - magicWindowOnlyDevice.requestSession({ immersive: true }) - )) - }); - })); -}, "requesting an immersive session on an unsupported device rejects"); - -</script>
diff --git a/third_party/WebKit/LayoutTests/xr/xrDevice_supportsSession_exclusive_rejects.html b/third_party/WebKit/LayoutTests/xr/xrDevice_supportsSession_exclusive_rejects.html deleted file mode 100644 index d3f016d..0000000 --- a/third_party/WebKit/LayoutTests/xr/xrDevice_supportsSession_exclusive_rejects.html +++ /dev/null
@@ -1,24 +0,0 @@ -<!DOCTYPE html> -<script src="../resources/testharness.js"></script> -<script src="../resources/testharnessreport.js"></script> -<script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script> -<script src="file:///gen/device/vr/public/mojom/vr_service.mojom.js"></script> -<script src="../external/wpt/resources/chromium/webxr-test.js"></script> -<script src="../xr/resources/xr-test-utils.js"></script> -<script src="../xr/resources/test-constants.js"></script> -<script> - - -promise_test( (t) => { - return XRTest.simulateDeviceConnection({ supportsImmersive:false }) - .then( (controller) => { return navigator.xr.requestDevice() }) - .then( (magicWindowOnlyDevice) => { - return promise_rejects( - t, - "NotSupportedError", - magicWindowOnlyDevice.supportsSession({ immersive: true }) - ); - }); -}, "supportsSession rejects when immersive session is not supported on device"); - -</script>
diff --git a/third_party/WebKit/LayoutTests/xr/xrDevice_supportsSession_exclusive_resolves.html b/third_party/WebKit/LayoutTests/xr/xrDevice_supportsSession_exclusive_resolves.html deleted file mode 100644 index 8b398ba..0000000 --- a/third_party/WebKit/LayoutTests/xr/xrDevice_supportsSession_exclusive_resolves.html +++ /dev/null
@@ -1,17 +0,0 @@ -<!DOCTYPE html> -<script src="../resources/testharness.js"></script> -<script src="../resources/testharnessreport.js"></script> -<script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script> -<script src="file:///gen/device/vr/public/mojom/vr_service.mojom.js"></script> -<script src="../external/wpt/resources/chromium/webxr-test.js"></script> -<script src="../xr/resources/xr-test-utils.js"></script> -<script src="../xr/resources/test-constants.js"></script> -<script> - -promise_test( () => { - return XRTest.simulateDeviceConnection({ supportsImmersive:true }) - .then( (controller) => { return navigator.xr.requestDevice() }) - .then( (device) => device.supportsSession({ immersive: true })); -}, "supportsSession resolves when support immersive session is supported on device"); - -</script>
diff --git a/third_party/WebKit/LayoutTests/xr/xrDevice_supportsSession_non_exclusive.html b/third_party/WebKit/LayoutTests/xr/xrDevice_supportsSession_non_exclusive.html deleted file mode 100644 index 7082623e..0000000 --- a/third_party/WebKit/LayoutTests/xr/xrDevice_supportsSession_non_exclusive.html +++ /dev/null
@@ -1,25 +0,0 @@ -<!DOCTYPE html> -<script src="../resources/testharness.js"></script> -<script src="../resources/testharnessreport.js"></script> -<script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script> -<script src="file:///gen/device/vr/public/mojom/vr_service.mojom.js"></script> -<script src="../external/wpt/resources/chromium/webxr-test.js"></script> -<script src="../xr/resources/xr-test-utils.js"></script> -<script src="../xr/resources/test-constants.js"></script> -<script> - -promise_test( (t) => { - return XRTest.simulateDeviceConnection({ supportsImmersive:true }) - .then( (controller) => { return navigator.xr.requestDevice() }) - .then( (device) => { - // Non-immersive sessions without a outputContext should not be supported. - promise_rejects(t, 'NotSupportedError', device.supportsSession()); - - // Non-immersive sessions with an outputContext should be supported. - return device.supportsSession({ - outputContext: getOutputContext() - }); - }); -}, "supportsSession properly identifies supported non-immersive sessions"); - -</script>
diff --git a/third_party/WebKit/LayoutTests/xr/xrSession_exclusive.html b/third_party/WebKit/LayoutTests/xr/xrSession_exclusive.html deleted file mode 100644 index 2ac44504..0000000 --- a/third_party/WebKit/LayoutTests/xr/xrSession_exclusive.html +++ /dev/null
@@ -1,29 +0,0 @@ -<!DOCTYPE html> -<script src="../resources/testharness.js"></script> -<script src="../resources/testharnessreport.js"></script> -<script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script> -<script src="file:///gen/device/vr/public/mojom/vr_service.mojom.js"></script> -<script src="../external/wpt/resources/chromium/webxr-test.js"></script> -<script src="../xr/resources/xr-test-utils.js"></script> -<script src="../xr/resources/test-constants.js"></script> -<canvas id="webgl-canvas"></canvas> - -<script> - - -promise_test( (t) => { - return XRTest.simulateDeviceConnection({ supportsImmersive:true }) - .then( (controller) => { return navigator.xr.requestDevice() }) - .then( (device) => new Promise((resolve) => { - runWithUserGesture( () => { - resolve(device.requestSession({ immersive: true }).then( (session) => { - assert_true(session.immersive); - assert_equals(session.device, device); - assert_approx_equals(session.depthNear, 0.1, FLOAT_EPSILON); - assert_approx_equals(session.depthFar, 1000.0, FLOAT_EPSILON); - })); - }); - })); -}, "supportsSession returns expected immersive session"); - -</script>
diff --git a/third_party/WebKit/LayoutTests/xr/xrSession_prevent_multiple_exclusive.html b/third_party/WebKit/LayoutTests/xr/xrSession_prevent_multiple_exclusive.html deleted file mode 100644 index a9295eb1..0000000 --- a/third_party/WebKit/LayoutTests/xr/xrSession_prevent_multiple_exclusive.html +++ /dev/null
@@ -1,45 +0,0 @@ -<!DOCTYPE html> -<script src="../resources/testharness.js"></script> -<script src="../resources/testharnessreport.js"></script> -<script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script> -<script src="file:///gen/device/vr/public/mojom/vr_service.mojom.js"></script> -<script src="../external/wpt/resources/chromium/webxr-test.js"></script> -<script src="../xr/resources/xr-test-utils.js"></script> -<script src="../xr/resources/test-constants.js"></script> -<canvas id="webgl-canvas"></canvas> - -<script> - - -promise_test( (t) => { - return XRTest.simulateDeviceConnection({ supportsImmersive:true }) - .then( (controller) => { return navigator.xr.requestDevice() }) - .then( (device) => new Promise((resolve) => { - runWithUserGesture( () => { - resolve(device.requestSession({ immersive: true }) - .then( (session) => new Promise((resolve) => { - runWithUserGesture( () => { - // Requesting a second immersive session from a device that already - // has an active immersive session should fail. Immersive sessions - // should take up the users entire view, and therefore it should - // be impossible for a user to be engaged with more than one. - resolve(promise_rejects( - t, - "InvalidStateError", - device.requestSession({ immersive: true }) - ).then( () => { - // End the immersive session and try again. Now the immersive - // session creation should succeed. - return session.end().then( () => new Promise((resolve) => { - runWithUserGesture( () => { - resolve(device.requestSession({ immersive: true })); - }); - })); - })); - }); - }))); - }); - })); -}, "requestSession prevents creation of multiple simultaneous immersive sessions"); - -</script>
diff --git a/third_party/WebKit/LayoutTests/xr/xrSession_requestFrameOfReference.html b/third_party/WebKit/LayoutTests/xr/xrSession_requestFrameOfReference.html deleted file mode 100644 index dcc5996..0000000 --- a/third_party/WebKit/LayoutTests/xr/xrSession_requestFrameOfReference.html +++ /dev/null
@@ -1,48 +0,0 @@ -<!DOCTYPE html> -<script src="../resources/testharness.js"></script> -<script src="../resources/testharnessreport.js"></script> -<script src="file:///gen/layout_test_data/mojo/public/js/mojo_bindings.js"></script> -<script src="file:///gen/device/vr/public/mojom/vr_service.mojom.js"></script> -<script src="../external/wpt/resources/chromium/webxr-test.js"></script> -<script src="../xr/resources/xr-test-utils.js"></script> -<script src="../xr/resources/test-constants.js"></script> -<canvas id="webgl-canvas"></canvas> - -<script> -let testName = "requestFrameOfReference returns the expected objects"; - -let fakeDeviceInitParams = { supportsImmersive:true }; - -let requestSessionOptions = [ - { outputContext: getOutputContext() }, - { immersive: true }, -]; - -let testFunction = function(session, t) { - return promise_rejects(t, new TypeError(), session.requestFrameOfReference("foo")) - .then(() => Promise.all([ - session.requestFrameOfReference("head-model").then( (frameOfRef) => { - assert_true(frameOfRef instanceof XRCoordinateSystem, - "head-model frameOfRef is not correct type."); - assert_true(frameOfRef instanceof XRFrameOfReference, - "head-model frameOfRef is not correct type."); - }), - session.requestFrameOfReference("eye-level").then( (frameOfRef) => { - assert_true(frameOfRef instanceof XRCoordinateSystem, - "eye-level frameOfRef is not correct type."); - assert_true(frameOfRef instanceof XRFrameOfReference, - "eye-level frameOfRef is not correct type."); - }), - session.requestFrameOfReference("stage").then( (frameOfRef) => { - assert_true(frameOfRef instanceof XRCoordinateSystem, - "stage frameOfRef is not correct type."); - assert_true(frameOfRef instanceof XRFrameOfReference, - "stage frameOfRef is not correct type."); - }) - ])); -}; - -xr_session_promise_test( - testFunction, fakeDeviceInitParams, requestSessionOptions, testName); - -</script>
diff --git a/third_party/blink/public/platform/platform.h b/third_party/blink/public/platform/platform.h index 6235b12..9853089 100644 --- a/third_party/blink/public/platform/platform.h +++ b/third_party/blink/public/platform/platform.h
@@ -368,6 +368,7 @@ virtual void FetchCachedCode( const WebURL&, base::OnceCallback<void(base::Time, const std::vector<uint8_t>&)>) {} + virtual void ClearCodeCacheEntry(const GURL&) {} // A suggestion to cache this metadata in association with this URL which // resource is in CacheStorage.
diff --git a/third_party/blink/public/platform/web_media_player.h b/third_party/blink/public/platform/web_media_player.h index b4cf7ff6..ce91f5e 100644 --- a/third_party/blink/public/platform/web_media_player.h +++ b/third_party/blink/public/platform/web_media_player.h
@@ -219,14 +219,14 @@ virtual uint64_t AudioDecodedByteCount() const = 0; virtual uint64_t VideoDecodedByteCount() const = 0; - // |out_metadata|, if set, is used to return metadata about the frame - // that is uploaded during this call. // |already_uploaded_id| indicates the unique_id of the frame last uploaded // to this destination. It should only be set by the caller if the contents // of the destination are known not to have changed since that upload. // - If |out_metadata| is not null, |already_uploaded_id| is compared with // the unique_id of the frame being uploaded. If it's the same, the // upload may be skipped and considered to be successful. + // |out_metadata|, if not null, is used to return metadata about the frame + // that is uploaded during this call. virtual void Paint(cc::PaintCanvas*, const WebRect&, cc::PaintFlags&, @@ -235,17 +235,18 @@ // Do a GPU-GPU texture copy of the current video frame to |texture|, // reallocating |texture| at the appropriate size with given internal - // format, format, and type if necessary. If the copy is impossible - // or fails, it returns false. + // format, format, and type if necessary. // - // |out_metadata|, if set, is used to return metadata about the frame - // that is uploaded during this call. + // Returns true iff the copy succeeded. + // // |already_uploaded_id| indicates the unique_id of the frame last uploaded // to this destination. It should only be set by the caller if the contents // of the destination are known not to have changed since that upload. // - If |out_metadata| is not null, |already_uploaded_id| is compared with // the unique_id of the frame being uploaded. If it's the same, the // upload may be skipped and considered to be successful. + // |out_metadata|, if not null, is used to return metadata about the frame + // that is uploaded during this call. virtual bool CopyVideoTextureToPlatformTexture( gpu::gles2::GLES2Interface*, unsigned target, @@ -256,13 +257,43 @@ int level, bool premultiply_alpha, bool flip_y, - int already_uploaded_id = -1, - VideoFrameUploadMetadata* out_metadata = nullptr) { + int already_uploaded_id, + VideoFrameUploadMetadata* out_metadata) { return false; } - // Copy sub video frame texture to |texture|. If the copy is impossible or - // fails, it returns false. + // Do a CPU-GPU, YUV-RGB upload of the current video frame to |texture|, + // reallocating |texture| at the appropriate size with given internal + // format, format, and type if necessary. + // + // Returns true iff the copy succeeded. + // + // |already_uploaded_id| indicates the unique_id of the frame last uploaded + // to this destination. It should only be set by the caller if the contents + // of the destination are known not to have changed since that upload. + // - If |out_metadata| is not null, |already_uploaded_id| is compared with + // the unique_id of the frame being uploaded. If it's the same, the + // upload may be skipped and considered to be successful. + // |out_metadata|, if not null, is used to return metadata about the frame + // that is uploaded during this call. + virtual bool CopyVideoYUVDataToPlatformTexture( + gpu::gles2::GLES2Interface*, + unsigned target, + unsigned texture, + unsigned internal_format, + unsigned format, + unsigned type, + int level, + bool premultiply_alpha, + bool flip_y, + int already_uploaded_id, + VideoFrameUploadMetadata* out_metadata) { + return false; + } + + // Copy sub video frame texture to |texture|. + // + // Returns true iff the copy succeeded. virtual bool CopyVideoSubTextureToPlatformTexture(gpu::gles2::GLES2Interface*, unsigned target, unsigned texture,
diff --git a/third_party/blink/renderer/core/DEPS b/third_party/blink/renderer/core/DEPS index 2527fda..6394fd59 100644 --- a/third_party/blink/renderer/core/DEPS +++ b/third_party/blink/renderer/core/DEPS
@@ -1,5 +1,6 @@ include_rules = [ "+base/atomic_sequence_num.h", + "+base/files/file.h", "+base/memory/scoped_refptr.h", "+base/synchronization/waitable_event.h", "+base/task/sequence_manager/task_time_observer.h",
diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink/renderer/core/dom/document.cc index a2f4d6f..5913d459a 100644 --- a/third_party/blink/renderer/core/dom/document.cc +++ b/third_party/blink/renderer/core/dom/document.cc
@@ -1496,6 +1496,15 @@ } void Document::SetContent(const String& content) { + // Only set the content of the document if it is ready to be set. This method + // could be called at any time. + if (ScriptableDocumentParser* parser = GetScriptableDocumentParser()) { + if (parser->IsParsing() && parser->IsExecutingScript()) + return; + } + if (ignore_opens_during_unload_count_) + return; + open(); parser_->Append(content); close(); @@ -3003,6 +3012,7 @@ } } +// https://html.spec.whatwg.org/C/dynamic-markup-insertion.html#document-open-steps void Document::open(Document* entered_document, ExceptionState& exception_state) { if (ImportLoader()) { @@ -3012,12 +3022,16 @@ return; } + // If |document| is an XML document, then throw an "InvalidStateError" + // DOMException exception. if (!IsHTMLDocument()) { exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError, "Only HTML documents support open()."); return; } + // If |document|'s throw-on-dynamic-markup-insertion counter is greater than + // 0, then throw an "InvalidStateError" DOMException. if (throw_on_dynamic_markup_insertion_count_) { exception_state.ThrowDOMException( DOMExceptionCode::kInvalidStateError, @@ -3028,25 +3042,40 @@ if (!AllowedToUseDynamicMarkUpInsertion("open", exception_state)) return; - if (entered_document) { - if (!GetSecurityOrigin()->IsSameSchemeHostPort( - entered_document->GetSecurityOrigin())) { - exception_state.ThrowSecurityError( - "Can only call open() on same-origin documents."); + // If |document|'s origin is not same origin to the origin of the responsible + // document specified by the entry settings object, then throw a + // "SecurityError" DOMException. + if (entered_document && !GetSecurityOrigin()->IsSameSchemeHostPort( + entered_document->GetSecurityOrigin())) { + exception_state.ThrowSecurityError( + "Can only call open() on same-origin documents."); + return; + } + + // If |document| has an active parser whose script nesting level is greater + // than 0, then return |document|. + if (ScriptableDocumentParser* parser = GetScriptableDocumentParser()) { + if (parser->IsParsing() && parser->IsExecutingScript()) return; - } + } + + // Similarly, if |document|'s ignore-opens-during-unload counter is greater + // than 0, then return |document|. + if (ignore_opens_during_unload_count_) + return; + + // Change |document|'s URL to the URL of the responsible document specified + // by the entry settings object. + if (entered_document && this != entered_document) { + // Clear the hash fragment from the inherited URL to prevent a + // scroll-into-view for any document.open()'d frame. + KURL new_url = entered_document->Url(); + new_url.SetFragmentIdentifier(String()); + SetURL(new_url); + SetSecurityOrigin(entered_document->GetMutableSecurityOrigin()); - - if (this != entered_document) { - // Clear the hash fragment from the inherited URL to prevent a - // scroll-into-view for any document.open()'d frame. - KURL new_url = entered_document->Url(); - new_url.SetFragmentIdentifier(String()); - SetURL(new_url); - SetReferrerPolicy(entered_document->GetReferrerPolicy()); - } - - cookie_url_ = entered_document->CookieURL(); + SetReferrerPolicy(entered_document->GetReferrerPolicy()); + SetCookieURL(entered_document->CookieURL()); } open(); @@ -3055,33 +3084,41 @@ // https://html.spec.whatwg.org/C/dynamic-markup-insertion.html#document-open-steps void Document::open() { DCHECK(!ImportLoader()); + DCHECK(!ignore_opens_during_unload_count_); + if (ScriptableDocumentParser* parser = GetScriptableDocumentParser()) + DCHECK(!parser->IsParsing() || !parser->IsExecutingScript()); - if (frame_) { - // If |document| has an active parser whose script nesting level is greater - // than 0, then return |document|. - if (ScriptableDocumentParser* parser = GetScriptableDocumentParser()) { - if (parser->IsParsing() && parser->IsExecutingScript()) - return; - } - - // Similarly, if |document|'s ignore-opens-during-unload counter is greater - // than 0, then return |document|. - if (ignore_opens_during_unload_count_) - return; - - if (frame_->Loader().HasProvisionalNavigation()) { - frame_->Loader().StopAllLoaders(); - // Navigations handled by the client should also be cancelled. - if (frame_->Client()) - frame_->Client()->AbortClientNavigation(); - } + // Abort |document|. + // + // TODO(timothygu): We are only aborting the document if there is a + // provisional navigation, unlike the spec. + if (frame_ && frame_->Loader().HasProvisionalNavigation()) { + frame_->Loader().StopAllLoaders(); + // Navigations handled by the client should also be cancelled. + if (frame_->Client()) + frame_->Client()->AbortClientNavigation(); } + // For each shadow-including inclusive descendant |node| of |document|, erase + // all event listeners and handlers given |node|. + // + // Erase all event listeners and handlers given |window|. + // + // NB: Document::RemoveAllEventListeners() (called by + // RemoveAllEventListenersRecursively()) erases event listeners from the + // Window object as well. RemoveAllEventListenersRecursively(); + ResetTreeScope(); if (frame_) frame_->Selection().Clear(); + + // Create a new HTML parser and associate it with |document|. + // + // Set the current document readiness of |document| to "loading". ImplicitOpen(kForceSynchronousParsing); + + // This is a script-created parser. if (ScriptableDocumentParser* parser = GetScriptableDocumentParser()) parser->SetWasCreatedByScript(true); @@ -3277,10 +3314,8 @@ entered_window, exception_state); } +// https://html.spec.whatwg.org/C/dynamic-markup-insertion.html#dom-document-close void Document::close(ExceptionState& exception_state) { - // FIXME: We should follow the specification more closely: - // http://www.whatwg.org/specs/web-apps/current-work/#dom-document-close - if (ImportLoader()) { exception_state.ThrowDOMException( DOMExceptionCode::kInvalidStateError, @@ -3288,12 +3323,16 @@ return; } + // If the Document object is an XML document, then throw an + // "InvalidStateError" DOMException. if (!IsHTMLDocument()) { exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError, "Only HTML documents support close()."); return; } + // If the Document object's throw-on-dynamic-markup-insertion counter is + // greater than zero, then throw an "InvalidStateError" DOMException. if (throw_on_dynamic_markup_insertion_count_) { exception_state.ThrowDOMException( DOMExceptionCode::kInvalidStateError, @@ -3307,13 +3346,20 @@ close(); } +// https://html.spec.whatwg.org/C/dynamic-markup-insertion.html#dom-document-close void Document::close() { + // If there is no script-created parser associated with the document, then + // return. if (!GetScriptableDocumentParser() || !GetScriptableDocumentParser()->WasCreatedByScript() || !GetScriptableDocumentParser()->IsParsing()) return; + // Insert an explicit "EOF" character at the end of the parser's input + // stream. parser_->Finish(); + + // TODO(timothygu): We should follow the specification more closely. if (!parser_ || !parser_->IsParsing()) SetReadyState(kComplete); CheckCompleted();
diff --git a/third_party/blink/renderer/core/dom/slot_assignment.cc b/third_party/blink/renderer/core/dom/slot_assignment.cc index 9db5db1..8b3fe1c 100644 --- a/third_party/blink/renderer/core/dom/slot_assignment.cc +++ b/third_party/blink/renderer/core/dom/slot_assignment.cc
@@ -37,6 +37,10 @@ ++slot_count_; needs_collect_slots_ = true; + if (owner_->IsManualSlotting()) { + DidAddSlotInternalInManualMode(slot); + return; + } DCHECK(!slot_map_->Contains(slot.GetName()) || GetCachedFirstSlotWithoutAccessingNodeTree(slot.GetName())); @@ -54,6 +58,15 @@ DCHECK_GT(slot_count_, 0u); --slot_count_; + if (owner_->IsManualSlotting()) { + DCHECK(!needs_collect_slots_); + CallSlotChangeIfNeeded(slot); + needs_collect_slots_ = true; + // TODO(crbug.com/869308):Avoid calling Slots in order not to hit the + // DCHECK(!needs_collect_slots_) + Slots(); + return; + } needs_collect_slots_ = true; DCHECK(GetCachedFirstSlotWithoutAccessingNodeTree(slot.GetName())); @@ -111,6 +124,17 @@ } } +void SlotAssignment::DidAddSlotInternalInManualMode(HTMLSlotElement& slot) { + for (Node& child : NodeTraversal::ChildrenOf(owner_->host())) { + auto* change_slot = FindSlotChange(slot, child); + if (change_slot) { + slot.SignalSlotChange(); + if (change_slot != slot) + change_slot->SignalSlotChange(); + } + } +} + void SlotAssignment::DidRemoveSlotInternal( HTMLSlotElement& slot, const AtomicString& slot_name, @@ -365,6 +389,35 @@ return user_agent_default_slot; } +HTMLSlotElement* SlotAssignment::FindSlotChange(HTMLSlotElement& slot, + Node& child) { + HTMLSlotElement* found_this_slot = nullptr; + for (auto a_slot : Slots()) { + if (a_slot == slot) { + found_this_slot = &slot; + continue; + } + if (a_slot->ContainsInAssignedNodesCandidates(child)) { + if (found_this_slot) { + // case2 in DidRemoveSlotChange or DidAddSlotChange + return a_slot; + } + // case3 in DidRemoveSlotChange or DidAddSlotChange + return nullptr; + } + } + // case1 in DidRemoveSlotChange or DidAddSlotChange or no slot for the child + return found_this_slot; +} + +void SlotAssignment::CallSlotChangeIfNeeded(HTMLSlotElement& slot) { + for (Node& child : NodeTraversal::ChildrenOf(owner_->host())) { + auto* change_slot = FindSlotChange(slot, child); + if (change_slot && change_slot != slot) + change_slot->SignalSlotChange(); + } +} + HTMLSlotElement* SlotAssignment::FindFirstAssignedSlot(Node& node) { for (auto slot : Slots()) { if (slot->ContainsInAssignedNodesCandidates(node))
diff --git a/third_party/blink/renderer/core/dom/slot_assignment.h b/third_party/blink/renderer/core/dom/slot_assignment.h index df07d8ef..9b27563 100644 --- a/third_party/blink/renderer/core/dom/slot_assignment.h +++ b/third_party/blink/renderer/core/dom/slot_assignment.h
@@ -43,6 +43,8 @@ const AtomicString& new_value); bool FindHostChildBySlotName(const AtomicString& slot_name) const; + void CallSlotChangeIfNeeded(HTMLSlotElement& slot); + HTMLSlotElement* FindSlotChange(HTMLSlotElement& slot, Node& child); void Trace(blink::Visitor*); @@ -71,6 +73,7 @@ const AtomicString& slot_name); void DidAddSlotInternal(HTMLSlotElement&); + void DidAddSlotInternalInManualMode(HTMLSlotElement&); void DidRemoveSlotInternal(HTMLSlotElement&, const AtomicString& slot_name, SlotMutationType);
diff --git a/third_party/blink/renderer/core/exported/web_element.cc b/third_party/blink/renderer/core/exported/web_element.cc index e9f1304a..24931b7 100644 --- a/third_party/blink/renderer/core/exported/web_element.cc +++ b/third_party/blink/renderer/core/exported/web_element.cc
@@ -155,9 +155,10 @@ SkBitmap WebElement::ImageContents() { if (IsNull()) return {}; - - return Unwrap<Element>()->ImageContents()->AsSkBitmapForCurrentFrame( - kRespectImageOrientation); + Image* image = Unwrap<Element>()->ImageContents(); + if (!image) + return {}; + return image->AsSkBitmapForCurrentFrame(kRespectImageOrientation); } void WebElement::RequestFullscreen() {
diff --git a/third_party/blink/renderer/core/fileapi/file_error.cc b/third_party/blink/renderer/core/fileapi/file_error.cc index 990ab27..bad63bf4 100644 --- a/third_party/blink/renderer/core/fileapi/file_error.cc +++ b/third_party/blink/renderer/core/fileapi/file_error.cc
@@ -143,6 +143,88 @@ } } +DOMExceptionCode FileErrorToExceptionCode(base::File::Error code) { + switch (code) { + case base::File::FILE_OK: + return DOMExceptionCode::kNoError; + case base::File::FILE_ERROR_FAILED: + return DOMExceptionCode::kInvalidStateError; + case base::File::FILE_ERROR_EXISTS: + return DOMExceptionCode::kPathExistsError; + case base::File::FILE_ERROR_NOT_EMPTY: + case base::File::FILE_ERROR_INVALID_OPERATION: + return DOMExceptionCode::kInvalidModificationError; + case base::File::FILE_ERROR_TOO_MANY_OPENED: + case base::File::FILE_ERROR_NO_MEMORY: + return DOMExceptionCode::kUnknownError; + case base::File::FILE_ERROR_NOT_FOUND: + return DOMExceptionCode::kNotFoundError; + case base::File::FILE_ERROR_IN_USE: + case base::File::FILE_ERROR_ACCESS_DENIED: + return DOMExceptionCode::kNoModificationAllowedError; + case base::File::FILE_ERROR_NO_SPACE: + return DOMExceptionCode::kQuotaExceededError; + case base::File::FILE_ERROR_NOT_A_DIRECTORY: + case base::File::FILE_ERROR_NOT_A_FILE: + return DOMExceptionCode::kTypeMismatchError; + case base::File::FILE_ERROR_ABORT: + return DOMExceptionCode::kAbortError; + case base::File::FILE_ERROR_SECURITY: + return DOMExceptionCode::kSecurityError; + case base::File::FILE_ERROR_INVALID_URL: + return DOMExceptionCode::kEncodingError; + case base::File::FILE_ERROR_IO: + return DOMExceptionCode::kNotReadableError; + case base::File::FILE_ERROR_MAX: + NOTREACHED(); + return DOMExceptionCode::kUnknownError; + } + NOTREACHED(); + return DOMExceptionCode::kUnknownError; +} + +const char* FileErrorToMessage(base::File::Error code) { + // Note that some of these do not set message. If message is null then the + // default message is used. + switch (code) { + case base::File::FILE_ERROR_NOT_FOUND: + return kNotFoundErrorMessage; + case base::File::FILE_ERROR_ACCESS_DENIED: + return kNoModificationAllowedErrorMessage; + case base::File::FILE_ERROR_FAILED: + return kInvalidStateErrorMessage; + case base::File::FILE_ERROR_ABORT: + return kAbortErrorMessage; + case base::File::FILE_ERROR_SECURITY: + return kSecurityErrorMessage; + case base::File::FILE_ERROR_NO_SPACE: + return kQuotaExceededErrorMessage; + case base::File::FILE_ERROR_INVALID_URL: + return kEncodingErrorMessage; + case base::File::FILE_ERROR_IO: + return kNotReadableErrorMessage; + case base::File::FILE_ERROR_EXISTS: + return kPathExistsErrorMessage; + case base::File::FILE_ERROR_NOT_A_DIRECTORY: + case base::File::FILE_ERROR_NOT_A_FILE: + return kTypeMismatchErrorMessage; + case base::File::FILE_OK: + case base::File::FILE_ERROR_INVALID_OPERATION: + case base::File::FILE_ERROR_NOT_EMPTY: + case base::File::FILE_ERROR_NO_MEMORY: + case base::File::FILE_ERROR_TOO_MANY_OPENED: + case base::File::FILE_ERROR_IN_USE: + // TODO(mek): More specific error messages for at least some of these + // errors. + return nullptr; + case base::File::FILE_ERROR_MAX: + NOTREACHED(); + return nullptr; + } + NOTREACHED(); + return nullptr; +} + } // namespace void ThrowDOMException(ExceptionState& exception_state, @@ -171,6 +253,12 @@ ErrorCodeToMessage(code)); } +DOMException* CreateDOMException(base::File::Error code) { + DCHECK_NE(code, base::File::FILE_OK); + return DOMException::Create(FileErrorToExceptionCode(code), + FileErrorToMessage(code)); +} + STATIC_ASSERT_ENUM(kWebFileErrorNotFound, kNotFoundErr); STATIC_ASSERT_ENUM(kWebFileErrorSecurity, kSecurityErr); STATIC_ASSERT_ENUM(kWebFileErrorAbort, kAbortErr);
diff --git a/third_party/blink/renderer/core/fileapi/file_error.h b/third_party/blink/renderer/core/fileapi/file_error.h index 4b5408c1..36aad68 100644 --- a/third_party/blink/renderer/core/fileapi/file_error.h +++ b/third_party/blink/renderer/core/fileapi/file_error.h
@@ -31,6 +31,7 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_FILEAPI_FILE_ERROR_H_ #define THIRD_PARTY_BLINK_RENDERER_CORE_FILEAPI_FILE_ERROR_H_ +#include "base/files/file.h" #include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" @@ -73,6 +74,7 @@ ErrorCode, String message = String()); CORE_EXPORT DOMException* CreateDOMException(ErrorCode); +CORE_EXPORT DOMException* CreateDOMException(base::File::Error); } // namespace FileError
diff --git a/third_party/blink/renderer/core/html/html_slot_element.cc b/third_party/blink/renderer/core/html/html_slot_element.cc index f5c28af7..7006760e 100644 --- a/third_party/blink/renderer/core/html/html_slot_element.cc +++ b/third_party/blink/renderer/core/html/html_slot_element.cc
@@ -189,12 +189,36 @@ return elements; } +bool HTMLSlotElement::IsAssignedNodeSameWithBefore( + HeapVector<Member<Node>>& new_assigned_nodes, + HeapHashSet<Member<Node>>& old_assigned_nodes) { + if (new_assigned_nodes.size() != old_assigned_nodes.size()) + return false; + for (auto node : old_assigned_nodes) { + if (!new_assigned_nodes.Contains(*node)) + return false; + } + return true; +} + void HTMLSlotElement::assign(HeapVector<Member<Node>> nodes) { - ContainingShadowRoot()->GetSlotAssignment().SetNeedsAssignmentRecalc(); + if (ContainingShadowRoot()) { + SlotChangeType slot_change_type = + IsAssignedNodeSameWithBefore(nodes, assigned_nodes_candidates_) + ? SlotChangeType::kSuppressSlotChangeEvent + : SlotChangeType::kSignalSlotChangeEvent; + DidSlotChange(slot_change_type); + } assigned_nodes_candidates_.clear(); for (Member<Node> child : nodes) { assigned_nodes_candidates_.insert(child); } + if (ContainingShadowRoot()) { + ContainingShadowRoot()->GetSlotAssignment().CallSlotChangeIfNeeded(*this); + // TODO(crbug.com/869308): Don't call SetNeedsAssignmentRecalc if we can + // detect all possible slotchange surely + ContainingShadowRoot()->GetSlotAssignment().SetNeedsAssignmentRecalc(); + } } bool HTMLSlotElement::ContainsInAssignedNodesCandidates( @@ -202,6 +226,10 @@ return assigned_nodes_candidates_.Contains(&host_child); } +void HTMLSlotElement::SignalSlotChange() { + DidSlotChange(SlotChangeType::kSignalSlotChangeEvent); +} + const HeapVector<Member<Node>>& HTMLSlotElement::GetDistributedNodes() { DCHECK(!RuntimeEnabledFeatures::IncrementalShadowDOMEnabled()); DCHECK(!NeedsDistributionRecalc());
diff --git a/third_party/blink/renderer/core/html/html_slot_element.h b/third_party/blink/renderer/core/html/html_slot_element.h index cb73e39c..f3540f7 100644 --- a/third_party/blink/renderer/core/html/html_slot_element.h +++ b/third_party/blink/renderer/core/html/html_slot_element.h
@@ -53,8 +53,12 @@ const HeapVector<Member<Element>> AssignedElementsForBinding( const AssignedNodesOptions&); + bool IsAssignedNodeSameWithBefore( + HeapVector<Member<Node>>& new_assigned_nodes, + HeapHashSet<Member<Node>>& old_assigned_nodes); void assign(HeapVector<Member<Node>> nodes); bool ContainsInAssignedNodesCandidates(Node&) const; + void SignalSlotChange(); const HeapVector<Member<Node>> FlattenedAssignedNodes();
diff --git a/third_party/blink/renderer/core/html/media/html_media_element.cc b/third_party/blink/renderer/core/html/media/html_media_element.cc index 8131b5f7..5e4ea3d 100644 --- a/third_party/blink/renderer/core/html/media/html_media_element.cc +++ b/third_party/blink/renderer/core/html/media/html_media_element.cc
@@ -1828,8 +1828,6 @@ if (ready_state_ >= kHaveMetadata && old_state < kHaveMetadata) { CreatePlaceholderTracksIfNecessary(); - SelectInitialTracksIfNecessary(); - MediaFragmentURIParser fragment_parser(current_src_); fragment_end_time_ = fragment_parser.EndTime(); @@ -3981,30 +3979,17 @@ // didn't explicitly announce the tracks. if (HasAudio() && !audioTracks().length()) { AddAudioTrack("audio", WebMediaPlayerClient::kAudioTrackKindMain, - "Audio Track", "", false); + "Audio Track", "", true); } // Create a placeholder video track if the player says it has video but it // didn't explicitly announce the tracks. if (HasVideo() && !videoTracks().length()) { AddVideoTrack("video", WebMediaPlayerClient::kVideoTrackKindMain, - "Video Track", "", false); + "Video Track", "", true); } } -void HTMLMediaElement::SelectInitialTracksIfNecessary() { - if (!MediaTracksEnabledInternally()) - return; - - // Enable the first audio track if an audio track hasn't been enabled yet. - if (audioTracks().length() > 0 && !audioTracks().HasEnabledTrack()) - audioTracks().AnonymousIndexedGetter(0)->setEnabled(true); - - // Select the first video track if a video track hasn't been selected yet. - if (videoTracks().length() > 0 && videoTracks().selectedIndex() == -1) - videoTracks().AnonymousIndexedGetter(0)->setSelected(true); -} - void HTMLMediaElement::SetNetworkState(NetworkState state) { if (network_state_ == state) return;
diff --git a/third_party/blink/renderer/core/html/media/html_media_element.h b/third_party/blink/renderer/core/html/media/html_media_element.h index e8a8b97..a69c53b3 100644 --- a/third_party/blink/renderer/core/html/media/html_media_element.h +++ b/third_party/blink/renderer/core/html/media/html_media_element.h
@@ -534,16 +534,12 @@ DirectionOfPlayback GetDirectionOfPlayback() const; // Creates placeholder AudioTrack and/or VideoTrack objects when - // WebMemediaPlayer objects advertise they have audio and/or video, but don't + // WebMediaPlayer objects advertise they have audio and/or video, but don't // explicitly signal them via addAudioTrack() and addVideoTrack(). // FIXME: Remove this once all WebMediaPlayer implementations properly report // their track info. void CreatePlaceholderTracksIfNecessary(); - // Sets the selected/enabled tracks if they aren't set before we initially - // transition to kHaveMetadata. - void SelectInitialTracksIfNecessary(); - void SetNetworkState(NetworkState); void AudioTracksTimerFired(TimerBase*);
diff --git a/third_party/blink/renderer/core/html/media/html_media_element_test.cc b/third_party/blink/renderer/core/html/media/html_media_element_test.cc index ad72f7c..86a12b86 100644 --- a/third_party/blink/renderer/core/html/media/html_media_element_test.cc +++ b/third_party/blink/renderer/core/html/media/html_media_element_test.cc
@@ -12,6 +12,8 @@ #include "third_party/blink/renderer/core/html/media/html_audio_element.h" #include "third_party/blink/renderer/core/html/media/html_video_element.h" #include "third_party/blink/renderer/core/html/media/media_error.h" +#include "third_party/blink/renderer/core/html/track/audio_track_list.h" +#include "third_party/blink/renderer/core/html/track/video_track_list.h" #include "third_party/blink/renderer/core/loader/empty_clients.h" #include "third_party/blink/renderer/core/testing/dummy_page_holder.h" #include "third_party/blink/renderer/platform/network/network_state_notifier.h" @@ -26,8 +28,12 @@ class MockWebMediaPlayer : public EmptyWebMediaPlayer { public: + MOCK_CONST_METHOD0(HasAudio, bool()); + MOCK_CONST_METHOD0(HasVideo, bool()); MOCK_CONST_METHOD0(Duration, double()); MOCK_CONST_METHOD0(CurrentTime, double()); + MOCK_METHOD1(EnabledAudioTracksChanged, void(const WebVector<TrackId>&)); + MOCK_METHOD1(SelectedVideoTrackChanged, void(TrackId*)); MOCK_METHOD3( Load, WebMediaPlayer::LoadTiming(LoadType load_type, @@ -69,7 +75,15 @@ // Most tests do not care about this call, nor its return value. Those that // do will clear this expectation and set custom expectations/returns. - EXPECT_CALL(*MockMediaPlayer(), Load(_, _, _)) + EXPECT_CALL(*mock_media_player, HasAudio()) + .WillRepeatedly(testing::Return(true)); + EXPECT_CALL(*mock_media_player, HasVideo()) + .WillRepeatedly(testing::Return(true)); + EXPECT_CALL(*mock_media_player, Duration()) + .WillRepeatedly(testing::Return(1.0)); + EXPECT_CALL(*mock_media_player, CurrentTime()) + .WillRepeatedly(testing::Return(0)); + EXPECT_CALL(*mock_media_player, Load(_, _, _)) .Times(AnyNumber()) .WillRepeatedly(Return(WebMediaPlayer::LoadTiming::kImmediate)); @@ -235,8 +249,6 @@ MockWebMediaPlayer* mock_wmpi = reinterpret_cast<MockWebMediaPlayer*>(Media()->GetWebMediaPlayer()); EXPECT_NE(mock_wmpi, nullptr); - EXPECT_CALL(*mock_wmpi, Duration()).WillRepeatedly(testing::Return(1.0)); - EXPECT_CALL(*mock_wmpi, CurrentTime()).WillRepeatedly(testing::Return(0)); EXPECT_TRUE(CouldPlayIfEnoughData()); // Playback can only end once the ready state is above kHaveMetadata. @@ -262,8 +274,6 @@ MockWebMediaPlayer* mock_wmpi = reinterpret_cast<MockWebMediaPlayer*>(Media()->GetWebMediaPlayer()); EXPECT_NE(mock_wmpi, nullptr); - EXPECT_CALL(*mock_wmpi, Duration()).WillRepeatedly(testing::Return(1.0)); - EXPECT_CALL(*mock_wmpi, CurrentTime()).WillRepeatedly(testing::Return(0)); EXPECT_TRUE(CouldPlayIfEnoughData()); SetReadyState(HTMLMediaElement::kHaveMetadata); @@ -419,4 +429,19 @@ EXPECT_TRUE(ShouldDelayLoadEvent()); } +TEST_P(HTMLMediaElementTest, DefaultTracksAreEnabled) { + // Default tracks should start enabled, not be created then enabled. + EXPECT_CALL(*MockMediaPlayer(), EnabledAudioTracksChanged(_)).Times(0); + EXPECT_CALL(*MockMediaPlayer(), SelectedVideoTrackChanged(_)).Times(0); + + Media()->SetSrc(SrcSchemeToURL(TestURLScheme::kHttp)); + test::RunPendingTasks(); + SetReadyState(HTMLMediaElement::kHaveFutureData); + + ASSERT_EQ(1u, Media()->audioTracks().length()); + ASSERT_EQ(1u, Media()->videoTracks().length()); + EXPECT_TRUE(Media()->audioTracks().AnonymousIndexedGetter(0)->enabled()); + EXPECT_TRUE(Media()->videoTracks().AnonymousIndexedGetter(0)->selected()); +} + } // namespace blink
diff --git a/third_party/blink/renderer/core/html/media/html_video_element.cc b/third_party/blink/renderer/core/html/media/html_video_element.cc index 95e18bd..1f1437c 100644 --- a/third_party/blink/renderer/core/html/media/html_video_element.cc +++ b/third_party/blink/renderer/core/html/media/html_video_element.cc
@@ -369,6 +369,26 @@ premultiply_alpha, flip_y, already_uploaded_id, out_metadata); } +bool HTMLVideoElement::CopyVideoYUVDataToPlatformTexture( + gpu::gles2::GLES2Interface* gl, + GLenum target, + GLuint texture, + GLenum internal_format, + GLenum format, + GLenum type, + GLint level, + bool premultiply_alpha, + bool flip_y, + int already_uploaded_id, + WebMediaPlayer::VideoFrameUploadMetadata* out_metadata) { + if (!GetWebMediaPlayer()) + return false; + + return GetWebMediaPlayer()->CopyVideoYUVDataToPlatformTexture( + gl, target, texture, internal_format, format, type, level, + premultiply_alpha, flip_y, already_uploaded_id, out_metadata); +} + bool HTMLVideoElement::TexImageImpl( WebMediaPlayer::TexImageFunctionID function_id, GLenum target,
diff --git a/third_party/blink/renderer/core/html/media/html_video_element.h b/third_party/blink/renderer/core/html/media/html_video_element.h index 09d299d..ef294a2 100644 --- a/third_party/blink/renderer/core/html/media/html_video_element.h +++ b/third_party/blink/renderer/core/html/media/html_video_element.h
@@ -85,9 +85,9 @@ const IntRect&, const cc::PaintFlags*, int already_uploaded_id = -1, - WebMediaPlayer::VideoFrameUploadMetadata* = nullptr) const; + WebMediaPlayer::VideoFrameUploadMetadata* out_metadata = nullptr) const; - // Used by WebGL to do GPU-GPU textures copy if possible. + // Used by WebGL to do GPU-GPU texture copy if possible. bool CopyVideoTextureToPlatformTexture( gpu::gles2::GLES2Interface*, GLenum target, @@ -98,8 +98,22 @@ GLint level, bool premultiply_alpha, bool flip_y, - int already_uploaded_id = -1, - WebMediaPlayer::VideoFrameUploadMetadata* out_metadata = nullptr); + int already_uploaded_id, + WebMediaPlayer::VideoFrameUploadMetadata* out_metadata); + + // Used by WebGL to do YUV-RGB, CPU-GPU texture copy if possible. + bool CopyVideoYUVDataToPlatformTexture( + gpu::gles2::GLES2Interface*, + GLenum target, + GLuint texture, + GLenum internal_format, + GLenum format, + GLenum type, + GLint level, + bool premultiply_alpha, + bool flip_y, + int already_uploaded_id, + WebMediaPlayer::VideoFrameUploadMetadata* out_metadata); // Used by WebGL to do CPU-GPU texture upload if possible. bool TexImageImpl(WebMediaPlayer::TexImageFunctionID,
diff --git a/third_party/blink/renderer/core/layout/layout_box_model_object.cc b/third_party/blink/renderer/core/layout/layout_box_model_object.cc index cbac05e..63ebb6a 100644 --- a/third_party/blink/renderer/core/layout/layout_box_model_object.cc +++ b/third_party/blink/renderer/core/layout/layout_box_model_object.cc
@@ -802,6 +802,8 @@ } void LayoutBoxModelObject::UpdateStickyPositionConstraints() const { + DCHECK(StyleRef().HasStickyConstrainedPosition()); + const FloatSize constraining_size = ComputeStickyConstrainingRect().Size(); StickyPositionScrollingConstraints constraints; @@ -878,8 +880,8 @@ max_container_width) + MinimumValueForLength(Style()->MarginLeft(), max_width)); - constraints.SetScrollContainerRelativeContainingBlockRect( - FloatRect(scroll_container_relative_containing_block_rect)); + constraints.scroll_container_relative_containing_block_rect = + FloatRect(scroll_container_relative_containing_block_rect); FloatRect sticky_box_rect = IsLayoutInline() ? FloatRect(ToLayoutInline(this)->LinesBoundingBox()) @@ -898,10 +900,10 @@ FloatSize container_border_offset(containing_block->BorderLeft(), containing_block->BorderTop()); sticky_location -= container_border_offset; - constraints.SetScrollContainerRelativeStickyBoxRect( + constraints.scroll_container_relative_sticky_box_rect = FloatRect(scroll_container_relative_padding_box_rect.Location() + ToFloatSize(sticky_location), - flipped_sticky_box_rect.Size())); + flipped_sticky_box_rect.Size()); // To correctly compute the offsets, the constraints need to know about any // nested position:sticky elements between themselves and their @@ -909,14 +911,14 @@ // // The respective search ranges are [container, containingBlock) and // [containingBlock, scrollAncestor). - constraints.SetNearestStickyLayerShiftingStickyBox( - FindFirstStickyBetween(location_container, containing_block)); + constraints.nearest_sticky_layer_shifting_sticky_box = + FindFirstStickyBetween(location_container, containing_block); // We cannot use |scrollAncestor| here as it disregards the root // ancestorOverflowLayer(), which we should include. - constraints.SetNearestStickyLayerShiftingContainingBlock( + constraints.nearest_sticky_layer_shifting_containing_block = FindFirstStickyBetween( containing_block, - &Layer()->AncestorOverflowLayer()->GetLayoutObject())); + &Layer()->AncestorOverflowLayer()->GetLayoutObject()); // We skip the right or top sticky offset if there is not enough space to // honor both the left/right or top/bottom offsets. @@ -938,17 +940,15 @@ } if (!Style()->Left().IsAuto() && !skip_left) { - constraints.SetLeftOffset(MinimumValueForLength( - Style()->Left(), LayoutUnit(constraining_size.Width()))); - constraints.AddAnchorEdge( - StickyPositionScrollingConstraints::kAnchorEdgeLeft); + constraints.left_offset = MinimumValueForLength( + Style()->Left(), LayoutUnit(constraining_size.Width())); + constraints.is_anchored_left = true; } if (!Style()->Right().IsAuto() && !skip_right) { - constraints.SetRightOffset(MinimumValueForLength( - Style()->Right(), LayoutUnit(constraining_size.Width()))); - constraints.AddAnchorEdge( - StickyPositionScrollingConstraints::kAnchorEdgeRight); + constraints.right_offset = MinimumValueForLength( + Style()->Right(), LayoutUnit(constraining_size.Width())); + constraints.is_anchored_right = true; } bool skip_bottom = false; @@ -970,20 +970,16 @@ } if (!Style()->Top().IsAuto()) { - constraints.SetTopOffset(MinimumValueForLength( - Style()->Top(), LayoutUnit(constraining_size.Height()))); - constraints.AddAnchorEdge( - StickyPositionScrollingConstraints::kAnchorEdgeTop); + constraints.top_offset = MinimumValueForLength( + Style()->Top(), LayoutUnit(constraining_size.Height())); + constraints.is_anchored_top = true; } if (!Style()->Bottom().IsAuto() && !skip_bottom) { - constraints.SetBottomOffset(MinimumValueForLength( - Style()->Bottom(), LayoutUnit(constraining_size.Height()))); - constraints.AddAnchorEdge( - StickyPositionScrollingConstraints::kAnchorEdgeBottom); + constraints.bottom_offset = MinimumValueForLength( + Style()->Bottom(), LayoutUnit(constraining_size.Height())); + constraints.is_anchored_bottom = true; } - // At least one edge should be anchored if we are calculating constraints. - DCHECK(constraints.GetAnchorEdges()); PaintLayerScrollableArea* scrollable_area = Layer()->AncestorOverflowLayer()->GetScrollableArea(); scrollable_area->GetStickyConstraintsMap().Set(Layer(), constraints);
diff --git a/third_party/blink/renderer/core/layout/layout_box_model_object_test.cc b/third_party/blink/renderer/core/layout/layout_box_model_object_test.cc index 51ff438c..a2987b8 100644 --- a/third_party/blink/renderer/core/layout/layout_box_model_object_test.cc +++ b/third_party/blink/renderer/core/layout/layout_box_model_object_test.cc
@@ -21,16 +21,6 @@ PaintLayer* GetPaintLayerByElementId(const char* id) { return ToLayoutBoxModelObject(GetLayoutObjectByElementId(id))->Layer(); } - - const FloatRect& GetScrollContainerRelativeContainingBlockRect( - const StickyPositionScrollingConstraints& constraints) const { - return constraints.ScrollContainerRelativeContainingBlockRect(); - } - - const FloatRect& GetScrollContainerRelativeStickyBoxRect( - const StickyPositionScrollingConstraints& constraints) const { - return constraints.ScrollContainerRelativeStickyBoxRect(); - } }; // Verifies that the sticky constraints are correctly computed. @@ -59,16 +49,16 @@ const StickyPositionScrollingConstraints& constraints = scrollable_area->GetStickyConstraintsMap().at(sticky->Layer()); - ASSERT_EQ(0.f, constraints.TopOffset()); + ASSERT_EQ(0.f, constraints.top_offset); // The coordinates of the constraint rects should all be with respect to the // unscrolled scroller. ASSERT_EQ(IntRect(15, 115, 170, 370), EnclosingIntRect( - GetScrollContainerRelativeContainingBlockRect(constraints))); + constraints.scroll_container_relative_containing_block_rect)); ASSERT_EQ( IntRect(15, 115, 100, 100), - EnclosingIntRect(GetScrollContainerRelativeStickyBoxRect(constraints))); + EnclosingIntRect(constraints.scroll_container_relative_sticky_box_rect)); // The sticky constraining rect also doesn't include the border offset. ASSERT_EQ(IntRect(0, 50, 400, 100), @@ -102,16 +92,16 @@ const StickyPositionScrollingConstraints& constraints = scrollable_area->GetStickyConstraintsMap().at(sticky->Layer()); - ASSERT_EQ(0.f, constraints.TopOffset()); + ASSERT_EQ(0.f, constraints.top_offset); // The coordinates of the constraint rects should all be with respect to the // unscrolled scroller. ASSERT_EQ(IntRect(215, 115, 170, 370), EnclosingIntRect( - GetScrollContainerRelativeContainingBlockRect(constraints))); + constraints.scroll_container_relative_containing_block_rect)); ASSERT_EQ( IntRect(285, 115, 100, 100), - EnclosingIntRect(GetScrollContainerRelativeStickyBoxRect(constraints))); + EnclosingIntRect(constraints.scroll_container_relative_sticky_box_rect)); // The sticky constraining rect also doesn't include the border offset. ASSERT_EQ(IntRect(0, 50, 400, 100), @@ -155,16 +145,16 @@ const StickyPositionScrollingConstraints& constraints = scrollable_area->GetStickyConstraintsMap().at(sticky->Layer()); - EXPECT_EQ(10.f, constraints.TopOffset()); + EXPECT_EQ(10.f, constraints.top_offset); // The coordinates of the constraint rects should all be with respect to the // unscrolled scroller. EXPECT_EQ(IntRect(0, 100, 200, 400), EnclosingIntRect( - GetScrollContainerRelativeContainingBlockRect(constraints))); + constraints.scroll_container_relative_containing_block_rect)); EXPECT_EQ( IntRect(0, 100, 10, 10), - EnclosingIntRect(GetScrollContainerRelativeStickyBoxRect(constraints))); + EnclosingIntRect(constraints.scroll_container_relative_sticky_box_rect)); EXPECT_EQ(IntRect(0, 50, 100, 100), EnclosingIntRect(sticky->ComputeStickyConstrainingRect())); } @@ -214,16 +204,16 @@ const StickyPositionScrollingConstraints& constraints = scrollable_area->GetStickyConstraintsMap().at(sticky->Layer()); - EXPECT_EQ(10.f, constraints.TopOffset()); + EXPECT_EQ(10.f, constraints.top_offset); // The coordinates of the constraint rects should all be with respect to the // unscrolled scroller. EXPECT_EQ(IntRect(2000, 100, 200, 400), EnclosingIntRect( - GetScrollContainerRelativeContainingBlockRect(constraints))); + constraints.scroll_container_relative_containing_block_rect)); EXPECT_EQ( IntRect(2190, 100, 10, 10), - EnclosingIntRect(GetScrollContainerRelativeStickyBoxRect(constraints))); + EnclosingIntRect(constraints.scroll_container_relative_sticky_box_rect)); EXPECT_EQ(IntRect(2100, 50, 100, 100), EnclosingIntRect(sticky->ComputeStickyConstrainingRect())); } @@ -255,16 +245,16 @@ const StickyPositionScrollingConstraints& constraints = scrollable_area->GetStickyConstraintsMap().at(sticky->Layer()); - ASSERT_EQ(0.f, constraints.TopOffset()); + ASSERT_EQ(0.f, constraints.top_offset); // The coordinates of the constraint rects should all be with respect to the // unscrolled scroller. ASSERT_EQ(IntRect(15, 115, 170, 370), EnclosingIntRect( - GetScrollContainerRelativeContainingBlockRect(constraints))); + constraints.scroll_container_relative_containing_block_rect)); ASSERT_EQ( IntRect(15, 115, 100, 100), - EnclosingIntRect(GetScrollContainerRelativeStickyBoxRect(constraints))); + EnclosingIntRect(constraints.scroll_container_relative_sticky_box_rect)); } // Verifies that the sticky constraints are correctly computed. @@ -293,14 +283,14 @@ const StickyPositionScrollingConstraints& constraints = scrollable_area->GetStickyConstraintsMap().at(sticky->Layer()); - ASSERT_EQ(0.f, constraints.TopOffset()); + ASSERT_EQ(0.f, constraints.top_offset); ASSERT_EQ(IntRect(25, 145, 200, 330), EnclosingIntRect( - GetScrollContainerRelativeContainingBlockRect(constraints))); + constraints.scroll_container_relative_containing_block_rect)); ASSERT_EQ( IntRect(25, 145, 100, 100), - EnclosingIntRect(GetScrollContainerRelativeStickyBoxRect(constraints))); + EnclosingIntRect(constraints.scroll_container_relative_sticky_box_rect)); } // Verifies that the sticky constraints are correct when the sticky position @@ -330,10 +320,10 @@ scrollable_area->GetStickyConstraintsMap().at(sticky->Layer()); ASSERT_EQ(IntRect(0, 0, 400, 1100), EnclosingIntRect( - GetScrollContainerRelativeContainingBlockRect(constraints))); + constraints.scroll_container_relative_containing_block_rect)); ASSERT_EQ( IntRect(0, 0, 100, 100), - EnclosingIntRect(GetScrollContainerRelativeStickyBoxRect(constraints))); + EnclosingIntRect(constraints.scroll_container_relative_sticky_box_rect)); } // Verifies that the sticky constraints are correct when the sticky position @@ -366,10 +356,10 @@ scrollable_area->GetStickyConstraintsMap().at(sticky->Layer()); ASSERT_EQ(IntRect(15, 115, 170, 370), EnclosingIntRect( - GetScrollContainerRelativeContainingBlockRect(constraints))); + constraints.scroll_container_relative_containing_block_rect)); ASSERT_EQ( IntRect(15, 165, 100, 100), - EnclosingIntRect(GetScrollContainerRelativeStickyBoxRect(constraints))); + EnclosingIntRect(constraints.scroll_container_relative_sticky_box_rect)); } TEST_F(LayoutBoxModelObjectTest, StickyPositionTableContainers) { @@ -395,10 +385,10 @@ scrollable_area->GetStickyConstraintsMap().at(sticky->Layer()); EXPECT_EQ(IntRect(0, 0, 50, 100), EnclosingIntRect( - GetScrollContainerRelativeContainingBlockRect(constraints))); + constraints.scroll_container_relative_containing_block_rect)); EXPECT_EQ( IntRect(0, 50, 50, 50), - EnclosingIntRect(GetScrollContainerRelativeStickyBoxRect(constraints))); + EnclosingIntRect(constraints.scroll_container_relative_sticky_box_rect)); } // Tests that when a non-layer changes size it invalidates the constraints for @@ -429,11 +419,10 @@ ToLayoutBoxModelObject(GetLayoutObjectByElementId("target")); EXPECT_TRUE( scrollable_area->GetStickyConstraintsMap().Contains(sticky->Layer())); - EXPECT_EQ(25.f, - GetScrollContainerRelativeStickyBoxRect( - scrollable_area->GetStickyConstraintsMap().at(sticky->Layer())) - .Location() - .X()); + EXPECT_EQ(25.f, scrollable_area->GetStickyConstraintsMap() + .at(sticky->Layer()) + .scroll_container_relative_sticky_box_rect.Location() + .X()); ToHTMLElement(target->GetNode())->classList().Add("hide"); GetDocument().View()->UpdateLifecycleToLayoutClean(); // Layout should invalidate the sticky constraints of the sticky element and @@ -444,11 +433,10 @@ // After updating compositing inputs we should have the updated position. GetDocument().View()->UpdateAllLifecyclePhases(); - EXPECT_EQ(50.f, - GetScrollContainerRelativeStickyBoxRect( - scrollable_area->GetStickyConstraintsMap().at(sticky->Layer())) - .Location() - .X()); + EXPECT_EQ(50.f, scrollable_area->GetStickyConstraintsMap() + .at(sticky->Layer()) + .scroll_container_relative_sticky_box_rect.Location() + .X()); } // Verifies that the correct sticky-box shifting ancestor is found when @@ -499,18 +487,18 @@ // The outer block element trivially has no sticky-box shifting ancestor. EXPECT_FALSE(constraints_map.at(sticky_outer_div) - .NearestStickyLayerShiftingStickyBox()); + .nearest_sticky_layer_shifting_sticky_box); // Neither does the outer inline element, as its parent element is also its // containing block. EXPECT_FALSE(constraints_map.at(sticky_outer_inline) - .NearestStickyLayerShiftingStickyBox()); + .nearest_sticky_layer_shifting_sticky_box); // However the inner inline element does have a sticky-box shifting ancestor, // as its containing block is the ancestor block element, above its ancestor // sticky element. EXPECT_EQ(sticky_outer_inline, constraints_map.at(sticky_inner_inline) - .NearestStickyLayerShiftingStickyBox()); + .nearest_sticky_layer_shifting_sticky_box); } // Verifies that the correct containing-block shifting ancestor is found when @@ -556,15 +544,15 @@ // The outer <div> should not detect the scroller as its containing-block // shifting ancestor. EXPECT_FALSE(constraints_map.at(sticky_parent) - .NearestStickyLayerShiftingContainingBlock()); + .nearest_sticky_layer_shifting_containing_block); // Both inner children should detect the parent <div> as their // containing-block shifting ancestor. They skip past unanchored sticky // because it will never have a non-zero offset. EXPECT_EQ(sticky_parent, constraints_map.at(sticky_child) - .NearestStickyLayerShiftingContainingBlock()); + .nearest_sticky_layer_shifting_containing_block); EXPECT_EQ(sticky_parent, constraints_map.at(sticky_nested_child) - .NearestStickyLayerShiftingContainingBlock()); + .nearest_sticky_layer_shifting_containing_block); } // Verifies that the correct containing-block shifting ancestor is found when @@ -596,7 +584,7 @@ // The grandchild sticky should detect the parent as its containing-block // shifting ancestor. EXPECT_EQ(sticky_parent, constraints_map.at(sticky_grandchild) - .NearestStickyLayerShiftingContainingBlock()); + .nearest_sticky_layer_shifting_containing_block); } // Verifies that the correct containing-block shifting ancestor is found when @@ -629,7 +617,7 @@ // The table cell should detect the outer <div> as its containing-block // shifting ancestor. EXPECT_EQ(sticky_outer, constraints_map.at(sticky_th) - .NearestStickyLayerShiftingContainingBlock()); + .nearest_sticky_layer_shifting_containing_block); } // Verifies that the calculated position:sticky offsets are correct when we have @@ -1051,9 +1039,9 @@ // The inner sticky should not detect the outer one as any sort of ancestor. EXPECT_FALSE(constraints_map.at(inner_sticky->Layer()) - .NearestStickyLayerShiftingStickyBox()); + .nearest_sticky_layer_shifting_sticky_box); EXPECT_FALSE(constraints_map.at(inner_sticky->Layer()) - .NearestStickyLayerShiftingContainingBlock()); + .nearest_sticky_layer_shifting_containing_block); // Scroll the page down. scrollable_area->ScrollToAbsolutePosition(
diff --git a/third_party/blink/renderer/core/page/scrolling/sticky_position_scrolling_constraints.cc b/third_party/blink/renderer/core/page/scrolling/sticky_position_scrolling_constraints.cc index 0aae3ee0..4564698 100644 --- a/third_party/blink/renderer/core/page/scrolling/sticky_position_scrolling_constraints.cc +++ b/third_party/blink/renderer/core/page/scrolling/sticky_position_scrolling_constraints.cc
@@ -8,11 +8,11 @@ namespace blink { FloatSize StickyPositionScrollingConstraints::ComputeStickyOffset( - const FloatRect& overflow_clip_rect, + const FloatRect& content_box_rect, const StickyConstraintsMap& constraints_map) { - FloatRect sticky_box_rect = scroll_container_relative_sticky_box_rect_; + FloatRect sticky_box_rect = scroll_container_relative_sticky_box_rect; FloatRect containing_block_rect = - scroll_container_relative_containing_block_rect_; + scroll_container_relative_containing_block_rect; FloatSize ancestor_sticky_box_offset = AncestorStickyBoxOffset(constraints_map); FloatSize ancestor_containing_block_offset = @@ -21,10 +21,10 @@ // Adjust the cached rect locations for any sticky ancestor elements. The // sticky offset applied to those ancestors affects us as follows: // - // 1. |nearest_sticky_layer_shifting_sticky_box_| is a sticky layer between + // 1. |nearest_sticky_layer_shifting_sticky_box| is a sticky layer between // ourselves and our containing block, e.g. a nested inline parent. // It shifts only the sticky_box_rect and not the containing_block_rect. - // 2. |nearest_sticky_layer_shifting_containing_block_| is a sticky layer + // 2. |nearest_sticky_layer_shifting_containing_block| is a sticky layer // between our containing block (inclusive) and our scroll ancestor // (exclusive). As such, it shifts both the sticky_box_rect and the // containing_block_rect. @@ -43,8 +43,8 @@ // As per the spec, 'left' overrides 'right' and 'top' overrides 'bottom'. FloatRect box_rect = sticky_box_rect; - if (HasAnchorEdge(kAnchorEdgeRight)) { - float right_limit = overflow_clip_rect.MaxX() - right_offset_; + if (is_anchored_right) { + float right_limit = content_box_rect.MaxX() - right_offset; float right_delta = std::min<float>(0, right_limit - sticky_box_rect.MaxX()); float available_space = @@ -55,8 +55,8 @@ box_rect.Move(right_delta, 0); } - if (HasAnchorEdge(kAnchorEdgeLeft)) { - float left_limit = overflow_clip_rect.X() + left_offset_; + if (is_anchored_left) { + float left_limit = content_box_rect.X() + left_offset; float left_delta = std::max<float>(0, left_limit - sticky_box_rect.X()); float available_space = std::max<float>( 0, containing_block_rect.MaxX() - sticky_box_rect.MaxX()); @@ -66,8 +66,8 @@ box_rect.Move(left_delta, 0); } - if (HasAnchorEdge(kAnchorEdgeBottom)) { - float bottom_limit = overflow_clip_rect.MaxY() - bottom_offset_; + if (is_anchored_bottom) { + float bottom_limit = content_box_rect.MaxY() - bottom_offset; float bottom_delta = std::min<float>(0, bottom_limit - sticky_box_rect.MaxY()); float available_space = @@ -78,8 +78,8 @@ box_rect.Move(0, bottom_delta); } - if (HasAnchorEdge(kAnchorEdgeTop)) { - float top_limit = overflow_clip_rect.Y() + top_offset_; + if (is_anchored_top) { + float top_limit = content_box_rect.Y() + top_offset; float top_delta = std::max<float>(0, top_limit - sticky_box_rect.Y()); float available_space = std::max<float>( 0, containing_block_rect.MaxY() - sticky_box_rect.MaxY()); @@ -93,44 +93,38 @@ // Now that we have computed our current sticky offset, update the cached // accumulated sticky offsets. - total_sticky_box_sticky_offset_ = ancestor_sticky_box_offset + sticky_offset; - total_containing_block_sticky_offset_ = ancestor_sticky_box_offset + - ancestor_containing_block_offset + - sticky_offset; + total_sticky_box_sticky_offset = ancestor_sticky_box_offset + sticky_offset; + total_containing_block_sticky_offset = ancestor_sticky_box_offset + + ancestor_containing_block_offset + + sticky_offset; return sticky_offset; } FloatSize StickyPositionScrollingConstraints::GetOffsetForStickyPosition( const StickyConstraintsMap& constraints_map) const { - FloatSize nearest_sticky_layer_shifting_sticky_box_constraints_offset; - if (nearest_sticky_layer_shifting_sticky_box_) { - nearest_sticky_layer_shifting_sticky_box_constraints_offset = - constraints_map.at(nearest_sticky_layer_shifting_sticky_box_) - .total_sticky_box_sticky_offset_; - } - return total_sticky_box_sticky_offset_ - - nearest_sticky_layer_shifting_sticky_box_constraints_offset; + return total_sticky_box_sticky_offset - + AncestorStickyBoxOffset(constraints_map); } FloatSize StickyPositionScrollingConstraints::AncestorStickyBoxOffset( - const StickyConstraintsMap& constraints_map) { - if (!nearest_sticky_layer_shifting_sticky_box_) + const StickyConstraintsMap& constraints_map) const { + if (!nearest_sticky_layer_shifting_sticky_box) return FloatSize(); - DCHECK(constraints_map.Contains(nearest_sticky_layer_shifting_sticky_box_)); - return constraints_map.at(nearest_sticky_layer_shifting_sticky_box_) - .total_sticky_box_sticky_offset_; + DCHECK(constraints_map.Contains(nearest_sticky_layer_shifting_sticky_box)); + return constraints_map.at(nearest_sticky_layer_shifting_sticky_box) + .total_sticky_box_sticky_offset; } FloatSize StickyPositionScrollingConstraints::AncestorContainingBlockOffset( - const StickyConstraintsMap& constraints_map) { - if (!nearest_sticky_layer_shifting_containing_block_) { + const StickyConstraintsMap& constraints_map) const { + if (!nearest_sticky_layer_shifting_containing_block) { return FloatSize(); } - DCHECK(constraints_map.Contains( - nearest_sticky_layer_shifting_containing_block_)); - return constraints_map.at(nearest_sticky_layer_shifting_containing_block_) - .total_containing_block_sticky_offset_; + DCHECK( + constraints_map.Contains(nearest_sticky_layer_shifting_containing_block)); + return constraints_map.at(nearest_sticky_layer_shifting_containing_block) + .total_containing_block_sticky_offset; } } // namespace blink
diff --git a/third_party/blink/renderer/core/page/scrolling/sticky_position_scrolling_constraints.h b/third_party/blink/renderer/core/page/scrolling/sticky_position_scrolling_constraints.h index 9712076..42a1494b 100644 --- a/third_party/blink/renderer/core/page/scrolling/sticky_position_scrolling_constraints.h +++ b/third_party/blink/renderer/core/page/scrolling/sticky_position_scrolling_constraints.h
@@ -12,7 +12,7 @@ namespace blink { class PaintLayer; -class StickyPositionScrollingConstraints; +struct StickyPositionScrollingConstraints; typedef WTF::HashMap<PaintLayer*, StickyPositionScrollingConstraints> StickyConstraintsMap; @@ -71,25 +71,13 @@ // already being shifted by its ancestor. To correctly handle such situations we // apply more complicated logic which is explained in the implementation of // |ComputeStickyOffset|. -class StickyPositionScrollingConstraints final { +struct StickyPositionScrollingConstraints final { public: - enum AnchorEdgeFlags { - kAnchorEdgeLeft = 1 << 0, - kAnchorEdgeRight = 1 << 1, - kAnchorEdgeTop = 1 << 2, - kAnchorEdgeBottom = 1 << 3 - }; - typedef unsigned AnchorEdges; - StickyPositionScrollingConstraints() - : anchor_edges_(0), - left_offset_(0), - right_offset_(0), - top_offset_(0), - bottom_offset_(0), - nearest_sticky_layer_shifting_sticky_box_(nullptr), - nearest_sticky_layer_shifting_containing_block_(nullptr) {} - + : is_anchored_left(false), + is_anchored_right(false), + is_anchored_top(false), + is_anchored_bottom(false) {} StickyPositionScrollingConstraints( const StickyPositionScrollingConstraints& other) = default; @@ -97,7 +85,7 @@ // // This method is non-const as we cache internal state for performance; see // documentation in the implementation for details. - FloatSize ComputeStickyOffset(const FloatRect& overflow_clip_rect, + FloatSize ComputeStickyOffset(const FloatRect& content_box_rect, const StickyConstraintsMap&); // Returns the last-computed offset of the sticky box from its original @@ -108,87 +96,15 @@ // element. (Or after prepaint for SlimmingPaintV2). FloatSize GetOffsetForStickyPosition(const StickyConstraintsMap&) const; - bool HasAncestorStickyElement() const { - return nearest_sticky_layer_shifting_sticky_box_ || - nearest_sticky_layer_shifting_containing_block_; - } + bool is_anchored_left : 1; + bool is_anchored_right : 1; + bool is_anchored_top : 1; + bool is_anchored_bottom : 1; - AnchorEdges GetAnchorEdges() const { return anchor_edges_; } - bool HasAnchorEdge(AnchorEdgeFlags flag) const { - return anchor_edges_ & flag; - } - void AddAnchorEdge(AnchorEdgeFlags edge_flag) { anchor_edges_ |= edge_flag; } - - float LeftOffset() const { return left_offset_; } - float RightOffset() const { return right_offset_; } - float TopOffset() const { return top_offset_; } - float BottomOffset() const { return bottom_offset_; } - - void SetLeftOffset(float offset) { left_offset_ = offset; } - void SetRightOffset(float offset) { right_offset_ = offset; } - void SetTopOffset(float offset) { top_offset_ = offset; } - void SetBottomOffset(float offset) { bottom_offset_ = offset; } - - void SetScrollContainerRelativeContainingBlockRect(const FloatRect& rect) { - scroll_container_relative_containing_block_rect_ = rect; - } - const FloatRect& ScrollContainerRelativeContainingBlockRect() const { - return scroll_container_relative_containing_block_rect_; - } - - void SetScrollContainerRelativeStickyBoxRect(const FloatRect& rect) { - scroll_container_relative_sticky_box_rect_ = rect; - } - const FloatRect& ScrollContainerRelativeStickyBoxRect() const { - return scroll_container_relative_sticky_box_rect_; - } - - void SetNearestStickyLayerShiftingStickyBox(PaintLayer* layer) { - nearest_sticky_layer_shifting_sticky_box_ = layer; - } - PaintLayer* NearestStickyLayerShiftingStickyBox() const { - return nearest_sticky_layer_shifting_sticky_box_; - } - - void SetNearestStickyLayerShiftingContainingBlock(PaintLayer* layer) { - nearest_sticky_layer_shifting_containing_block_ = layer; - } - PaintLayer* NearestStickyLayerShiftingContainingBlock() const { - return nearest_sticky_layer_shifting_containing_block_; - } - - bool operator==(const StickyPositionScrollingConstraints& other) const { - return left_offset_ == other.left_offset_ && - right_offset_ == other.right_offset_ && - top_offset_ == other.top_offset_ && - bottom_offset_ == other.bottom_offset_ && - scroll_container_relative_containing_block_rect_ == - other.scroll_container_relative_containing_block_rect_ && - scroll_container_relative_sticky_box_rect_ == - other.scroll_container_relative_sticky_box_rect_ && - nearest_sticky_layer_shifting_sticky_box_ == - other.nearest_sticky_layer_shifting_sticky_box_ && - nearest_sticky_layer_shifting_containing_block_ == - other.nearest_sticky_layer_shifting_containing_block_ && - total_sticky_box_sticky_offset_ == - other.total_sticky_box_sticky_offset_ && - total_containing_block_sticky_offset_ == - other.total_containing_block_sticky_offset_; - } - - bool operator!=(const StickyPositionScrollingConstraints& other) const { - return !(*this == other); - } - - private: - FloatSize AncestorStickyBoxOffset(const StickyConstraintsMap&); - FloatSize AncestorContainingBlockOffset(const StickyConstraintsMap&); - - AnchorEdges anchor_edges_; - float left_offset_; - float right_offset_; - float top_offset_; - float bottom_offset_; + float left_offset = 0.f; + float right_offset = 0.f; + float top_offset = 0.f; + float bottom_offset = 0.f; // The containing block rect and sticky box rect are the basic components // for calculating the sticky offset to apply after a scroll. Consider the @@ -203,12 +119,12 @@ // The layout position of the containing block relative to the scroll // container. When calculating the sticky offset it is used to ensure the // sticky element stays bounded by its containing block. - FloatRect scroll_container_relative_containing_block_rect_; + FloatRect scroll_container_relative_containing_block_rect; // The layout position of the sticky element relative to the scroll container. // When calculating the sticky offset it is used to determine how large the // offset needs to be to satisfy the sticky constraints. - FloatRect scroll_container_relative_sticky_box_rect_; + FloatRect scroll_container_relative_sticky_box_rect; // In the case of nested sticky elements the layout position of the sticky // element and its containing block are not accurate (as they are affected by @@ -219,9 +135,10 @@ // // See the implementation of |ComputeStickyOffset| for documentation on how // these ancestors are used to correct the offset calculation. - PaintLayer* nearest_sticky_layer_shifting_sticky_box_; - PaintLayer* nearest_sticky_layer_shifting_containing_block_; + PaintLayer* nearest_sticky_layer_shifting_sticky_box = nullptr; + PaintLayer* nearest_sticky_layer_shifting_containing_block = nullptr; + private: // For performance we cache our accumulated sticky offset to allow descendant // sticky elements to offset their constraint rects. Because we can either // affect a descendant element's sticky box constraint rect or containing @@ -229,8 +146,8 @@ // The sticky box offset accumulates the chain of sticky elements that are // between this sticky element and its containing block. Any descendant using - // |total_sticky_box_sticky_offset_| has the same containing block as this - // element, so |total_sticky_box_sticky_offset_| does not accumulate + // |total_sticky_box_sticky_offset| has the same containing block as this + // element, so |total_sticky_box_sticky_offset| does not accumulate // containing block sticky offsets. For example, consider the following chain: // // <div style="position: sticky;"> @@ -241,13 +158,16 @@ // // In the above example, both outerInline and innerInline have the same // containing block - the outermost <div>. - FloatSize total_sticky_box_sticky_offset_; + FloatSize total_sticky_box_sticky_offset; // The containing block offset accumulates all sticky-related offsets between // this element and the ancestor scroller. If this element is a containing // block shifting ancestor for some descendant, it shifts the descendant's // constraint rects by its entire offset. - FloatSize total_containing_block_sticky_offset_; + FloatSize total_containing_block_sticky_offset; + + FloatSize AncestorStickyBoxOffset(const StickyConstraintsMap&) const; + FloatSize AncestorContainingBlockOffset(const StickyConstraintsMap&) const; }; } // namespace blink
diff --git a/third_party/blink/renderer/core/paint/BUILD.gn b/third_party/blink/renderer/core/paint/BUILD.gn index c5e9081..d81d34e2 100644 --- a/third_party/blink/renderer/core/paint/BUILD.gn +++ b/third_party/blink/renderer/core/paint/BUILD.gn
@@ -13,8 +13,6 @@ "background_image_geometry.h", "block_flow_paint_invalidator.cc", "block_flow_paint_invalidator.h", - "block_flow_painter.cc", - "block_flow_painter.h", "block_paint_invalidator.cc", "block_paint_invalidator.h", "block_painter.cc",
diff --git a/third_party/blink/renderer/core/paint/block_flow_painter.cc b/third_party/blink/renderer/core/paint/block_flow_painter.cc deleted file mode 100644 index dc29d0a..0000000 --- a/third_party/blink/renderer/core/paint/block_flow_painter.cc +++ /dev/null
@@ -1,62 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "third_party/blink/renderer/core/paint/block_flow_painter.h" - -#include "third_party/blink/renderer/core/layout/floating_objects.h" -#include "third_party/blink/renderer/core/layout/layout_block_flow.h" -#include "third_party/blink/renderer/core/paint/block_painter.h" -#include "third_party/blink/renderer/core/paint/line_box_list_painter.h" -#include "third_party/blink/renderer/core/paint/object_painter.h" -#include "third_party/blink/renderer/core/paint/paint_info.h" - -namespace blink { - -void BlockFlowPainter::PaintContents(const PaintInfo& paint_info, - const LayoutPoint& paint_offset) { - if (paint_info.SuppressPaintingDescendants() && - !layout_block_flow_.IsLayoutView()) { - return; - } - - if (!layout_block_flow_.ChildrenInline()) { - BlockPainter(layout_block_flow_).PaintContents(paint_info, paint_offset); - return; - } - if (ShouldPaintDescendantOutlines(paint_info.phase)) { - ObjectPainter(layout_block_flow_).PaintInlineChildrenOutlines(paint_info); - } else { - LineBoxListPainter(layout_block_flow_.LineBoxes()) - .Paint(layout_block_flow_, paint_info, paint_offset); - } -} - -void BlockFlowPainter::PaintFloats(const PaintInfo& paint_info) { - if (!layout_block_flow_.GetFloatingObjects()) - return; - - DCHECK(paint_info.phase == PaintPhase::kFloat || - paint_info.phase == PaintPhase::kSelection || - paint_info.phase == PaintPhase::kTextClip); - PaintInfo float_paint_info(paint_info); - if (paint_info.phase == PaintPhase::kFloat) - float_paint_info.phase = PaintPhase::kForeground; - - for (const auto& floating_object : - layout_block_flow_.GetFloatingObjects()->Set()) { - if (!floating_object->ShouldPaint()) - continue; - - const LayoutBox* floating_layout_object = - floating_object->GetLayoutObject(); - // TODO(wangxianzhu): Should this be a DCHECK? - if (floating_layout_object->HasSelfPaintingLayer()) - continue; - - ObjectPainter(*floating_layout_object) - .PaintAllPhasesAtomically(float_paint_info); - } -} - -} // namespace blink
diff --git a/third_party/blink/renderer/core/paint/block_flow_painter.h b/third_party/blink/renderer/core/paint/block_flow_painter.h deleted file mode 100644 index 8f8c8e45..0000000 --- a/third_party/blink/renderer/core/paint/block_flow_painter.h +++ /dev/null
@@ -1,31 +0,0 @@ -// Copyright 2014 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_BLOCK_FLOW_PAINTER_H_ -#define THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_BLOCK_FLOW_PAINTER_H_ - -#include "third_party/blink/renderer/platform/wtf/allocator.h" - -namespace blink { - -struct PaintInfo; -class LayoutBlockFlow; -class LayoutPoint; - -class BlockFlowPainter { - STACK_ALLOCATED(); - - public: - BlockFlowPainter(const LayoutBlockFlow& layout_block_flow) - : layout_block_flow_(layout_block_flow) {} - void PaintContents(const PaintInfo&, const LayoutPoint& paint_offset); - void PaintFloats(const PaintInfo&); - - private: - const LayoutBlockFlow& layout_block_flow_; -}; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_BLOCK_FLOW_PAINTER_H_
diff --git a/third_party/blink/renderer/core/paint/block_painter.cc b/third_party/blink/renderer/core/paint/block_painter.cc index 06a127a8..c778fb2 100644 --- a/third_party/blink/renderer/core/paint/block_painter.cc +++ b/third_party/blink/renderer/core/paint/block_painter.cc
@@ -12,8 +12,8 @@ #include "third_party/blink/renderer/core/layout/layout_flexible_box.h" #include "third_party/blink/renderer/core/layout/layout_inline.h" #include "third_party/blink/renderer/core/page/page.h" -#include "third_party/blink/renderer/core/paint/block_flow_painter.h" #include "third_party/blink/renderer/core/paint/box_painter.h" +#include "third_party/blink/renderer/core/paint/line_box_list_painter.h" #include "third_party/blink/renderer/core/paint/object_painter.h" #include "third_party/blink/renderer/core/paint/paint_info.h" #include "third_party/blink/renderer/core/paint/paint_info_with_offset.h" @@ -185,15 +185,36 @@ DISABLE_CFI_PERF void BlockPainter::PaintObject(const PaintInfo& paint_info, const LayoutPoint& paint_offset) { + const PaintPhase paint_phase = paint_info.phase; + // This function implements some of the painting order algorithm (described + // within the description of stacking context, here + // https://www.w3.org/TR/css-position-3/#det-stacking-context). References are + // made below to the step numbers described in that document. + + // If this block has been truncated, early-out here, because it will not be + // displayed. A truncated block occurs when text-overflow: ellipsis is set on + // a block, and there is not enough room to display all elements. The elements + // that don't get shown are "Truncated". if (layout_block_.IsTruncated()) return; - const PaintPhase paint_phase = paint_info.phase; + // If we're *printing* the foreground, paint the URL. + if (paint_phase == PaintPhase::kForeground && paint_info.IsPrinting()) { + ObjectPainter(layout_block_) + .AddPDFURLRectIfNeeded(paint_info, paint_offset); + } + // If we're painting our background (either 1. kBlockBackground - background + // of the current object and non-self-painting descendants, or 2. + // kSelfBlockBackgroundOnly - Paint background of the current object only), + // paint those now. This is steps #1, 2, and 4 of the CSS spec (see above). if (ShouldPaintSelfBlockBackground(paint_phase)) { + // Paint the background if we're visible and this block has a box decoration + // (background, border, appearance, or box shadow). if (layout_block_.StyleRef().Visibility() == EVisibility::kVisible && - layout_block_.HasBoxDecorationBackground()) + layout_block_.HasBoxDecorationBackground()) { layout_block_.PaintBoxDecorationBackground(paint_info, paint_offset); + } if (RuntimeEnabledFeatures::PaintTouchActionRectsEnabled()) RecordHitTestData(paint_info, paint_offset); // Record the scroll hit test after the background so background squashing @@ -201,22 +222,15 @@ // immediately before the background. if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled()) PaintScrollHitTestDisplayItem(paint_info); - // We're done. We don't bother painting any children. - if (paint_phase == PaintPhase::kSelfBlockBackgroundOnly) - return; } - if (paint_phase == PaintPhase::kMask && - layout_block_.StyleRef().Visibility() == EVisibility::kVisible) { - layout_block_.PaintMask(paint_info, paint_offset); - return; - } - - if (paint_phase == PaintPhase::kForeground && paint_info.IsPrinting()) - ObjectPainter(layout_block_) - .AddPDFURLRectIfNeeded(paint_info, paint_offset); - - if (paint_phase != PaintPhase::kSelfOutlineOnly) { + // If we're in any phase except *just* the self (outline or background) or a + // mask, paint children now. This is step #5, 7, 8, and 9 of the CSS spec (see + // above). + if (paint_phase != PaintPhase::kSelfOutlineOnly && + paint_phase != PaintPhase::kSelfBlockBackgroundOnly && + paint_phase != PaintPhase::kMask) { + // Handle scrolling translation. base::Optional<ScopedPaintChunkProperties> scoped_scroll_property; base::Optional<PaintInfo> scrolled_paint_info; if (const auto* fragment = paint_info.FragmentToPaint(layout_block_)) { @@ -238,30 +252,85 @@ } } } - const PaintInfo& contents_paint_info = scrolled_paint_info ? *scrolled_paint_info : paint_info; + // Actually paint the contents. if (layout_block_.IsLayoutBlockFlow()) { - BlockFlowPainter block_flow_painter(ToLayoutBlockFlow(layout_block_)); - block_flow_painter.PaintContents(contents_paint_info, paint_offset); - if (paint_phase == PaintPhase::kFloat || - paint_phase == PaintPhase::kSelection || - paint_phase == PaintPhase::kTextClip) - block_flow_painter.PaintFloats(contents_paint_info); + // All floating descendants will be LayoutBlockFlow objects, and will get + // painted here. That is step #5 of the CSS spec (see above). + PaintBlockFlowContents(contents_paint_info, paint_offset); } else { PaintContents(contents_paint_info, paint_offset); } } + // If we're painting the outline, paint it now. This is step #10 of the CSS + // spec (see above). if (ShouldPaintSelfOutline(paint_phase)) ObjectPainter(layout_block_).PaintOutline(paint_info, paint_offset); + // If we're painting a visible mask, paint it now. (This does not correspond + // to any painting order steps within the CSS spec.) + if (paint_phase == PaintPhase::kMask && + layout_block_.StyleRef().Visibility() == EVisibility::kVisible) { + layout_block_.PaintMask(paint_info, paint_offset); + } + // If the caret's node's layout object's containing block is this block, and - // the paint action is PaintPhaseForeground, then paint the caret. + // the paint action is PaintPhaseForeground, then paint the caret (cursor or + // drag caret). (This does not correspond to any painting order steps within + // the CSS spec.) if (paint_phase == PaintPhase::kForeground && - layout_block_.ShouldPaintCarets()) + layout_block_.ShouldPaintCarets()) { PaintCarets(paint_info, paint_offset); + } +} + +void BlockPainter::PaintBlockFlowContents(const PaintInfo& paint_info, + const LayoutPoint& paint_offset) { + DCHECK(layout_block_.IsLayoutBlockFlow()); + if (layout_block_.IsLayoutView() || + !paint_info.SuppressPaintingDescendants()) { + if (!layout_block_.ChildrenInline()) { + PaintContents(paint_info, paint_offset); + } else if (ShouldPaintDescendantOutlines(paint_info.phase)) { + ObjectPainter(layout_block_).PaintInlineChildrenOutlines(paint_info); + } else { + LineBoxListPainter(ToLayoutBlockFlow(layout_block_).LineBoxes()) + .Paint(layout_block_, paint_info, paint_offset); + } + } + + // If we don't have any floats to paint, or we're in the wrong paint phase, + // then we're done for now. + auto* floating_objects = + ToLayoutBlockFlow(layout_block_).GetFloatingObjects(); + const PaintPhase paint_phase = paint_info.phase; + if (!floating_objects || !(paint_phase == PaintPhase::kFloat || + paint_phase == PaintPhase::kSelection || + paint_phase == PaintPhase::kTextClip)) { + return; + } + + // If we're painting floats (not selections or textclips), change + // the paint phase to foreground. + PaintInfo float_paint_info(paint_info); + if (paint_info.phase == PaintPhase::kFloat) + float_paint_info.phase = PaintPhase::kForeground; + + // Paint all floats. + for (const auto& floating_object : floating_objects->Set()) { + if (!floating_object->ShouldPaint()) + continue; + const LayoutBox* floating_layout_object = + floating_object->GetLayoutObject(); + // TODO(wangxianzhu): Should this be a DCHECK? + if (floating_layout_object->HasSelfPaintingLayer()) + continue; + ObjectPainter(*floating_layout_object) + .PaintAllPhasesAtomically(float_paint_info); + } } void BlockPainter::PaintCarets(const PaintInfo& paint_info,
diff --git a/third_party/blink/renderer/core/paint/block_painter.h b/third_party/blink/renderer/core/paint/block_painter.h index c8f6de4..1bd47cd6 100644 --- a/third_party/blink/renderer/core/paint/block_painter.h +++ b/third_party/blink/renderer/core/paint/block_painter.h
@@ -47,6 +47,7 @@ // called in the background paint phase even if there is no other painted // content. void RecordHitTestData(const PaintInfo&, const LayoutPoint& paint_offset); + void PaintBlockFlowContents(const PaintInfo&, const LayoutPoint&); void PaintCarets(const PaintInfo&, const LayoutPoint& paint_offset); const LayoutBlock& layout_block_;
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 f5f105d..b3351795 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
@@ -351,28 +351,20 @@ constraints_map.at(&owning_layer_); constraint.is_sticky = true; - constraint.is_anchored_left = - constraints.GetAnchorEdges() & - StickyPositionScrollingConstraints::kAnchorEdgeLeft; - constraint.is_anchored_right = - constraints.GetAnchorEdges() & - StickyPositionScrollingConstraints::kAnchorEdgeRight; - constraint.is_anchored_top = - constraints.GetAnchorEdges() & - StickyPositionScrollingConstraints::kAnchorEdgeTop; - constraint.is_anchored_bottom = - constraints.GetAnchorEdges() & - StickyPositionScrollingConstraints::kAnchorEdgeBottom; - constraint.left_offset = constraints.LeftOffset(); - constraint.right_offset = constraints.RightOffset(); - constraint.top_offset = constraints.TopOffset(); - constraint.bottom_offset = constraints.BottomOffset(); + constraint.is_anchored_left = constraints.is_anchored_left; + constraint.is_anchored_right = constraints.is_anchored_right; + constraint.is_anchored_top = constraints.is_anchored_top; + constraint.is_anchored_bottom = constraints.is_anchored_bottom; + constraint.left_offset = constraints.left_offset; + constraint.right_offset = constraints.right_offset; + constraint.top_offset = constraints.top_offset; + constraint.bottom_offset = constraints.bottom_offset; constraint.scroll_container_relative_sticky_box_rect = - RoundedIntRect(constraints.ScrollContainerRelativeStickyBoxRect()); - constraint.scroll_container_relative_containing_block_rect = - RoundedIntRect(constraints.ScrollContainerRelativeContainingBlockRect()); + RoundedIntRect(constraints.scroll_container_relative_sticky_box_rect); + constraint.scroll_container_relative_containing_block_rect = RoundedIntRect( + constraints.scroll_container_relative_containing_block_rect); PaintLayer* sticky_box_shifting_ancestor = - constraints.NearestStickyLayerShiftingStickyBox(); + constraints.nearest_sticky_layer_shifting_sticky_box; if (sticky_box_shifting_ancestor && sticky_box_shifting_ancestor->GetCompositedLayerMapping()) { constraint.nearest_element_shifting_sticky_box = @@ -381,7 +373,7 @@ ->GetElementId(); } PaintLayer* containing_block_shifting_ancestor = - constraints.NearestStickyLayerShiftingContainingBlock(); + constraints.nearest_sticky_layer_shifting_containing_block; if (containing_block_shifting_ancestor && containing_block_shifting_ancestor->GetCompositedLayerMapping()) { constraint.nearest_element_shifting_containing_block =
diff --git a/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h b/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h index fd1b342a..dba8086 100644 --- a/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h +++ b/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.h
@@ -531,7 +531,7 @@ // + overflow_controls_ancestor_clipping_layer_ [OPTIONAL] // | + overflow_controls_host_layer_ [OPTIONAL] // | + layer_for_vertical_scrollbar_ [OPTIONAL] - // | + layer_for_vertical_scrollbar_ [OPTIONAL] + // | + layer_for_horizontal_scrollbar_ [OPTIONAL] // | + layer_for_scroll_corner_ [OPTIONAL] // + decoration_outline_layer_ [OPTIONAL] // The overflow controls may need to be repositioned in the graphics layer
diff --git a/third_party/blink/renderer/core/paint/object_paint_invalidator.cc b/third_party/blink/renderer/core/paint/object_paint_invalidator.cc index 91a228d..d1a31aa0 100644 --- a/third_party/blink/renderer/core/paint/object_paint_invalidator.cc +++ b/third_party/blink/renderer/core/paint/object_paint_invalidator.cc
@@ -322,9 +322,13 @@ if (full_invalidation) return reason; + const LayoutRect invalidation_rect = + UnionRect(new_selection_rect, old_selection_rect); + if (invalidation_rect.IsEmpty()) + return reason; + object_.GetMutableForPainting().SetPartialInvalidationVisualRect( - UnionRect(object_.PartialInvalidationVisualRect(), - UnionRect(new_selection_rect, old_selection_rect))); + UnionRect(object_.PartialInvalidationVisualRect(), invalidation_rect)); return PaintInvalidationReason::kSelection; }
diff --git a/third_party/blink/renderer/core/paint/object_painter.cc b/third_party/blink/renderer/core/paint/object_painter.cc index f5ac9b23..9445e34 100644 --- a/third_party/blink/renderer/core/paint/object_painter.cc +++ b/third_party/blink/renderer/core/paint/object_painter.cc
@@ -113,7 +113,7 @@ } void ObjectPainter::PaintAllPhasesAtomically(const PaintInfo& paint_info) { - // Pass PaintPhaseSelection and PaintPhaseTextClip to the descendants so that + // Pass kSelection and kTextClip to the descendants so that // they will paint for selection and text clip respectively. We don't need // complete painting for these phases. if (paint_info.phase == PaintPhase::kSelection ||
diff --git a/third_party/blink/renderer/core/paint/object_painter.h b/third_party/blink/renderer/core/paint/object_painter.h index be00a33..351c2e5a 100644 --- a/third_party/blink/renderer/core/paint/object_painter.h +++ b/third_party/blink/renderer/core/paint/object_painter.h
@@ -39,9 +39,8 @@ // // It is expected that the caller will call this function independent of the // value of paintInfo.phase, and this function will do atomic paint (for - // PaintPhaseForeground), normal paint (for PaintPhaseSelection and - // PaintPhaseTextClip) or nothing (other paint phases) according to - // paintInfo.phase. + // kForeground), normal paint (for kSelection and kTextClip) or nothing (other + // paint phases) according to paintInfo.phase. void PaintAllPhasesAtomically(const PaintInfo&); const LayoutObject& layout_object_;
diff --git a/third_party/blink/renderer/core/paint/paint_and_raster_invalidation_test.cc b/third_party/blink/renderer/core/paint/paint_and_raster_invalidation_test.cc index 367fbce..e3e4204 100644 --- a/third_party/blink/renderer/core/paint/paint_and_raster_invalidation_test.cc +++ b/third_party/blink/renderer/core/paint/paint_and_raster_invalidation_test.cc
@@ -887,6 +887,34 @@ GetDocument().View()->SetTracksPaintInvalidations(false); } +TEST_P(PaintAndRasterInvalidationTest, ScrollingInvalidatesStickyOffset) { + SetBodyInnerHTML(R"HTML( + <div id="scroller" style="width:300px; height:200px; overflow:scroll"> + <div id="sticky" style="position:sticky; top:50px; + width:50px; height:100px; background:red;"> + <div id="inner" style="width:100px; height:50px; background:red;"> + </div> + </div> + <div style="height:1000px;"></div> + </div> + )HTML"); + + Element* scroller = GetDocument().getElementById("scroller"); + scroller->setScrollTop(100); + + const auto* sticky = GetLayoutObjectByElementId("sticky"); + EXPECT_TRUE(sticky->ShouldCheckForPaintInvalidation()); + EXPECT_EQ(LayoutPoint(0, 50), sticky->FirstFragment().PaintOffset()); + const auto* inner = GetLayoutObjectByElementId("inner"); + EXPECT_EQ(LayoutPoint(0, 50), inner->FirstFragment().PaintOffset()); + + GetDocument().View()->UpdateAllLifecyclePhases(); + + EXPECT_FALSE(sticky->ShouldCheckForPaintInvalidation()); + EXPECT_EQ(LayoutPoint(0, 150), sticky->FirstFragment().PaintOffset()); + EXPECT_EQ(LayoutPoint(0, 150), inner->FirstFragment().PaintOffset()); +} + class PaintInvalidatorTestClient : public EmptyChromeClient { public: void InvalidateRect(const IntRect&) override {
diff --git a/third_party/blink/renderer/core/paint/paint_layer.cc b/third_party/blink/renderer/core/paint/paint_layer.cc index b73a9619..5b03e044 100644 --- a/third_party/blink/renderer/core/paint/paint_layer.cc +++ b/third_party/blink/renderer/core/paint/paint_layer.cc
@@ -351,15 +351,9 @@ } bool PaintLayer::SticksToScroller() const { - if (GetLayoutObject().StyleRef().GetPosition() != EPosition::kSticky) + if (!GetLayoutObject().StyleRef().HasStickyConstrainedPosition()) return false; - if (auto* ancestor_scrollable_area = - AncestorOverflowLayer()->GetScrollableArea()) { - return ancestor_scrollable_area->GetStickyConstraintsMap() - .at(const_cast<PaintLayer*>(this)) - .GetAnchorEdges(); - } - return false; + return AncestorOverflowLayer()->GetScrollableArea(); } bool PaintLayer::FixedToViewport() const {
diff --git a/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc b/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc index adea385..3874f11 100644 --- a/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc +++ b/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc
@@ -509,6 +509,8 @@ void PaintLayerScrollableArea::InvalidatePaintForScrollOffsetChange( bool offset_was_zero) { + InvalidatePaintForStickyDescendants(); + bool requires_paint_invalidation = false; // "background-attachment: local" causes the background of this element to @@ -554,13 +556,9 @@ bool is_root_layer = Layer()->IsRootLayer(); frame_view->InvalidateBackgroundAttachmentFixedDescendants(*GetLayoutBox()); - if (is_root_layer) { - // Some special invalidations for the root layer. - if (frame_view->HasViewportConstrainedObjects()) { - if (!frame_view->InvalidateViewportConstrainedObjects()) - requires_paint_invalidation = true; - } - InvalidatePaintForStickyDescendants(); + if (is_root_layer && frame_view->HasViewportConstrainedObjects() && + !frame_view->InvalidateViewportConstrainedObjects()) { + requires_paint_invalidation = true; } if (requires_paint_invalidation) { @@ -1893,7 +1891,7 @@ void PaintLayerScrollableArea::InvalidatePaintForStickyDescendants() { if (PaintLayerScrollableAreaRareData* d = RareData()) { for (PaintLayer* sticky_layer : d->sticky_constraints_map_.Keys()) - sticky_layer->GetLayoutObject().SetSubtreeShouldDoFullPaintInvalidation(); + sticky_layer->GetLayoutObject().SetShouldCheckForPaintInvalidation(); } }
diff --git a/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h b/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h index b11c19df..4dc348c 100644 --- a/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h +++ b/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.h
@@ -65,7 +65,6 @@ struct PaintInvalidatorContext; class PaintLayer; class ScrollingCoordinator; -class StickyPositionScrollingConstraints; class SubtreeLayoutScope; struct CORE_EXPORT PaintLayerScrollableAreaRareData {
diff --git a/third_party/blink/renderer/core/paint/paint_phase.h b/third_party/blink/renderer/core/paint/paint_phase.h index a4e23b7..c004c6b 100644 --- a/third_party/blink/renderer/core/paint/paint_phase.h +++ b/third_party/blink/renderer/core/paint/paint_phase.h
@@ -49,7 +49,7 @@ kBlockBackground = 0, // // The following two values are added besides the normal - // PaintPhaseBlockBackground to distinguish backgrounds for the object itself + // kBlockBackground to distinguish backgrounds for the object itself // and for descendants, because the two backgrounds are often painted with // different scroll offsets and clips. // @@ -57,8 +57,8 @@ kSelfBlockBackgroundOnly = 1, // Paint backgrounds of non-self-painting descendants only. The painter should // call each non-self-painting child's paint method by passing - // paintInfo.forDescendants() which converts - // PaintPhaseDescendantsBlockBackgroundsOnly to PaintPhaseBlockBackground. + // paintInfo.forDescendants() which converts kDescendantBlockBackgroundsOnly + // to kBlockBackground. kDescendantBlockBackgroundsOnly = 2, // Float phase @@ -79,8 +79,8 @@ kSelfOutlineOnly = 6, // Paint outlines of non-self-painting descendants only. The painter should // call each non-self-painting child's paint method by passing - // paintInfo.forDescendants() which - // converts PaintPhaseDescendantsOutlinesOnly to PaintPhaseBlockOutline. + // paintInfo.forDescendants() which converts kDescendantOutlinesOnly to + // kOutline. kDescendantOutlinesOnly = 7, // The below are auxiliary phases which are used to paint special effects.
diff --git a/third_party/blink/renderer/core/workers/dedicated_worker.cc b/third_party/blink/renderer/core/workers/dedicated_worker.cc index 8ab54b0..369b62dd 100644 --- a/third_party/blink/renderer/core/workers/dedicated_worker.cc +++ b/third_party/blink/renderer/core/workers/dedicated_worker.cc
@@ -74,14 +74,6 @@ return nullptr; } - if (options.name() != "") { - // TODO(asamidoi): Implement 'name' option (https://crbug.com/721219) - context->AddConsoleMessage(ConsoleMessage::Create( - kJSMessageSource, kInfoMessageLevel, - "'name' param in WorkerOptions is not implemented yet. See " - "https://crbug.com/721219 for details.")); - } - // TODO(nhiroki): Remove this flag check once module loading for // DedicatedWorker is enabled by default (https://crbug.com/680046). if (options.type() == "module" && @@ -256,6 +248,10 @@ return context_proxy_->HasPendingActivity() || classic_script_loader_; } +const String DedicatedWorker::Name() const { + return options_.name(); +} + WorkerClients* DedicatedWorker::CreateWorkerClients() { WorkerClients* worker_clients = WorkerClients::Create(); CoreInitializer::GetInstance().ProvideLocalFileSystemToWorker(
diff --git a/third_party/blink/renderer/core/workers/dedicated_worker.h b/third_party/blink/renderer/core/workers/dedicated_worker.h index ad90d378..042df39 100644 --- a/third_party/blink/renderer/core/workers/dedicated_worker.h +++ b/third_party/blink/renderer/core/workers/dedicated_worker.h
@@ -73,6 +73,9 @@ // (via AbstractWorker -> EventTargetWithInlineData -> EventTarget). bool HasPendingActivity() const final; + // Returns the name specified by WorkerOptions. + const String Name() const; + DEFINE_ATTRIBUTE_EVENT_LISTENER(message); void Trace(blink::Visitor*) override;
diff --git a/third_party/blink/renderer/core/workers/dedicated_worker_global_scope.cc b/third_party/blink/renderer/core/workers/dedicated_worker_global_scope.cc index 2831cfa0..ec38d83 100644 --- a/third_party/blink/renderer/core/workers/dedicated_worker_global_scope.cc +++ b/third_party/blink/renderer/core/workers/dedicated_worker_global_scope.cc
@@ -52,10 +52,12 @@ namespace blink { DedicatedWorkerGlobalScope::DedicatedWorkerGlobalScope( + const String& name, std::unique_ptr<GlobalScopeCreationParams> creation_params, DedicatedWorkerThread* thread, base::TimeTicks time_origin) - : WorkerGlobalScope(std::move(creation_params), thread, time_origin) {} + : WorkerGlobalScope(std::move(creation_params), thread, time_origin), + name_(name) {} DedicatedWorkerGlobalScope::~DedicatedWorkerGlobalScope() = default; @@ -84,6 +86,10 @@ new WorkerModuleTreeClient(modulator)); } +const String DedicatedWorkerGlobalScope::name() const { + return name_; +} + void DedicatedWorkerGlobalScope::postMessage(ScriptState* script_state, const ScriptValue& message, Vector<ScriptValue>& transfer,
diff --git a/third_party/blink/renderer/core/workers/dedicated_worker_global_scope.h b/third_party/blink/renderer/core/workers/dedicated_worker_global_scope.h index 9e40d719..02be7b9 100644 --- a/third_party/blink/renderer/core/workers/dedicated_worker_global_scope.h +++ b/third_party/blink/renderer/core/workers/dedicated_worker_global_scope.h
@@ -49,7 +49,8 @@ DEFINE_WRAPPERTYPEINFO(); public: - DedicatedWorkerGlobalScope(std::unique_ptr<GlobalScopeCreationParams>, + DedicatedWorkerGlobalScope(const String& name, + std::unique_ptr<GlobalScopeCreationParams>, DedicatedWorkerThread*, base::TimeTicks time_origin); ~DedicatedWorkerGlobalScope() override; @@ -65,6 +66,8 @@ FetchClientSettingsObjectSnapshot* outside_settings_object, network::mojom::FetchCredentialsMode) override; + const String name() const; + void postMessage(ScriptState*, const ScriptValue& message, Vector<ScriptValue>& transfer, @@ -80,6 +83,9 @@ void Trace(blink::Visitor*) override; DedicatedWorkerObjectProxy& WorkerObjectProxy() const; + + private: + const String name_; }; DEFINE_TYPE_CASTS(DedicatedWorkerGlobalScope,
diff --git a/third_party/blink/renderer/core/workers/dedicated_worker_global_scope.idl b/third_party/blink/renderer/core/workers/dedicated_worker_global_scope.idl index 4ef0ca86..3e8c7eb 100644 --- a/third_party/blink/renderer/core/workers/dedicated_worker_global_scope.idl +++ b/third_party/blink/renderer/core/workers/dedicated_worker_global_scope.idl
@@ -34,6 +34,8 @@ Global=(Worker,DedicatedWorker), Exposed=DedicatedWorker ] interface DedicatedWorkerGlobalScope : WorkerGlobalScope { + [Replaceable] readonly attribute DOMString name; + [CallWith=ScriptState, RaisesException] void postMessage(any message, optional sequence<object> transfer = []); [RuntimeEnabled=PostMessageOptions, CallWith=ScriptState, RaisesException] void postMessage(any message, PostMessageOptions options);
diff --git a/third_party/blink/renderer/core/workers/dedicated_worker_messaging_proxy.cc b/third_party/blink/renderer/core/workers/dedicated_worker_messaging_proxy.cc index 939bd22..c3b6dbf 100644 --- a/third_party/blink/renderer/core/workers/dedicated_worker_messaging_proxy.cc +++ b/third_party/blink/renderer/core/workers/dedicated_worker_messaging_proxy.cc
@@ -193,8 +193,8 @@ std::unique_ptr<WorkerThread> DedicatedWorkerMessagingProxy::CreateWorkerThread() { - return DedicatedWorkerThread::Create(GetExecutionContext(), - WorkerObjectProxy()); + return DedicatedWorkerThread::Create( + worker_object_->Name(), GetExecutionContext(), WorkerObjectProxy()); } } // namespace blink
diff --git a/third_party/blink/renderer/core/workers/dedicated_worker_test.cc b/third_party/blink/renderer/core/workers/dedicated_worker_test.cc index 49f9a65..8101626 100644 --- a/third_party/blink/renderer/core/workers/dedicated_worker_test.cc +++ b/third_party/blink/renderer/core/workers/dedicated_worker_test.cc
@@ -30,7 +30,8 @@ class DedicatedWorkerThreadForTest final : public DedicatedWorkerThread { public: DedicatedWorkerThreadForTest(DedicatedWorkerObjectProxy& worker_object_proxy) - : DedicatedWorkerThread(nullptr /* parent_execution_context*/, + : DedicatedWorkerThread("fake worker name", + nullptr /* parent_execution_context*/, worker_object_proxy) { worker_backing_thread_ = WorkerBackingThread::Create( WebThreadCreationParams(WebThreadType::kTestThread)); @@ -39,7 +40,7 @@ WorkerOrWorkletGlobalScope* CreateWorkerGlobalScope( std::unique_ptr<GlobalScopeCreationParams> creation_params) override { auto* global_scope = new DedicatedWorkerGlobalScope( - std::move(creation_params), this, time_origin_); + "fake worker name", std::move(creation_params), this, time_origin_); // Initializing a global scope with a dummy creation params may emit warning // messages (e.g., invalid CSP directives). Clear them here for tests that // check console messages (i.e., UseCounter tests).
diff --git a/third_party/blink/renderer/core/workers/dedicated_worker_thread.cc b/third_party/blink/renderer/core/workers/dedicated_worker_thread.cc index 4ccb2438..b081cbf0 100644 --- a/third_party/blink/renderer/core/workers/dedicated_worker_thread.cc +++ b/third_party/blink/renderer/core/workers/dedicated_worker_thread.cc
@@ -46,16 +46,19 @@ namespace blink { std::unique_ptr<DedicatedWorkerThread> DedicatedWorkerThread::Create( + const String& name, ExecutionContext* parent_execution_context, DedicatedWorkerObjectProxy& worker_object_proxy) { - return base::WrapUnique( - new DedicatedWorkerThread(parent_execution_context, worker_object_proxy)); + return base::WrapUnique(new DedicatedWorkerThread( + name, parent_execution_context, worker_object_proxy)); } DedicatedWorkerThread::DedicatedWorkerThread( + const String& name, ExecutionContext* parent_execution_context, DedicatedWorkerObjectProxy& worker_object_proxy) : WorkerThread(worker_object_proxy), + name_(name.IsolatedCopy()), worker_object_proxy_(worker_object_proxy) { FrameOrWorkerScheduler* scheduler = parent_execution_context ? parent_execution_context->GetScheduler() @@ -73,7 +76,7 @@ WorkerOrWorkletGlobalScope* DedicatedWorkerThread::CreateWorkerGlobalScope( std::unique_ptr<GlobalScopeCreationParams> creation_params) { - return new DedicatedWorkerGlobalScope(std::move(creation_params), this, + return new DedicatedWorkerGlobalScope(name_, std::move(creation_params), this, time_origin_); }
diff --git a/third_party/blink/renderer/core/workers/dedicated_worker_thread.h b/third_party/blink/renderer/core/workers/dedicated_worker_thread.h index 9bff5cf..01466db 100644 --- a/third_party/blink/renderer/core/workers/dedicated_worker_thread.h +++ b/third_party/blink/renderer/core/workers/dedicated_worker_thread.h
@@ -41,6 +41,7 @@ class CORE_EXPORT DedicatedWorkerThread : public WorkerThread { public: static std::unique_ptr<DedicatedWorkerThread> Create( + const String& name, ExecutionContext* parent_execution_context, DedicatedWorkerObjectProxy&); ~DedicatedWorkerThread() override; @@ -56,7 +57,8 @@ private: friend class DedicatedWorkerThreadForTest; - DedicatedWorkerThread(ExecutionContext* parent_execution_context, + DedicatedWorkerThread(const String& name, + ExecutionContext* parent_execution_context, DedicatedWorkerObjectProxy&); WorkerOrWorkletGlobalScope* CreateWorkerGlobalScope( std::unique_ptr<GlobalScopeCreationParams>) override; @@ -66,6 +68,7 @@ } std::unique_ptr<WorkerBackingThread> worker_backing_thread_; + const String name_; DedicatedWorkerObjectProxy& worker_object_proxy_; };
diff --git a/third_party/blink/renderer/modules/filesystem/file_system_writer.cc b/third_party/blink/renderer/modules/filesystem/file_system_writer.cc index b7e07768..a92da64a 100644 --- a/third_party/blink/renderer/modules/filesystem/file_system_writer.cc +++ b/third_party/blink/renderer/modules/filesystem/file_system_writer.cc
@@ -7,6 +7,7 @@ #include "third_party/blink/renderer/bindings/core/v8/script_promise.h" #include "third_party/blink/renderer/core/dom/dom_exception.h" #include "third_party/blink/renderer/core/fileapi/blob.h" +#include "third_party/blink/renderer/core/fileapi/file_error.h" #include "third_party/blink/renderer/platform/wtf/functional.h" namespace blink { @@ -67,9 +68,7 @@ if (result == base::File::FILE_OK) { pending_operation_->Resolve(); } else { - // TODO(mek): Take actual error code into account. - pending_operation_->Reject( - DOMException::Create(DOMExceptionCode::kAbortError)); + pending_operation_->Reject(FileError::CreateDOMException(result)); } } @@ -78,9 +77,7 @@ if (result == base::File::FILE_OK) { pending_operation_->Resolve(); } else { - // TODO(mek): Take actual error code into account. - pending_operation_->Reject( - DOMException::Create(DOMExceptionCode::kAbortError)); + pending_operation_->Reject(FileError::CreateDOMException(result)); } }
diff --git a/third_party/blink/renderer/modules/vr/navigator_vr.h b/third_party/blink/renderer/modules/vr/navigator_vr.h index 9a6da1b..9841513 100644 --- a/third_party/blink/renderer/modules/vr/navigator_vr.h +++ b/third_party/blink/renderer/modules/vr/navigator_vr.h
@@ -39,8 +39,8 @@ ~NavigatorVR() override; // XR API - // TODO(offenwanger) Should eventually move this out into it's own separate - // Navigator supplement. + // TODO(http://crbug.com/842025) Should eventually move this out into it's own + // separate Navigator supplement. static XR* xr(Navigator&); XR* xr();
diff --git a/third_party/blink/renderer/modules/vr/vr_display.cc b/third_party/blink/renderer/modules/vr/vr_display.cc index f2015ce1..3a73e9a 100644 --- a/third_party/blink/renderer/modules/vr/vr_display.cc +++ b/third_party/blink/renderer/modules/vr/vr_display.cc
@@ -140,7 +140,8 @@ options->immersive = false; // Set in_on_display_activate to true, this will prevent the request present // from being logged. - // TODO(offenwanger): clean up the logging when refactors are complete. + // TODO(http://crbug.com/842025): clean up the logging when refactors are + // complete. device_ptr_->RequestSession( std::move(options), true, WTF::Bind(&VRDisplay::OnNonImmersiveSessionRequestReturned,
diff --git a/third_party/blink/renderer/modules/vr/vr_frame_data.cc b/third_party/blink/renderer/modules/vr/vr_frame_data.cc index dbc8775..d17d973b 100644 --- a/third_party/blink/renderer/modules/vr/vr_frame_data.cc +++ b/third_party/blink/renderer/modules/vr/vr_frame_data.cc
@@ -187,8 +187,6 @@ fov_right = right_eye->FieldOfView(); } else { DCHECK(!left_eye && !right_eye); - // TODO(offenwanger): Look into making the projection matrixes null instead - // of hard coding values. May break some apps. fov_left = fov_right = new VRFieldOfView(45, 45, 45, 45); }
diff --git a/third_party/blink/renderer/modules/webgl/webgl2_rendering_context_base.cc b/third_party/blink/renderer/modules/webgl/webgl2_rendering_context_base.cc index bf7cb5c..690a0193 100644 --- a/third_party/blink/renderer/modules/webgl/webgl2_rendering_context_base.cc +++ b/third_party/blink/renderer/modules/webgl/webgl2_rendering_context_base.cc
@@ -168,6 +168,8 @@ bound_pixel_unpack_buffer_ = nullptr; bound_transform_feedback_buffer_ = nullptr; bound_uniform_buffer_ = nullptr; + bound_atomic_counter_buffer_ = nullptr; + bound_shader_storage_buffer_ = nullptr; current_boolean_occlusion_query_ = nullptr; current_transform_feedback_primitives_written_query_ = nullptr; @@ -197,6 +199,22 @@ bound_indexed_uniform_buffers_.resize(max_uniform_buffer_bindings); max_bound_uniform_buffer_index_ = 0; + if (ContextType() == Platform::kWebGL2ComputeContextType) { + GLint max_atomic_counter_buffer_bindings = 0; + ContextGL()->GetIntegerv(GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS, + &max_atomic_counter_buffer_bindings); + bound_indexed_atomic_counter_buffers_.clear(); + bound_indexed_atomic_counter_buffers_.resize( + max_atomic_counter_buffer_bindings); + + GLint max_shader_storage_buffer_bindings = 0; + ContextGL()->GetIntegerv(GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, + &max_shader_storage_buffer_bindings); + bound_indexed_shader_storage_buffers_.clear(); + bound_indexed_shader_storage_buffers_.resize( + max_shader_storage_buffer_bindings); + } + pack_row_length_ = 0; pack_skip_pixels_ = 0; pack_skip_rows_ = 0; @@ -4662,6 +4680,34 @@ } return WebGLAny(script_state, bound_indexed_uniform_buffers_[index].Get()); + case GL_ATOMIC_COUNTER_BUFFER_BINDING: { + if (ContextType() != Platform::kWebGL2ComputeContextType) { + SynthesizeGLError(GL_INVALID_ENUM, "getIndexedParameter", + "invalid parameter name"); + return ScriptValue::CreateNull(script_state); + } + if (index >= bound_indexed_atomic_counter_buffers_.size()) { + SynthesizeGLError(GL_INVALID_VALUE, "getIndexedParameter", + "index out of range"); + return ScriptValue::CreateNull(script_state); + } + return WebGLAny(script_state, + bound_indexed_atomic_counter_buffers_[index].Get()); + } + case GL_SHADER_STORAGE_BUFFER_BINDING: { + if (ContextType() != Platform::kWebGL2ComputeContextType) { + SynthesizeGLError(GL_INVALID_ENUM, "getIndexedParameter", + "invalid parameter name"); + return ScriptValue::CreateNull(script_state); + } + if (index >= bound_indexed_shader_storage_buffers_.size()) { + SynthesizeGLError(GL_INVALID_VALUE, "getIndexedParameter", + "index out of range"); + return ScriptValue::CreateNull(script_state); + } + return WebGLAny(script_state, + bound_indexed_shader_storage_buffers_[index].Get()); + } case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE: case GL_TRANSFORM_FEEDBACK_BUFFER_START: case GL_UNIFORM_BUFFER_SIZE: @@ -4670,6 +4716,19 @@ ContextGL()->GetInteger64i_v(target, index, &value); return WebGLAny(script_state, value); } + case GL_ATOMIC_COUNTER_BUFFER_SIZE: + case GL_ATOMIC_COUNTER_BUFFER_START: + case GL_SHADER_STORAGE_BUFFER_SIZE: + case GL_SHADER_STORAGE_BUFFER_START: { + if (ContextType() != Platform::kWebGL2ComputeContextType) { + SynthesizeGLError(GL_INVALID_ENUM, "getIndexedParameter", + "invalid parameter name"); + return ScriptValue::CreateNull(script_state); + } + GLint64 value = -1; + ContextGL()->GetInteger64i_v(target, index, &value); + return WebGLAny(script_state, value); + } default: SynthesizeGLError(GL_INVALID_ENUM, "getIndexedParameter", "invalid parameter name"); @@ -5218,6 +5277,8 @@ case GL_PIXEL_UNPACK_BUFFER: case GL_TRANSFORM_FEEDBACK_BUFFER: case GL_UNIFORM_BUFFER: + case GL_ATOMIC_COUNTER_BUFFER: + case GL_SHADER_STORAGE_BUFFER: SynthesizeGLError( GL_INVALID_OPERATION, function_name, "element array buffers can not be bound to a different target"); @@ -5234,6 +5295,8 @@ case GL_PIXEL_UNPACK_BUFFER: case GL_UNIFORM_BUFFER: case GL_TRANSFORM_FEEDBACK_BUFFER: + case GL_ATOMIC_COUNTER_BUFFER: + case GL_SHADER_STORAGE_BUFFER: if (target == GL_ELEMENT_ARRAY_BUFFER) { SynthesizeGLError(GL_INVALID_OPERATION, function_name, "buffers bound to non ELEMENT_ARRAY_BUFFER targets " @@ -5260,6 +5323,13 @@ case GL_TRANSFORM_FEEDBACK_BUFFER: case GL_UNIFORM_BUFFER: return true; + case GL_ATOMIC_COUNTER_BUFFER: + case GL_SHADER_STORAGE_BUFFER: + if (ContextType() != Platform::kWebGL2ComputeContextType) { + SynthesizeGLError(GL_INVALID_ENUM, function_name, "invalid target"); + return false; + } + return true; default: SynthesizeGLError(GL_INVALID_ENUM, function_name, "invalid target"); return false; @@ -5302,6 +5372,12 @@ case GL_UNIFORM_BUFFER: bound_uniform_buffer_ = buffer; break; + case GL_ATOMIC_COUNTER_BUFFER: + bound_atomic_counter_buffer_ = buffer; + break; + case GL_SHADER_STORAGE_BUFFER: + bound_shader_storage_buffer_ = buffer; + break; default: NOTREACHED(); break; @@ -5319,6 +5395,13 @@ case GL_TRANSFORM_FEEDBACK_BUFFER: case GL_UNIFORM_BUFFER: return true; + case GL_ATOMIC_COUNTER_BUFFER: + case GL_SHADER_STORAGE_BUFFER: + if (ContextType() != Platform::kWebGL2ComputeContextType) { + SynthesizeGLError(GL_INVALID_ENUM, function_name, "invalid target"); + return false; + } + return true; default: SynthesizeGLError(GL_INVALID_ENUM, function_name, "invalid target"); return false; @@ -5370,6 +5453,24 @@ max_bound_uniform_buffer_index_ = i; } break; + case GL_ATOMIC_COUNTER_BUFFER: + if (index >= bound_indexed_atomic_counter_buffers_.size()) { + SynthesizeGLError(GL_INVALID_VALUE, function_name, + "index out of range"); + return false; + } + bound_indexed_atomic_counter_buffers_[index] = buffer; + bound_atomic_counter_buffer_ = buffer; + break; + case GL_SHADER_STORAGE_BUFFER: + if (index >= bound_indexed_shader_storage_buffers_.size()) { + SynthesizeGLError(GL_INVALID_VALUE, function_name, + "index out of range"); + return false; + } + bound_indexed_shader_storage_buffers_[index] = buffer; + bound_shader_storage_buffer_ = buffer; + break; default: NOTREACHED(); break; @@ -5731,6 +5832,10 @@ visitor->Trace(bound_transform_feedback_buffer_); visitor->Trace(bound_uniform_buffer_); visitor->Trace(bound_indexed_uniform_buffers_); + visitor->Trace(bound_atomic_counter_buffer_); + visitor->Trace(bound_indexed_atomic_counter_buffers_); + visitor->Trace(bound_shader_storage_buffer_); + visitor->Trace(bound_indexed_shader_storage_buffers_); visitor->Trace(current_boolean_occlusion_query_); visitor->Trace(current_transform_feedback_primitives_written_query_); visitor->Trace(current_elapsed_query_); @@ -5838,6 +5943,22 @@ case GL_UNIFORM_BUFFER: buffer = bound_uniform_buffer_.Get(); break; + case GL_ATOMIC_COUNTER_BUFFER: { + if (ContextType() != Platform::kWebGL2ComputeContextType) { + SynthesizeGLError(GL_INVALID_ENUM, function_name, "invalid target"); + return nullptr; + } + buffer = bound_atomic_counter_buffer_.Get(); + break; + } + case GL_SHADER_STORAGE_BUFFER: { + if (ContextType() != Platform::kWebGL2ComputeContextType) { + SynthesizeGLError(GL_INVALID_ENUM, function_name, "invalid target"); + return nullptr; + } + buffer = bound_shader_storage_buffer_.Get(); + break; + } default: SynthesizeGLError(GL_INVALID_ENUM, function_name, "invalid target"); return nullptr; @@ -5936,6 +6057,10 @@ bound_transform_feedback_buffer_ = nullptr; if (bound_uniform_buffer_ == buffer) bound_uniform_buffer_ = nullptr; + if (bound_atomic_counter_buffer_ == buffer) + bound_atomic_counter_buffer_ = nullptr; + if (bound_shader_storage_buffer_ == buffer) + bound_shader_storage_buffer_ = nullptr; transform_feedback_binding_->UnbindBuffer(buffer);
diff --git a/third_party/blink/renderer/modules/webgl/webgl2_rendering_context_base.h b/third_party/blink/renderer/modules/webgl/webgl2_rendering_context_base.h index 27e18e2..a410ef3 100644 --- a/third_party/blink/renderer/modules/webgl/webgl2_rendering_context_base.h +++ b/third_party/blink/renderer/modules/webgl/webgl2_rendering_context_base.h
@@ -1127,7 +1127,13 @@ TraceWrapperMember<WebGLBuffer> bound_pixel_unpack_buffer_; TraceWrapperMember<WebGLBuffer> bound_transform_feedback_buffer_; TraceWrapperMember<WebGLBuffer> bound_uniform_buffer_; + TraceWrapperMember<WebGLBuffer> bound_atomic_counter_buffer_; + TraceWrapperMember<WebGLBuffer> bound_shader_storage_buffer_; + HeapVector<TraceWrapperMember<WebGLBuffer>> + bound_indexed_atomic_counter_buffers_; + HeapVector<TraceWrapperMember<WebGLBuffer>> + bound_indexed_shader_storage_buffers_; HeapVector<TraceWrapperMember<WebGLBuffer>> bound_indexed_uniform_buffers_; GLint max_transform_feedback_separate_attribs_; size_t max_bound_uniform_buffer_index_;
diff --git a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc index 225606d4..2fd6f8e 100644 --- a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc +++ b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc
@@ -830,7 +830,8 @@ compatible_xr_device_ = xr_device; return ScriptPromise::CastUndefined(script_state); } else { - // TODO(offenwanger): Trigger context loss and recreate on compatible GPU. + // TODO(http://crbug.com/876140) Trigger context loss and recreate on + // compatible GPU. return ScriptPromise::RejectWithDOMException( script_state, DOMException::Create( @@ -1019,7 +1020,8 @@ context_type_(context_type) { DCHECK(context_provider); - // TODO(offenwanger) Make sure this is being created on a compatible adapter. + // TODO(http://crbug.com/876140) Make sure this is being created on a + // compatible adapter. compatible_xr_device_ = static_cast<XRDevice*>(requested_attributes.compatible_xr_device.Get()); @@ -1113,8 +1115,8 @@ DCHECK(!isContextLost()); DCHECK(GetDrawingBuffer()); - // TODO(offenwanger): Check if compatible_xr_device needs to be taken into - // account here. + // TODO(http://crbug.com/876140) Does compatible_xr_device needs to be taken + // into account here? marked_canvas_dirty_ = false; animation_frame_in_progress_ = false; @@ -1574,7 +1576,8 @@ bool WebGLRenderingContextBase::ContextCreatedOnCompatibleAdapter( const XRDevice* device) { - // TODO(offenwanger): Determine if device is compatible with current context. + // TODO(http://crbug.com/876140) Determine if device is compatible with + // current context. return true; } @@ -5444,6 +5447,7 @@ // cause precision lost. So, uploading such video texture to half float or // float texture can not use GPU-GPU path. if (use_copyTextureCHROMIUM) { + DCHECK(Extensions3DUtil::CanUseCopyTextureCHROMIUM(target)); DCHECK_EQ(xoffset, 0); DCHECK_EQ(yoffset, 0); DCHECK_EQ(zoffset, 0); @@ -5458,6 +5462,17 @@ texture->UpdateLastUploadedFrame(frame_metadata); return; } + + // For certain video frame formats (e.g. I420/YUV), if they start on the CPU + // (e.g. video camera frames): upload them to the GPU, do a GPU decode, and + // then copy into the target texture. + if (video->CopyVideoYUVDataToPlatformTexture( + ContextGL(), target, texture->Object(), internalformat, format, + type, level, unpack_premultiply_alpha_, unpack_flip_y_, + already_uploaded_id, frame_metadata_ptr)) { + texture->UpdateLastUploadedFrame(frame_metadata); + return; + } } if (source_image_rect_is_default) { @@ -5477,49 +5492,6 @@ } } - if (use_copyTextureCHROMIUM) { - // Try using an accelerated image buffer, this allows YUV conversion to be - // done on the GPU. - std::unique_ptr<CanvasResourceProvider> resource_provider = - CanvasResourceProvider::Create( - IntSize(video->videoWidth(), video->videoHeight()), - CanvasResourceProvider::kAcceleratedResourceUsage, - SharedGpuContext::ContextProviderWrapper(), - 0 /* msaa_sample_count */, CanvasColorParams(), - CanvasResourceProvider::kDefaultPresentationMode, - nullptr /* canvas_resource_dispatcher */, is_origin_top_left_); - if (resource_provider && resource_provider->IsValid()) { - // The video element paints an RGBA frame into our surface here. By - // using an AcceleratedImageBufferSurface, we enable the WebMediaPlayer - // implementation to do any necessary color space conversion on the GPU - // (though it may still do a CPU conversion and upload the results). - video->PaintCurrentFrame( - resource_provider->Canvas(), - IntRect(0, 0, video->videoWidth(), video->videoHeight()), nullptr, - already_uploaded_id, frame_metadata_ptr); - - // This is a straight GPU-GPU copy, any necessary color space conversion - // was handled in the paintCurrentFrameInContext() call. - - // Note that copyToPlatformTexture no longer allocates the destination - // texture. - TexImage2DBase(target, level, internalformat, video->videoWidth(), - video->videoHeight(), 0, format, type, nullptr); - - if (Extensions3DUtil::CanUseCopyTextureCHROMIUM(target)) { - scoped_refptr<StaticBitmapImage> image = resource_provider->Snapshot(); - if (!!image && - image->CopyToTexture( - ContextGL(), target, texture->Object(), - unpack_premultiply_alpha_, unpack_flip_y_, IntPoint(0, 0), - IntRect(0, 0, video->videoWidth(), video->videoHeight()))) { - texture->UpdateLastUploadedFrame(frame_metadata); - return; - } - } - } - } - scoped_refptr<Image> image = VideoFrameToImage(video, already_uploaded_id, frame_metadata_ptr); if (!image)
diff --git a/third_party/blink/renderer/modules/xr/xr_device.cc b/third_party/blink/renderer/modules/xr/xr_device.cc index 43a1612..cf795d2 100644 --- a/third_party/blink/renderer/modules/xr/xr_device.cc +++ b/third_party/blink/renderer/modules/xr/xr_device.cc
@@ -158,9 +158,10 @@ XRPresentationContext* output_context = options.hasOutputContext() ? options.outputContext() : nullptr; - // TODO(offenwanger): Once device activation is sorted out for WebXR, either - // pass in the value for metrics, or remove the value as soon as legacy API - // has been removed. + // TODO(http://crbug.com/826899) Once device activation is sorted out for + // WebXR, either pass in the correct value for metrics to know whether + // this was triggered by device activation, or remove the value as soon as + // legacy API has been removed. device_ptr_->RequestSession( std::move(session_options), false /* triggered by display activate */, WTF::Bind(&XRDevice::OnRequestSessionReturned, WrapWeakPersistent(this),
diff --git a/third_party/libvpx/README.chromium b/third_party/libvpx/README.chromium index 90bdcb4e..72a3783 100644 --- a/third_party/libvpx/README.chromium +++ b/third_party/libvpx/README.chromium
@@ -5,9 +5,9 @@ License File: source/libvpx/LICENSE Security Critical: yes -Date: Thursday August 16 2018 +Date: Wednesday August 22 2018 Branch: master -Commit: 6c62530c666fc0bcf4385a35a7c49e44c9f38cf5 +Commit: dbcb89be244e03074ee80e7bc6d5c22e6fc5dd79 Description: Contains the sources used to compile libvpx binaries used by Google Chrome and
diff --git a/third_party/libvpx/libvpx_srcs.gni b/third_party/libvpx/libvpx_srcs.gni index e3a4d39..29f2983 100644 --- a/third_party/libvpx/libvpx_srcs.gni +++ b/third_party/libvpx/libvpx_srcs.gni
@@ -268,12 +268,10 @@ "//third_party/libvpx/source/libvpx/vp9/vp9_dx_iface.h", "//third_party/libvpx/source/libvpx/vp9/vp9_iface_common.h", "//third_party/libvpx/source/libvpx/vpx/internal/vpx_codec_internal.h", - "//third_party/libvpx/source/libvpx/vpx/src/svc_encodeframe.c", "//third_party/libvpx/source/libvpx/vpx/src/vpx_codec.c", "//third_party/libvpx/source/libvpx/vpx/src/vpx_decoder.c", "//third_party/libvpx/source/libvpx/vpx/src/vpx_encoder.c", "//third_party/libvpx/source/libvpx/vpx/src/vpx_image.c", - "//third_party/libvpx/source/libvpx/vpx/svc_context.h", "//third_party/libvpx/source/libvpx/vpx/vp8.h", "//third_party/libvpx/source/libvpx/vpx/vp8cx.h", "//third_party/libvpx/source/libvpx/vpx/vp8dx.h", @@ -743,12 +741,10 @@ "//third_party/libvpx/source/libvpx/vp9/vp9_dx_iface.h", "//third_party/libvpx/source/libvpx/vp9/vp9_iface_common.h", "//third_party/libvpx/source/libvpx/vpx/internal/vpx_codec_internal.h", - "//third_party/libvpx/source/libvpx/vpx/src/svc_encodeframe.c", "//third_party/libvpx/source/libvpx/vpx/src/vpx_codec.c", "//third_party/libvpx/source/libvpx/vpx/src/vpx_decoder.c", "//third_party/libvpx/source/libvpx/vpx/src/vpx_encoder.c", "//third_party/libvpx/source/libvpx/vpx/src/vpx_image.c", - "//third_party/libvpx/source/libvpx/vpx/svc_context.h", "//third_party/libvpx/source/libvpx/vpx/vp8.h", "//third_party/libvpx/source/libvpx/vpx/vp8cx.h", "//third_party/libvpx/source/libvpx/vpx/vp8dx.h", @@ -1219,12 +1215,10 @@ "//third_party/libvpx/source/libvpx/vp9/vp9_dx_iface.h", "//third_party/libvpx/source/libvpx/vp9/vp9_iface_common.h", "//third_party/libvpx/source/libvpx/vpx/internal/vpx_codec_internal.h", - "//third_party/libvpx/source/libvpx/vpx/src/svc_encodeframe.c", "//third_party/libvpx/source/libvpx/vpx/src/vpx_codec.c", "//third_party/libvpx/source/libvpx/vpx/src/vpx_decoder.c", "//third_party/libvpx/source/libvpx/vpx/src/vpx_encoder.c", "//third_party/libvpx/source/libvpx/vpx/src/vpx_image.c", - "//third_party/libvpx/source/libvpx/vpx/svc_context.h", "//third_party/libvpx/source/libvpx/vpx/vp8.h", "//third_party/libvpx/source/libvpx/vpx/vp8cx.h", "//third_party/libvpx/source/libvpx/vpx/vp8dx.h", @@ -1590,12 +1584,10 @@ "//third_party/libvpx/source/libvpx/vp9/vp9_dx_iface.h", "//third_party/libvpx/source/libvpx/vp9/vp9_iface_common.h", "//third_party/libvpx/source/libvpx/vpx/internal/vpx_codec_internal.h", - "//third_party/libvpx/source/libvpx/vpx/src/svc_encodeframe.c", "//third_party/libvpx/source/libvpx/vpx/src/vpx_codec.c", "//third_party/libvpx/source/libvpx/vpx/src/vpx_decoder.c", "//third_party/libvpx/source/libvpx/vpx/src/vpx_encoder.c", "//third_party/libvpx/source/libvpx/vpx/src/vpx_image.c", - "//third_party/libvpx/source/libvpx/vpx/svc_context.h", "//third_party/libvpx/source/libvpx/vpx/vp8.h", "//third_party/libvpx/source/libvpx/vpx/vp8cx.h", "//third_party/libvpx/source/libvpx/vpx/vp8dx.h", @@ -1987,12 +1979,10 @@ "//third_party/libvpx/source/libvpx/vp9/vp9_dx_iface.h", "//third_party/libvpx/source/libvpx/vp9/vp9_iface_common.h", "//third_party/libvpx/source/libvpx/vpx/internal/vpx_codec_internal.h", - "//third_party/libvpx/source/libvpx/vpx/src/svc_encodeframe.c", "//third_party/libvpx/source/libvpx/vpx/src/vpx_codec.c", "//third_party/libvpx/source/libvpx/vpx/src/vpx_decoder.c", "//third_party/libvpx/source/libvpx/vpx/src/vpx_encoder.c", "//third_party/libvpx/source/libvpx/vpx/src/vpx_image.c", - "//third_party/libvpx/source/libvpx/vpx/svc_context.h", "//third_party/libvpx/source/libvpx/vpx/vp8.h", "//third_party/libvpx/source/libvpx/vpx/vp8cx.h", "//third_party/libvpx/source/libvpx/vpx/vp8dx.h", @@ -2439,12 +2429,10 @@ "//third_party/libvpx/source/libvpx/vp9/vp9_dx_iface.h", "//third_party/libvpx/source/libvpx/vp9/vp9_iface_common.h", "//third_party/libvpx/source/libvpx/vpx/internal/vpx_codec_internal.h", - "//third_party/libvpx/source/libvpx/vpx/src/svc_encodeframe.c", "//third_party/libvpx/source/libvpx/vpx/src/vpx_codec.c", "//third_party/libvpx/source/libvpx/vpx/src/vpx_decoder.c", "//third_party/libvpx/source/libvpx/vpx/src/vpx_encoder.c", "//third_party/libvpx/source/libvpx/vpx/src/vpx_image.c", - "//third_party/libvpx/source/libvpx/vpx/svc_context.h", "//third_party/libvpx/source/libvpx/vpx/vp8.h", "//third_party/libvpx/source/libvpx/vpx/vp8cx.h", "//third_party/libvpx/source/libvpx/vpx/vp8dx.h", @@ -2819,12 +2807,10 @@ "//third_party/libvpx/source/libvpx/vp9/vp9_dx_iface.h", "//third_party/libvpx/source/libvpx/vp9/vp9_iface_common.h", "//third_party/libvpx/source/libvpx/vpx/internal/vpx_codec_internal.h", - "//third_party/libvpx/source/libvpx/vpx/src/svc_encodeframe.c", "//third_party/libvpx/source/libvpx/vpx/src/vpx_codec.c", "//third_party/libvpx/source/libvpx/vpx/src/vpx_decoder.c", "//third_party/libvpx/source/libvpx/vpx/src/vpx_encoder.c", "//third_party/libvpx/source/libvpx/vpx/src/vpx_image.c", - "//third_party/libvpx/source/libvpx/vpx/svc_context.h", "//third_party/libvpx/source/libvpx/vpx/vp8.h", "//third_party/libvpx/source/libvpx/vpx/vp8cx.h", "//third_party/libvpx/source/libvpx/vpx/vp8dx.h", @@ -3160,12 +3146,10 @@ "//third_party/libvpx/source/libvpx/vp9/vp9_dx_iface.h", "//third_party/libvpx/source/libvpx/vp9/vp9_iface_common.h", "//third_party/libvpx/source/libvpx/vpx/internal/vpx_codec_internal.h", - "//third_party/libvpx/source/libvpx/vpx/src/svc_encodeframe.c", "//third_party/libvpx/source/libvpx/vpx/src/vpx_codec.c", "//third_party/libvpx/source/libvpx/vpx/src/vpx_decoder.c", "//third_party/libvpx/source/libvpx/vpx/src/vpx_encoder.c", "//third_party/libvpx/source/libvpx/vpx/src/vpx_image.c", - "//third_party/libvpx/source/libvpx/vpx/svc_context.h", "//third_party/libvpx/source/libvpx/vpx/vp8.h", "//third_party/libvpx/source/libvpx/vpx/vp8cx.h", "//third_party/libvpx/source/libvpx/vpx/vp8dx.h", @@ -3500,12 +3484,10 @@ "//third_party/libvpx/source/libvpx/vp9/vp9_dx_iface.h", "//third_party/libvpx/source/libvpx/vp9/vp9_iface_common.h", "//third_party/libvpx/source/libvpx/vpx/internal/vpx_codec_internal.h", - "//third_party/libvpx/source/libvpx/vpx/src/svc_encodeframe.c", "//third_party/libvpx/source/libvpx/vpx/src/vpx_codec.c", "//third_party/libvpx/source/libvpx/vpx/src/vpx_decoder.c", "//third_party/libvpx/source/libvpx/vpx/src/vpx_encoder.c", "//third_party/libvpx/source/libvpx/vpx/src/vpx_image.c", - "//third_party/libvpx/source/libvpx/vpx/svc_context.h", "//third_party/libvpx/source/libvpx/vpx/vp8.h", "//third_party/libvpx/source/libvpx/vpx/vp8cx.h", "//third_party/libvpx/source/libvpx/vpx/vp8dx.h",
diff --git a/third_party/libvpx/source/config/vpx_version.h b/third_party/libvpx/source/config/vpx_version.h index d8f4d31..f8af2c1 100644 --- a/third_party/libvpx/source/config/vpx_version.h +++ b/third_party/libvpx/source/config/vpx_version.h
@@ -2,7 +2,7 @@ #define VERSION_MAJOR 1 #define VERSION_MINOR 7 #define VERSION_PATCH 0 -#define VERSION_EXTRA "834-g6c62530c6" +#define VERSION_EXTRA "881-gdbcb89be2" #define VERSION_PACKED ((VERSION_MAJOR<<16)|(VERSION_MINOR<<8)|(VERSION_PATCH)) -#define VERSION_STRING_NOSP "v1.7.0-834-g6c62530c6" -#define VERSION_STRING " v1.7.0-834-g6c62530c6" +#define VERSION_STRING_NOSP "v1.7.0-881-gdbcb89be2" +#define VERSION_STRING " v1.7.0-881-gdbcb89be2"
diff --git a/third_party/zlib/BUILD.gn b/third_party/zlib/BUILD.gn index 69b49ba..b44bda66 100644 --- a/third_party/zlib/BUILD.gn +++ b/third_party/zlib/BUILD.gn
@@ -78,7 +78,7 @@ source_set("zlib_arm_crc32") { visibility = [ ":*" ] - if (!is_ios && !is_chromeos && !is_fuchsia) { + if (is_clang && (!is_ios && !is_chromeos && !is_fuchsia)) { include_dirs = [ "." ] if (is_android) { @@ -97,10 +97,6 @@ "crc32_simd.h", ] - if (!is_win || is_clang) { - cflags_c = [ "-march=armv8-a+crc" ] - } - if (!is_debug) { configs -= [ "//build/config/compiler:default_optimization" ] configs += [ "//build/config/compiler:optimize_speed" ]
diff --git a/third_party/zlib/crc32_simd.c b/third_party/zlib/crc32_simd.c index c20b8eb..03698adf 100644 --- a/third_party/zlib/crc32_simd.c +++ b/third_party/zlib/crc32_simd.c
@@ -160,8 +160,34 @@ * * TODO: implement a version using the PMULL instruction. */ -#include <arm_acle.h> +/* CRC32 intrinsics are #ifdef'ed out of arm_acle.h unless we build with an + * armv8 target, which is incompatible with ThinLTO optimizations on Android. + * (Namely, mixing and matching different module-level targets makes ThinLTO + * warn, and Android defaults to armv7-a. This restriction does not apply to + * function-level `target`s, however.) + * + * Since we only need three crc intrinsics, and since clang's implementation of + * those are just wrappers around compiler builtins, it's simplest to #define + * those builtins directly. If this #define list grows too much (or we depend on + * an intrinsic that isn't a trivial wrapper), we may have to find a better way + * to go about this. + * + * NOTE: clang currently complains that "'+soft-float-abi' is not a recognized + * feature for this target (ignoring feature)." This appears to be a harmless + * bug in clang. + */ +#define __crc32b __builtin_arm_crc32b +#define __crc32d __builtin_arm_crc32d +#define __crc32w __builtin_arm_crc32w + +#if defined(__aarch64__) +#define TARGET_ARMV8_WITH_CRC __attribute__((target("crc"))) +#else +#define TARGET_ARMV8_WITH_CRC __attribute__((target("armv8-a,crc"))) +#endif + +TARGET_ARMV8_WITH_CRC uint32_t ZLIB_INTERNAL armv8_crc32_little(unsigned long crc, const unsigned char *buf, z_size_t len) @@ -202,6 +228,7 @@ return ~c; } +TARGET_ARMV8_WITH_CRC Pos ZLIB_INTERNAL insert_string_arm(deflate_state *const s, const Pos str) { Pos ret;
diff --git a/tools/clang/scripts/update.py b/tools/clang/scripts/update.py index d9a889f..3a4d4b2 100755 --- a/tools/clang/scripts/update.py +++ b/tools/clang/scripts/update.py
@@ -35,7 +35,7 @@ CLANG_REVISION = 'HEAD' # This is incremented when pushing a new build of Clang at the same revision. -CLANG_SUB_REVISION=1 +CLANG_SUB_REVISION=2 PACKAGE_VERSION = "%s-%s" % (CLANG_REVISION, CLANG_SUB_REVISION) @@ -307,18 +307,6 @@ f.write('endif (CHROMIUM_TOOLS_SRC)\n') -def DownloadHostGcc(args): - """Downloads gcc 4.8.5 and makes sure args.gcc_toolchain is set.""" - if not sys.platform.startswith('linux') or args.gcc_toolchain: - return - gcc_dir = os.path.join(LLVM_BUILD_TOOLS_DIR, 'gcc485precise') - if not os.path.exists(gcc_dir): - print 'Downloading pre-built GCC 4.8.5...' - DownloadAndUnpack( - CDS_URL + '/tools/gcc485precise.tgz', LLVM_BUILD_TOOLS_DIR) - args.gcc_toolchain = gcc_dir - - def AddSvnToPathOnWin(): """Download svn.exe and add it to PATH.""" if sys.platform != 'win32': @@ -501,7 +489,6 @@ print 'Removing old lib dir: %s' % old_lib_dir RmTree(old_lib_dir) - DownloadHostGcc(args) AddCMakeToPath(args) AddGnuWinToPath() @@ -514,21 +501,6 @@ cc, cxx = None, None libstdcpp = None - if args.gcc_toolchain: # This option is only used on Linux. - # Use the specified gcc installation for building. - cc = os.path.join(args.gcc_toolchain, 'bin', 'gcc') - cxx = os.path.join(args.gcc_toolchain, 'bin', 'g++') - - if not os.access(cc, os.X_OK): - print 'Invalid --gcc-toolchain: "%s"' % args.gcc_toolchain - print '"%s" does not appear to be valid.' % cc - return 1 - - # Set LD_LIBRARY_PATH to make auxiliary targets (tablegen, bootstrap - # compiler, etc.) find the .so. - libstdcpp = subprocess.check_output( - [cxx, '-print-file-name=libstdc++.so.6']).rstrip() - os.environ['LD_LIBRARY_PATH'] = os.path.dirname(libstdcpp) cflags = [] cxxflags = [] @@ -578,11 +550,6 @@ cc = os.path.join(LLVM_BOOTSTRAP_INSTALL_DIR, 'bin', 'clang') cxx = os.path.join(LLVM_BOOTSTRAP_INSTALL_DIR, 'bin', 'clang++') - if args.gcc_toolchain: - # Tell the bootstrap compiler to use a specific gcc prefix to search - # for standard library headers and shared object files. - cflags = ['--gcc-toolchain=' + args.gcc_toolchain] - cxxflags = ['--gcc-toolchain=' + args.gcc_toolchain] print 'Building final compiler' # LLVM uses C++11 starting in llvm 3.5. On Linux, this means libstdc++4.7+ is
diff --git a/tools/determinism/compare_build_artifacts.py b/tools/determinism/compare_build_artifacts.py index c7eab3e..db69ae44 100755 --- a/tools/determinism/compare_build_artifacts.py +++ b/tools/determinism/compare_build_artifacts.py
@@ -81,6 +81,10 @@ for inner_file in files: ret_files.add(os.path.join(root, inner_file)) + # Also add any .isolated files that exist. + for isolated in glob.glob(os.path.join(build_dir, '*.isolated')): + ret_files.add(isolated) + # Convert back to a relpath since that's what the caller is expecting. return set(os.path.relpath(f, build_dir) for f in ret_files)
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl index 40da997..1482505 100644 --- a/tools/mb/mb_config.pyl +++ b/tools/mb/mb_config.pyl
@@ -526,7 +526,15 @@ 'android_optional_gpu_tests_rel': 'gpu_tests_android_release_trybot_arm64', 'android_unswarmed_pixel_aosp': 'android_debug_trybot_arm64', 'cast_shell_android': 'android_cast_debug_static_bot_compile_only', + 'gpu-manual-try-android-l-nexus-5-32': 'android_release_trybot', + 'gpu-manual-try-android-l-nexus-6-32': 'android_release_trybot', + 'gpu-manual-try-android-m-nexus-6p-64': 'android_release_trybot_arm64', + 'gpu-manual-try-android-m-nexus-9-64': 'android_release_trybot_arm64', + 'gpu-manual-try-android-n-nvidia-shield-tv-64': 'android_release_trybot_arm64', 'gpu-manual-try-android-p-pixel-2-32': 'gpu_tests_android_vulkan_release_trybot', + 'gpu-manual-try-android-p-pixel-2-32-deqp': 'deqp_android_vulkan_release_trybot', + 'gpu-manual-try-android-p-pixel-2-64': 'gpu_tests_android_vulkan_release_trybot_arm64', + 'gpu-manual-try-android-p-pixel-2-64-deqp': 'deqp_android_vulkan_release_trybot_arm64', 'linux_android_dbg_ng': 'android_debug_trybot', },
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index 17279d7..dcc5612 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -14241,6 +14241,7 @@ <int value="464" label="WebRtcEventLogCollectionAllowed"/> <int value="465" label="PowerSmartDimEnabled"/> <int value="466" label="CoalesceH2ConnectionsWithClientCertificatesForHosts"/> + <int value="467" label="NetBiosDiscoveryEnabled"/> </enum> <enum name="EnterprisePolicyInvalidations"> @@ -49109,6 +49110,142 @@ <int value="1" label="Failure"/> </enum> +<enum name="VideoCaptureError"> + <int value="0" label="kNone"/> + <int value="1" + label="kVideoCaptureControllerInvalidOrUnsupportedVideoCaptureParametersRequested"/> + <int value="2" label="kVideoCaptureControllerIsAlreadyInErrorState"/> + <int value="3" label="kVideoCaptureManagerDeviceConnectionLost"/> + <int value="4" label="kFrameSinkVideoCaptureDeviceAleradyEndedOnFatalError"/> + <int value="5" label="kFrameSinkVideoCaptureDeviceEncounteredFatalError"/> + <int value="6" label="kV4L2FailedToOpenV4L2DeviceDriverFile"/> + <int value="7" label="kV4L2ThisIsNotAV4L2VideoCaptureDevice"/> + <int value="8" label="kV4L2FailedToFindASupportedCameraFormat"/> + <int value="9" label="kV4L2FailedToSetVideoCaptureFormat"/> + <int value="10" label="kV4L2UnsupportedPixelFormat"/> + <int value="11" label="kV4L2FailedToSetCameraFramerate"/> + <int value="12" label="kV4L2ErrorRequestingMmapBuffers"/> + <int value="13" label="kV4L2AllocateBufferFailed"/> + <int value="14" label="kV4L2VidiocStreamonFailed"/> + <int value="15" label="kV4L2VidiocStreamoffFailed"/> + <int value="16" label="kV4L2FailedToVidiocReqbufsWithCount0"/> + <int value="17" label="kV4L2PollFailed"/> + <int value="18" label="kV4L2MultipleContinuousTimeoutsWhileReadPolling"/> + <int value="19" label="kV4L2FailedToDequeueCaptureBuffer"/> + <int value="20" label="kV4L2FailedToEnqueueCaptureBuffer"/> + <int value="21" label="kSingleClientVideoCaptureHostLostConnectionToDevice"/> + <int value="22" label="kSingleClientVideoCaptureDeviceLaunchAborted"/> + <int value="23" label="kDesktopCaptureDeivceWebrtcDesktopCapturerHasFailed"/> + <int value="24" label="kFileVideoCaptureDeviceCouldNotOpenVideoFile"/> + <int value="25" + label="kDeviceCaptureLinuxFailedToCreateVideoCaptureDelegate"/> + <int value="26" label="kErrorFakeDeviceIntentionallyEmittingErrorEvent"/> + <int value="27" label="kDeviceClientTooManyFramesDropped"/> + <int value="28" label="kDeviceClientTooManyFramesDroppedY16"/> + <int value="29" + label="kDeviceMediaToMojoAdapterEncounteredUnsupportedBufferType"/> + <int value="30" + label="kVideoCaptureManagerProcessDeviceStartQueueDeviceInfoNotFound"/> + <int value="31" label="kInProcessDeviceLauncherFailedToCreateDeviceInstance"/> + <int value="32" + label="kServiceDeviceLauncherLostConnectionToDeviceFactoryDuringDeviceStart"/> + <int value="33" + label="kServiceDeviceLauncherServiceRespondedWithDeviceNotFound"/> + <int value="34" + label="kServiceDeviceLauncherConnectionLostWhileWaitingForCallback"/> + <int value="35" label="kIntentionalErrorRaisedByUnitTest"/> + <int value="36" label="kCrosHalV3FailedToStartDeviceThread"/> + <int value="37" label="kCrosHalV3DeviceDelegateMojoConnectionError"/> + <int value="38" label="kCrosHalV3DeviceDelegateFailedToGetCameraInfo"/> + <int value="39" label="kCrosHalV3DeviceDelegateMissingSensorOrientationInfo"/> + <int value="40" label="kCrosHalV3DeviceDelegateFailedToOpenCameraDevice"/> + <int value="41" + label="kCrosHalV3DeviceDelegateFailedToInitializeCameraDevice"/> + <int value="42" label="kCrosHalV3DeviceDelegateFailedToConfigureStreams"/> + <int value="43" + label="kCrosHalV3DeviceDelegateWrongNumberOfStreamsConfigured"/> + <int value="44" + label="kCrosHalV3DeviceDelegateFailedToGetDefaultRequestSettings"/> + <int value="45" label="kCrosHalV3BufferManagerHalRequestedTooManyBuffers"/> + <int value="46" label="kCrosHalV3BufferManagerFailedToCreateGpuMemoryBuffer"/> + <int value="47" label="kCrosHalV3BufferManagerFailedToMapGpuMemoryBuffer"/> + <int value="48" label="kCrosHalV3BufferManagerUnsupportedVideoPixelFormat"/> + <int value="49" label="kCrosHalV3BufferManagerFailedToDupFd"/> + <int value="50" label="kCrosHalV3BufferManagerFailedToWrapGpuMemoryHandle"/> + <int value="51" label="kCrosHalV3BufferManagerFailedToRegisterBuffer"/> + <int value="52" label="kCrosHalV3BufferManagerProcessCaptureRequestFailed"/> + <int value="53" label="kCrosHalV3BufferManagerInvalidPendingResultId"/> + <int value="54" + label="kCrosHalV3BufferManagerReceivedDuplicatedPartialMetadata"/> + <int value="55" + label="kCrosHalV3BufferManagerIncorrectNumberOfOutputBuffersReceived"/> + <int value="56" + label="kCrosHalV3BufferManagerInvalidTypeOfOutputBuffersReceived"/> + <int value="57" + label="kCrosHalV3BufferManagerReceivedMultipleResultBuffersForFrame"/> + <int value="58" + label="kCrosHalV3BufferManagerUnknownStreamInCamera3NotifyMsg"/> + <int value="59" label="kCrosHalV3BufferManagerReceivedInvalidShutterTime"/> + <int value="60" label="kCrosHalV3BufferManagerFatalDeviceError"/> + <int value="61" label="kCrosHalV3BufferManagerReceivedFrameIsOutOfOrder"/> + <int value="62" label="kCrosHalV3BufferManagerFailedToUnwrapReleaseFenceFd"/> + <int value="63" + label="kCrosHalV3BufferManagerSyncWaitOnReleaseFenceTimedOut"/> + <int value="64" label="kCrosHalV3BufferManagerInvalidJpegBlob"/> + <int value="65" label="kAndroidFailedToAllocate"/> + <int value="66" label="kAndroidFailedToStartCapture"/> + <int value="67" label="kAndroidFailedToStopCapture"/> + <int value="68" label="kAndroidApi1CameraErrorCallbackReceived"/> + <int value="69" label="kAndroidApi2CameraDeviceErrorReceived"/> + <int value="70" label="kAndroidApi2CaptureSessionConfigureFailed"/> + <int value="71" label="kAndroidApi2ImageReaderUnexpectedImageFormat"/> + <int value="72" label="kAndroidApi2ImageReaderSizeDidNotMatchImageSize"/> + <int value="73" label="kAndroidApi2ErrorRestartingPreview"/> + <int value="74" label="kAndroidScreenCaptureUnsupportedFormat"/> + <int value="75" label="kAndroidScreenCaptureFailedToStartCaptureMachine"/> + <int value="76" label="kAndroidScreenCaptureTheUserDeniedScreenCapture"/> + <int value="77" label="kAndroidScreenCaptureFailedToStartScreenCapture"/> + <int value="78" label="kWinDirectShowCantGetCaptureFormatSettings"/> + <int value="79" label="kWinDirectShowFailedToGetNumberOfCapabilities"/> + <int value="80" label="kWinDirectShowFailedToGetCaptureDeviceCapabilities"/> + <int value="81" label="kWinDirectShowFailedToSetCaptureDeviceOutputFormat"/> + <int value="82" label="kWinDirectShowFailedToConnectTheCaptureGraph"/> + <int value="83" label="kWinDirectShowFailedToPauseTheCaptureDevice"/> + <int value="84" label="kWinDirectShowFailedToStartTheCaptureDevice"/> + <int value="85" label="kWinDirectShowFailedToStopTheCaptureGraph"/> + <int value="86" label="kWinMediaFoundationEngineIsNull"/> + <int value="87" label="kWinMediaFoundationEngineGetSourceFailed"/> + <int value="88" label="kWinMediaFoundationFillPhotoCapabilitiesFailed"/> + <int value="89" label="kWinMediaFoundationFillVideoCapabilitiesFailed"/> + <int value="90" label="kWinMediaFoundationNoVideoCapabilityFound"/> + <int value="91" label="kWinMediaFoundationGetAvailableDeviceMediaTypeFailed"/> + <int value="92" label="kWinMediaFoundationSetCurrentDeviceMediaTypeFailed"/> + <int value="93" label="kWinMediaFoundationEngineGetSinkFailed"/> + <int value="94" + label="kWinMediaFoundationSinkQueryCapturePreviewInterfaceFailed"/> + <int value="95" label="kWinMediaFoundationSinkRemoveAllStreamsFailed"/> + <int value="96" label="kWinMediaFoundationCreateSinkVideoMediaTypeFailed"/> + <int value="97" label="kWinMediaFoundationConvertToVideoSinkMediaTypeFailed"/> + <int value="98" label="kWinMediaFoundationSinkAddStreamFailed"/> + <int value="99" label="kWinMediaFoundationSinkSetSampleCallbackFailed"/> + <int value="100" label="kWinMediaFoundationEngineStartPreviewFailed"/> + <int value="101" label="kWinMediaFoundationGetMediaEventStatusFailed"/> + <int value="102" label="kMacSetCaptureDeviceFailed"/> + <int value="103" label="kMacCouldNotStartCaptureDevice"/> + <int value="104" label="kMacReceivedFrameWithUnexpectedResolution"/> + <int value="105" label="kMacUpdateCaptureResolutionFailed"/> + <int value="106" label="kMacDeckLinkDeviceIdNotFoundInTheSystem"/> + <int value="107" label="kMacDeckLinkErrorQueryingInputInterface"/> + <int value="108" label="kMacDeckLinkErrorCreatingDisplayModeIterator"/> + <int value="109" label="kMacDeckLinkCouldNotFindADisplayMode"/> + <int value="110" label="kMacDeckLinkCouldNotSelectTheVideoFormatWeLike"/> + <int value="111" label="kMacDeckLinkCouldNotStartCapturing"/> + <int value="112" label="kMacDeckLinkUnsupportedPixelFormat"/> + <int value="113" + label="kMacAvFoundationReceivedAVCaptureSessionRuntimeErrorNotification"/> + <int value="114" label="kAndroidApi2ErrorConfiguringCamera"/> +</enum> + <enum name="VideoCaptureEvent"> <int value="0" label="Starting video capture"/> <int value="1" label="Stopping video capture normally"/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 05f32424..720859e 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -3079,6 +3079,17 @@ </summary> </histogram> +<histogram name="Apps.AppListSuggestedChipLaunched" units="indices" + expires_after="2019-09-01"> + <owner>newcomer@chromium.org</owner> + <owner>charleszhao@chromium.org</owner> + <summary> + The number of times suggested chips are launched at each suggested-apps + tile. An index i, ranged from 0 to kNumStartPageTiles - 1, is logged each + time a suggested chip is launched from i-th tile. + </summary> +</histogram> + <histogram name="Apps.AppListTimeToDiscover" units="ms"> <owner>tapted@chromium.org</owner> <summary> @@ -43546,6 +43557,17 @@ </summary> </histogram> +<histogram name="Media.VideoCapture.Error" enum="VideoCaptureError"> + <owner>chfremer@chromium.org</owner> + <summary> + Breaks down the events counted in Media.VideoCaptureManager.Event bucket + "Stopping video capture due to error" by the origin of the error. + This allows narrowing down what is causing errors. An event for this + histogram is emitted once for each time a client disconnects from a video + capture session because the session has reported an error. + </summary> +</histogram> + <histogram name="Media.VideoCapture.FrameRate" units="fps"> <owner>mcasas@chromium.org</owner> <summary> @@ -68875,6 +68897,7 @@ <histogram name="PageLoad.Experimental.InputTiming.InputToNavigationStart" units="ms" expires_after="2019-08-22"> <owner>sullivan@chromium.org</owner> + <owner>tdresser@chromium.org</owner> <summary> The time between the OS-level input event that initiated a navigation, and the navigation actually starting. @@ -68885,12 +68908,35 @@ name="PageLoad.Experimental.InputTiming.InputToNavigationStart.Background" units="ms" expires_after="2019-08-22"> <owner>sullivan@chromium.org</owner> + <owner>tdresser@chromium.org</owner> <summary> The time between the OS-level input event that initiated a navigation, and the navigation actually starting, for background loads. </summary> </histogram> +<histogram + name="PageLoad.Experimental.InputTiming.InputToNavigationStart.FromLinkClick" + units="ms" expires_after="2019-08-22"> + <owner>sullivan@chromium.org</owner> + <owner>tdresser@chromium.org</owner> + <summary> + The time between the OS-level click/tap event and navigation start, for + clicks on links in the renderer. + </summary> +</histogram> + +<histogram + name="PageLoad.Experimental.InputTiming.InputToNavigationStart.FromOmnibox" + units="ms" expires_after="2019-08-22"> + <owner>sullivan@chromium.org</owner> + <owner>tdresser@chromium.org</owner> + <summary> + The time between the OS-level keypress/tap event in the omnibox and + navigation start, for navigations from the omnibox. + </summary> +</histogram> + <histogram name="PageLoad.Experimental.NavigationToInteractive" units="ms"> <owner>dproy@chromium.org</owner> <owner>tdresser@chromium.org</owner>
diff --git a/tools/perf/benchmarks/loading.py b/tools/perf/benchmarks/loading.py index 61caa2c..9de446e 100644 --- a/tools/perf/benchmarks/loading.py +++ b/tools/perf/benchmarks/loading.py
@@ -18,11 +18,6 @@ options = {'pageset_repeat': 2} - def SetExtraBrowserOptions(self, options): - options.AppendExtraBrowserArgs([ - '--enable-features=TracingPerfettoBackend', - ]) - def CreateCoreTimelineBasedMeasurementOptions(self): tbm_options = timeline_based_measurement.Options() loading_metrics_category.AugmentOptionsForLoadingMetrics(tbm_options)
diff --git a/tools/perf/core/perf_benchmark.py b/tools/perf/core/perf_benchmark.py index 77722d2..7a8ba55 100644 --- a/tools/perf/core/perf_benchmark.py +++ b/tools/perf/core/perf_benchmark.py
@@ -104,6 +104,12 @@ # with the test results. options.AppendExtraBrowserArgs( '--disable-gpu-process-for-dx12-vulkan-info-collection') + + # Switch Chrome to use Perfetto instead of TraceLog as the tracing backend, + # needed until the feature gets turned on by default everywhere. + if options.browser_type != 'reference': + options.AppendExtraBrowserArgs( + '--enable-features=TracingPerfettoBackend') self.SetExtraBrowserOptions(options) @staticmethod
diff --git a/tools/perf/page_sets/rendering/top_real_world_desktop.py b/tools/perf/page_sets/rendering/top_real_world_desktop.py index 62243e6f..cb48c5a2 100644 --- a/tools/perf/page_sets/rendering/top_real_world_desktop.py +++ b/tools/perf/page_sets/rendering/top_real_world_desktop.py
@@ -2,6 +2,7 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. from telemetry.page import shared_page_state +from telemetry.util import wpr_modes from page_sets.login_helpers import google_login from page_sets.login_helpers import linkedin_login @@ -210,7 +211,8 @@ extra_browser_args=extra_browser_args) def RunNavigateSteps(self, action_runner): - linkedin_login.LoginDesktopAccount(action_runner, 'linkedin') + if self.wpr_mode != wpr_modes.WPR_REPLAY: + linkedin_login.LoginDesktopAccount(action_runner, 'linkedin') super(Linkedin2018Page, self).RunNavigateSteps(action_runner) @@ -324,7 +326,8 @@ URL = 'https://mail.google.com/mail/' def RunNavigateSteps(self, action_runner): - google_login.NewLoginGoogleAccount(action_runner, 'googletest') + if self.wpr_mode != wpr_modes.WPR_REPLAY: + google_login.NewLoginGoogleAccount(action_runner, 'googletest') super(Gmail2018SmoothPage, self).RunNavigateSteps(action_runner) action_runner.WaitForJavaScriptCondition( 'window.gmonkey !== undefined &&' @@ -349,7 +352,8 @@ URL='https://www.google.com/calendar/' def RunNavigateSteps(self, action_runner): - google_login.NewLoginGoogleAccount(action_runner, 'googletest') + if self.wpr_mode != wpr_modes.WPR_REPLAY: + google_login.NewLoginGoogleAccount(action_runner, 'googletest') super(GoogleCalendar2018SmoothPage, self).RunNavigateSteps(action_runner) action_runner.WaitForElement('span[class~="sm8sCf"]') action_runner.ExecuteJavaScript("""
diff --git a/ui/android/java/res/OWNERS b/ui/android/java/res/OWNERS new file mode 100644 index 0000000..4258df9 --- /dev/null +++ b/ui/android/java/res/OWNERS
@@ -0,0 +1,15 @@ +# This restriction is in place to avoid accidential addition to our top level +# layout files, such as add duplicated assets, or introducing new colors when +# we don't want them. +set noparent + +bauerb@chromium.org +dtrainor@chromium.org +huayinz@chromium.org +mdjones@chromium.org +tedchoc@chromium.org +twellington@chromium.org +yusufo@chromium.org + +# COMPONENT: UI>Browser>Mobile +# OS: Android
diff --git a/ui/aura/window_event_dispatcher.cc b/ui/aura/window_event_dispatcher.cc index 2473091..46ebe7f 100644 --- a/ui/aura/window_event_dispatcher.cc +++ b/ui/aura/window_event_dispatcher.cc
@@ -861,7 +861,7 @@ } void WindowEventDispatcher::PostSynthesizeMouseMove() { - if (synthesize_mouse_move_) + if (synthesize_mouse_move_ || in_shutdown_) return; synthesize_mouse_move_ = true; base::ThreadTaskRunnerHandle::Get()->PostNonNestableTask( @@ -873,6 +873,8 @@ void WindowEventDispatcher::SynthesizeMouseMoveAfterChangeToWindow( Window* window) { + if (in_shutdown_) + return; if (window->IsVisible() && window->ContainsPointInRoot(GetLastMouseLocationInRoot())) { PostSynthesizeMouseMove(); @@ -881,7 +883,7 @@ ui::EventDispatchDetails WindowEventDispatcher::SynthesizeMouseMoveEvent() { DispatchDetails details; - if (!synthesize_mouse_move_) + if (!synthesize_mouse_move_ || in_shutdown_) return details; synthesize_mouse_move_ = false;
diff --git a/ui/aura/window_event_dispatcher.h b/ui/aura/window_event_dispatcher.h index 187c1b5..5a9e099 100644 --- a/ui/aura/window_event_dispatcher.h +++ b/ui/aura/window_event_dispatcher.h
@@ -64,6 +64,7 @@ WindowEventDispatcher(WindowTreeHost* host, bool are_events_in_pixels); ~WindowEventDispatcher() override; + // Stops dispatching/synthesizing mouse events. void Shutdown(); WindowTreeHost* host() { return host_; }
diff --git a/ui/aura/window_event_dispatcher_unittest.cc b/ui/aura/window_event_dispatcher_unittest.cc index 70316fa..a2d54866 100644 --- a/ui/aura/window_event_dispatcher_unittest.cc +++ b/ui/aura/window_event_dispatcher_unittest.cc
@@ -940,6 +940,31 @@ recorder.mouse_locations()[0].ToString()); } +// Tests that a mouse-exit event is not synthesized during shutdown. +TEST_P(WindowEventDispatcherTest, NoMouseExitInShutdown) { + EventFilterRecorder recorder; + test::TestWindowDelegate delegate; + std::unique_ptr<aura::Window> window(CreateTestWindowWithDelegate( + &delegate, 1, gfx::Rect(10, 10, 50, 50), root_window())); + window->Show(); + window->AddPreTargetHandler(&recorder); + + // Simulate mouse move into the window. + const gfx::Point event_location = window->bounds().CenterPoint(); + ui::MouseEvent mouse(ui::ET_MOUSE_MOVED, event_location, event_location, + ui::EventTimeForNow(), 0, 0); + DispatchEventUsingWindowDispatcher(&mouse); + EXPECT_FALSE(recorder.events().empty()); + recorder.Reset(); + + // Simulate shutdown. + host()->dispatcher()->Shutdown(); + + // Hiding the window does not generate a mouse-exit event. + window->Hide(); + EXPECT_TRUE(recorder.events().empty()); +} + // Verifies that a direct call to ProcessedTouchEvent() does not cause a crash. TEST_P(WindowEventDispatcherTest, CallToProcessedTouchEvent) { test::TestWindowDelegate delegate; @@ -1118,6 +1143,29 @@ root_window()->RemovePreTargetHandler(&recorder); } +// Tests that a mouse-press event is not dispatched during shutdown. +TEST_P(WindowEventDispatcherTest, DoNotDispatchInShutdown) { + EventFilterRecorder recorder; + test::TestWindowDelegate delegate; + std::unique_ptr<aura::Window> window(CreateTestWindowWithDelegate( + &delegate, 1234, gfx::Rect(5, 5, 100, 100), root_window())); + window->Show(); + window->AddPreTargetHandler(&recorder); + + // Simulate shutdown. + host()->dispatcher()->Shutdown(); + + // Attempt to dispatch a mouse press. + const gfx::Point center = window->bounds().CenterPoint(); + ui::MouseEvent press(ui::ET_MOUSE_PRESSED, center, center, + ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON, + ui::EF_LEFT_MOUSE_BUTTON); + DispatchEventUsingWindowDispatcher(&press); + + // Event was not dispatched. + EXPECT_TRUE(recorder.events().empty()); +} + #if defined(OS_WIN) && defined(ARCH_CPU_X86) #define MAYBE(x) DISABLED_##x #else
diff --git a/ui/base/BUILD.gn b/ui/base/BUILD.gn index 2ada278..38c70868 100644 --- a/ui/base/BUILD.gn +++ b/ui/base/BUILD.gn
@@ -303,6 +303,8 @@ "win/foreground_helper.h", "win/hidden_window.cc", "win/hidden_window.h", + "win/hwnd_metrics.cc", + "win/hwnd_metrics.h", "win/hwnd_subclass.cc", "win/hwnd_subclass.h", "win/internal_constants.cc",
diff --git a/ui/base/win/hwnd_metrics.cc b/ui/base/win/hwnd_metrics.cc new file mode 100644 index 0000000..95e2552 --- /dev/null +++ b/ui/base/win/hwnd_metrics.cc
@@ -0,0 +1,27 @@ +// Copyright 2018 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ui/base/win/hwnd_metrics.h" + +#include <windows.h> + +#include "ui/display/win/screen_win.h" + +namespace ui { + +int GetFrameThickness(HMONITOR monitor) { + // On Windows 10 the visible frame border is one pixel thick, but there is + // some additional non-visible space: SM_CXSIZEFRAME (the resize handle) + // and SM_CXPADDEDBORDER (additional border space that isn't part of the + // resize handle). + const int resize_frame_thickness = + display::win::ScreenWin::GetSystemMetricsForMonitor(monitor, + SM_CXSIZEFRAME); + const int padding_thickness = + display::win::ScreenWin::GetSystemMetricsForMonitor(monitor, + SM_CXPADDEDBORDER); + return resize_frame_thickness + padding_thickness; +} + +} // namespace ui
diff --git a/ui/base/win/hwnd_metrics.h b/ui/base/win/hwnd_metrics.h new file mode 100644 index 0000000..22ec6f9 --- /dev/null +++ b/ui/base/win/hwnd_metrics.h
@@ -0,0 +1,19 @@ +// 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 UI_BASE_WIN_HWND_METRICS_H_ +#define UI_BASE_WIN_HWND_METRICS_H_ + +#include <windows.h> + +#include "ui/base/ui_base_export.h" + +namespace ui { + +// The size, in pixels, of the non-client frame around a window on |monitor|. +UI_BASE_EXPORT int GetFrameThickness(HMONITOR monitor); + +} // namespace ui + +#endif // UI_BASE_WIN_HWND_METRICS_H_
diff --git a/ui/file_manager/integration_tests/file_manager/create_new_folder.js b/ui/file_manager/integration_tests/file_manager/create_new_folder.js index 808bf157..3a1a545 100644 --- a/ui/file_manager/integration_tests/file_manager/create_new_folder.js +++ b/ui/file_manager/integration_tests/file_manager/create_new_folder.js
@@ -42,92 +42,92 @@ } /** - * Creates new folder. + * Creates a new folder in the file list. + * * @param {string} windowId The Files app windowId. - * @param {string} path Initial path. * @param {Array<TestEntryInfo>} initialEntrySet Initial set of entries. - * @param {string} rootLabel label path's root. + * @param {string} selector Downloads or Drive directory tree item selector. * @return {Promise} Promise to be fulfilled on success. */ -function createNewFolder(windowId, path, initialEntrySet, rootLabel) { - var caller = getCaller(); - return Promise.resolve() - .then(function() { - return navigateWithDirectoryTree(windowId, path, rootLabel); - }) - .then(function() { - // Push Ctrl + E. - return remoteCall.callRemoteTestUtil( - 'fakeKeyDown', windowId, - // Ctrl + E - ['#file-list', 'e', 'U+0045', true, false, false]); +function createNewFolder(windowId, initialEntrySet, selector) { + const textInput = '#file-list .table-row[renaming] input.rename'; + + return new Promise(function(resolve) { + // Focus the file-list. + remoteCall.callRemoteTestUtil('focus', windowId, ['#file-list'], resolve); + }).then(function(result) { + chrome.test.assertTrue(result); + // Press Ctrl+E to create a new folder. + const key = ['#file-list', 'e', 'U+0045', true, false, false]; + return remoteCall.callRemoteTestUtil('fakeKeyDown', windowId, key); + }).then(function(result) { + chrome.test.assertTrue(result); + // Check: a new folder should be shown in the file list. + const files = [['New Folder', '--', 'Folder', '']].concat( + TestEntryInfo.getExpectedRows(initialEntrySet)); + return remoteCall.waitForFiles( + windowId, files, {ignoreLastModifiedTime: true}); }).then(function() { - // Wait for rename text field. - return remoteCall.waitForElement(windowId, 'li[renaming] input.rename'); + // Check: a new folder should be present in the directory tree. + const newSubtreeChildItem = selector + + ' .tree-children .tree-item[entry-label="New Folder"]'; + return remoteCall.waitForElement(windowId, newSubtreeChildItem); }).then(function() { + // Check: the text input should be shown in the file list. + return remoteCall.waitForElement(windowId, textInput); + }).then(function() { + // Get all file list rows that have attribute 'renaming'. + const renamingFileListRows = ['#file-list .table-row[renaming]']; return remoteCall.callRemoteTestUtil( - 'queryAllElements', - windowId, - ['div.detail-table > list > li[selected]']); + 'queryAllElements', windowId, renamingFileListRows); }).then(function(elements) { - // Ensure that only the new directory is selected and being renamed. + // Check: the new folder only should be 'renaming'. chrome.test.assertEq(1, elements.length); + chrome.test.assertEq(0, elements[0].text.indexOf('New Folder--')); + chrome.test.assertTrue('selected' in elements[0].attributes); + }).then(function() { + // Get all file list rows that have attribute 'selected'. + const selectedFileListRows = ['#file-list .table-row[selected]']; + return remoteCall.callRemoteTestUtil( + 'queryAllElements', windowId, selectedFileListRows); + }).then(function(elements) { + // Check: the new folder only should be 'selected'. + chrome.test.assertEq(1, elements.length); + chrome.test.assertEq(0, elements[0].text.indexOf('New Folder--')); chrome.test.assertTrue('renaming' in elements[0].attributes); }).then(function() { - // Check directory tree for new folder. - var expectedRows = [['New Folder', '--', 'Folder', '']].concat( + // Type the test folder name. + return remoteCall.callRemoteTestUtil( + 'inputText', windowId, [textInput, 'Test Folder Name']); + }).then(function() { + // Press the Enter key. + const key = [textInput, 'Enter', 'Enter', false, false, false]; + return remoteCall.callRemoteTestUtil('fakeKeyDown', windowId, key); + }).then(function(result) { + chrome.test.assertTrue(result); + // Wait until renaming is complete. + const renamingItem = ['#file-list .table-row[renaming]']; + return remoteCall.waitForElementLost(windowId, renamingItem); + }).then(function() { + // Check: the test folder should be shown in the file list. + const files = [['Test Folder Name', '--', 'Folder', '']].concat( TestEntryInfo.getExpectedRows(initialEntrySet)); return remoteCall.waitForFiles( - windowId, expectedRows, {ignoreLastModifiedTime: true}); + windowId, files, {ignoreLastModifiedTime: true}); + }).then(function(elements) { + // Check: the test folder should be present in the directory tree. + const testSubtreeChildItem = selector + + ' .tree-children .tree-item[entry-label="Test Folder Name"]'; + return remoteCall.waitForElement(windowId, testSubtreeChildItem); }).then(function() { - // Type new folder name. + // Get all file list rows that have attribute 'selected'. + const selectedFileListRows = ['#file-list .table-row[selected]']; return remoteCall.callRemoteTestUtil( - 'inputText', windowId, ['input.rename', 'Test Folder Name']); - }).then(function() { - // Push Enter. - return remoteCall.callRemoteTestUtil( - 'fakeKeyDown', - windowId, - ['input.rename', 'Enter', 'Enter', false, false, false]); - }).then(function() { - // Wait until rename completes. - return remoteCall.waitForElementLost(windowId, 'input.rename'); - }).then(function() { - // A newer entry is then added for the renamed folder. - var expectedRows = [['Test Folder Name', '--', 'Folder', '']].concat( - TestEntryInfo.getExpectedRows(initialEntrySet)); - return remoteCall.waitForFiles( - windowId, expectedRows, {ignoreLastModifiedTime: true}); - }).then(function() { - var expectedEntryRows = TestEntryInfo.getExpectedRows(initialEntrySet); - expectedEntryRows.push(['Test Folder Name', '--', 'Folder', '']); - // Wait for the new folder. - return remoteCall.waitForFiles(windowId, - expectedEntryRows, - {ignoreLastModifiedTime: true}); - }).then(function() { - // Wait until the new created folder is selected. - var nameSpanQuery = 'div.detail-table > list > ' + - 'li[selected]:not([renaming]) span.entry-name'; - - return repeatUntil(function() { - var selectedNameRetrievePromise = remoteCall.callRemoteTestUtil( - 'queryAllElements', - windowId, - ['div.detail-table > list > li[selected] span.entry-name']); - - return selectedNameRetrievePromise.then(function(elements) { - if (elements.length !== 1) { - return pending( - caller, 'Selection is not ready (elements: %j)', elements); - } else if (elements[0].text !== 'Test Folder Name') { - return pending( - caller, 'Selected item is wrong. (actual: %s)', elements[0].text); - } else { - return true; - } - }); - }); + 'queryAllElements', windowId, selectedFileListRows); + }).then(function(elements) { + // Check: the test folder only should be 'selected'. + chrome.test.assertEq(1, elements.length); + chrome.test.assertEq(0, elements[0].text.indexOf('Test Folder Name--')); }); } @@ -172,7 +172,7 @@ }).then(function() { return selectFirstFileListItem(windowId); }).then(function() { - return createNewFolder(windowId, '', BASIC_LOCAL_ENTRY_SET, 'Downloads'); + return createNewFolder(windowId, BASIC_LOCAL_ENTRY_SET, TREEITEM_DOWNLOADS); }); testPromise(promise); @@ -188,7 +188,7 @@ windowId = results.windowId; return expandRoot(windowId, TREEITEM_DOWNLOADS); }).then(function() { - return createNewFolder(windowId, '', BASIC_LOCAL_ENTRY_SET, 'Downloads'); + return createNewFolder(windowId, BASIC_LOCAL_ENTRY_SET, TREEITEM_DOWNLOADS); }); testPromise(promise); @@ -204,8 +204,12 @@ windowId = results.windowId; return expandRoot(windowId, TREEITEM_DOWNLOADS); }).then(function() { - const photosEntrySet = []; - return createNewFolder(windowId, '/photos', photosEntrySet, 'Downloads'); + return navigateWithDirectoryTree(windowId, '/photos', 'Downloads'); + }).then(function() { + return remoteCall.waitForFiles( + windowId, [], {ignoreLastModifiedTime: true}); + }).then(function() { + return createNewFolder(windowId, [], TREEITEM_DOWNLOADS); }); testPromise(promise); @@ -221,7 +225,7 @@ windowId = results.windowId; return expandRoot(windowId, TREEITEM_DRIVE); }).then(function() { - return createNewFolder(windowId, '', BASIC_DRIVE_ENTRY_SET, 'My Drive'); + return createNewFolder(windowId, BASIC_DRIVE_ENTRY_SET, TREEITEM_DRIVE); }); testPromise(promise);
diff --git a/ui/views/win/hwnd_message_handler.cc b/ui/views/win/hwnd_message_handler.cc index 97097c4..54eb0fcd 100644 --- a/ui/views/win/hwnd_message_handler.cc +++ b/ui/views/win/hwnd_message_handler.cc
@@ -31,6 +31,7 @@ #include "ui/base/ime/text_input_type.h" #include "ui/base/ui_base_features.h" #include "ui/base/view_prop.h" +#include "ui/base/win/hwnd_metrics.h" #include "ui/base/win/internal_constants.h" #include "ui/base/win/lock_state.h" #include "ui/base/win/mouse_wheel_util.h" @@ -1365,13 +1366,11 @@ if (IsMaximized()) { // Windows automatically adds a standard width border to all sides when a // window is maximized. - // TODO(870135): This should be using ScreenWin::GetSystemMetricsForMonitor, - // but doing so causes some clipping on sub-processes that are DPI unaware. - int border_thickness = GetSystemMetrics(SM_CXSIZEFRAME); + int frame_thickness = ui::GetFrameThickness(monitor); if (!delegate_->HasFrame()) - border_thickness -= 1; - *insets = gfx::Insets( - border_thickness, border_thickness, border_thickness, border_thickness); + frame_thickness -= 1; + *insets = gfx::Insets(frame_thickness, frame_thickness, frame_thickness, + frame_thickness); return true; }
diff --git a/webrunner/BUILD.gn b/webrunner/BUILD.gn index da50639..832affed 100644 --- a/webrunner/BUILD.gn +++ b/webrunner/BUILD.gn
@@ -212,6 +212,7 @@ "fidl/context_provider.fidl", "fidl/frame.fidl", "fidl/navigation_controller.fidl", + "fidl/navigation_state_change_observer.fidl", ] public_deps = [
diff --git a/webrunner/browser/context_impl_browsertest.cc b/webrunner/browser/context_impl_browsertest.cc index 5d740435..f1ebebb8 100644 --- a/webrunner/browser/context_impl_browsertest.cc +++ b/webrunner/browser/context_impl_browsertest.cc
@@ -5,7 +5,9 @@ #include <lib/fidl/cpp/binding.h> #include "base/macros.h" +#include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents_observer.h" +#include "net/test/embedded_test_server/default_handlers.h" #include "net/test/embedded_test_server/embedded_test_server.h" #include "net/test/embedded_test_server/http_request.h" #include "testing/gmock/include/gmock/gmock.h" @@ -15,7 +17,6 @@ #include "webrunner/browser/webrunner_browser_test.h" namespace webrunner { -namespace { using testing::_; using testing::AllOf; @@ -23,9 +24,9 @@ using testing::InvokeWithoutArgs; using testing::Mock; -// Use a shorter name for NavigationStateChangeDetails, because it is +// Use a shorter name for NavigationEvent, because it is // referenced frequently in this file. -using NavigationDetails = chromium::web::NavigationStateChangeDetails; +using NavigationDetails = chromium::web::NavigationEvent; const char kPage1Path[] = "/title1.html"; const char kPage2Path[] = "/title2.html"; @@ -36,38 +37,90 @@ return !arg.is_null(); } +// Defines mock methods used by tests to observe NavigationStateChangeEvents +// and lower-level WebContentsObserver events. +class MockNavigationObserver : public chromium::web::NavigationEventObserver, + public content::WebContentsObserver { + public: + using content::WebContentsObserver::Observe; + + MockNavigationObserver() = default; + ~MockNavigationObserver() override = default; + + // Acknowledges processing of the most recent OnNavigationStateChanged call. + void Acknowledge() { + DCHECK(navigation_ack_callback_); + std::move(navigation_ack_callback_)(); + + // Pump the acknowledgement message over IPC. + base::RunLoop().RunUntilIdle(); + } + + MOCK_METHOD1(MockableOnNavigationStateChanged, + void(chromium::web::NavigationEvent change)); + + // chromium::web::NavigationEventObserver implementation. + // Proxies calls to MockableOnNavigationStateChanged(), because GMock does + // not work well with fit::Callbacks inside mocked actions. + void OnNavigationStateChanged( + chromium::web::NavigationEvent change, + OnNavigationStateChangedCallback callback) override { + MockableOnNavigationStateChanged(std::move(change)); + navigation_ack_callback_ = std::move(callback); + } + + // WebContentsObserver implementation. + MOCK_METHOD2(DidFinishLoad, + void(content::RenderFrameHost* render_frame_host, + const GURL& validated_url)); + + private: + OnNavigationStateChangedCallback navigation_ack_callback_; + + DISALLOW_COPY_AND_ASSIGN(MockNavigationObserver); +}; + class ContextImplTest : public WebRunnerBrowserTest { public: - ContextImplTest() = default; + ContextImplTest() : navigation_observer_binding_(&navigation_observer_) {} ~ContextImplTest() = default; MOCK_METHOD1(OnServeHttpRequest, void(const net::test_server::HttpRequest& request)); protected: - void NavigateAndCheck(const std::string& url, - const std::string& expected_title, - chromium::web::NavigationController* controller) { - base::RunLoop run_loop; - EXPECT_CALL(*this, OnNavigationStateChanged(testing::AllOf( - Field(&NavigationDetails::title, expected_title), - Field(&NavigationDetails::url, IsSet())))) - .WillOnce(InvokeWithoutArgs([&run_loop] { run_loop.Quit(); })); - controller->LoadUrl(url, nullptr); - run_loop.Run(); - Mock::VerifyAndClearExpectations(this); - } - chromium::web::FramePtr CreateFrame() { chromium::web::FramePtr frame; context()->CreateFrame(frame.NewRequest()); - frame.events().OnNavigationStateChanged = - fit::bind_member(this, &ContextImplTest::OnNavigationStateChanged); + frame->SetNavigationEventObserver( + navigation_observer_binding_.NewBinding()); + base::RunLoop().RunUntilIdle(); return frame; } - MOCK_METHOD1(OnNavigationStateChanged, - void(chromium::web::NavigationStateChangeDetails change)); + // Navigates a |controller| to |url|, blocking until navigation is complete. + void CheckLoadUrl(const std::string& url, + const std::string& expected_title, + chromium::web::NavigationController* controller) { + base::RunLoop run_loop; + EXPECT_CALL(navigation_observer_, + MockableOnNavigationStateChanged(testing::AllOf( + Field(&NavigationDetails::title, expected_title), + Field(&NavigationDetails::url, url)))) + .WillOnce(InvokeWithoutArgs([&run_loop]() { run_loop.Quit(); })); + controller->LoadUrl(url, nullptr); + run_loop.Run(); + Mock::VerifyAndClearExpectations(this); + navigation_observer_.Acknowledge(); + } + + void TearDownOnMainThread() override { + navigation_observer_binding_.Unbind(); + } + + testing::StrictMock<MockNavigationObserver> navigation_observer_; + fidl::Binding<chromium::web::NavigationEventObserver> + navigation_observer_binding_; private: DISALLOW_COPY_AND_ASSIGN(ContextImplTest); @@ -87,16 +140,16 @@ IN_PROC_BROWSER_TEST_F(ContextImplTest, NavigateFrame) { chromium::web::FramePtr frame = CreateFrame(); - chromium::web::NavigationControllerPtr navigation_controller; - frame->GetNavigationController(navigation_controller.NewRequest()); + chromium::web::NavigationControllerPtr controller; + frame->GetNavigationController(controller.NewRequest()); - NavigateAndCheck(url::kAboutBlankURL, url::kAboutBlankURL, - navigation_controller.get()); + CheckLoadUrl(url::kAboutBlankURL, url::kAboutBlankURL, controller.get()); frame.Unbind(); } -IN_PROC_BROWSER_TEST_F(ContextImplTest, FrameDeletedBeforeContext) { +// TODO(crbug.com/876894): Disabled due to flakiness under QEMU. +IN_PROC_BROWSER_TEST_F(ContextImplTest, DISABLED_FrameDeletedBeforeContext) { chromium::web::FramePtr frame = CreateFrame(); // Process the frame creation message. @@ -140,34 +193,19 @@ GURL title1(embedded_test_server()->GetURL(kPage1Path)); GURL title2(embedded_test_server()->GetURL(kPage2Path)); - { - base::RunLoop run_loop; - EXPECT_CALL(*this, OnNavigationStateChanged(testing::AllOf( - Field(&NavigationDetails::title, kPage1Title), - Field(&NavigationDetails::url, IsSet())))) - .WillOnce(InvokeWithoutArgs([&run_loop] { run_loop.Quit(); })); - controller->LoadUrl(title1.spec(), nullptr); - run_loop.Run(); - } + CheckLoadUrl(title1.spec(), kPage1Title, controller.get()); + CheckLoadUrl(title2.spec(), kPage2Title, controller.get()); { base::RunLoop run_loop; - EXPECT_CALL(*this, OnNavigationStateChanged(testing::AllOf( - Field(&NavigationDetails::title, kPage2Title), - Field(&NavigationDetails::url, IsSet())))) - .WillOnce(InvokeWithoutArgs([&run_loop] { run_loop.Quit(); })); - controller->LoadUrl(title2.spec(), nullptr); - run_loop.Run(); - } - - { - base::RunLoop run_loop; - EXPECT_CALL(*this, OnNavigationStateChanged(testing::AllOf( - Field(&NavigationDetails::title, kPage1Title), - Field(&NavigationDetails::url, IsSet())))) + EXPECT_CALL(navigation_observer_, + MockableOnNavigationStateChanged(testing::AllOf( + Field(&NavigationDetails::title, kPage1Title), + Field(&NavigationDetails::url, IsSet())))) .WillOnce(InvokeWithoutArgs([&run_loop] { run_loop.Quit(); })); controller->GoBack(); run_loop.Run(); + navigation_observer_.Acknowledge(); } // At the top of the navigation entry list; this should be a no-op. @@ -178,12 +216,14 @@ { base::RunLoop run_loop; - EXPECT_CALL(*this, OnNavigationStateChanged(testing::AllOf( - Field(&NavigationDetails::title, kPage2Title), - Field(&NavigationDetails::url, IsSet())))) + EXPECT_CALL(navigation_observer_, + MockableOnNavigationStateChanged(testing::AllOf( + Field(&NavigationDetails::title, kPage2Title), + Field(&NavigationDetails::url, IsSet())))) .WillOnce(InvokeWithoutArgs([&run_loop] { run_loop.Quit(); })); controller->GoForward(); run_loop.Run(); + navigation_observer_.Acknowledge(); } // At the end of the navigation entry list; this should be a no-op. @@ -205,28 +245,27 @@ GURL url(embedded_test_server()->GetURL(kPage1Path)); EXPECT_CALL(*this, OnServeHttpRequest(_)); - NavigateAndCheck(url.spec(), kPage1Title, navigation_controller.get()); + CheckLoadUrl(url.spec(), kPage1Title, navigation_controller.get()); + + navigation_observer_.Observe( + context_impl()->GetFrameImplForTest(&frame)->web_contents_.get()); // Reload with NO_CACHE. { base::RunLoop run_loop; EXPECT_CALL(*this, OnServeHttpRequest(_)); - EXPECT_CALL(*this, OnNavigationStateChanged(testing::AllOf( - Field(&NavigationDetails::title, kPage1Title), - Field(&NavigationDetails::url, IsSet())))) + EXPECT_CALL(navigation_observer_, DidFinishLoad(_, url)) .WillOnce(InvokeWithoutArgs([&run_loop]() { run_loop.Quit(); })); navigation_controller->Reload(chromium::web::ReloadType::NO_CACHE); run_loop.Run(); Mock::VerifyAndClearExpectations(this); + navigation_observer_.Acknowledge(); } - // Reload with PARTIAL_CACHE. { base::RunLoop run_loop; EXPECT_CALL(*this, OnServeHttpRequest(_)); - EXPECT_CALL(*this, OnNavigationStateChanged(testing::AllOf( - Field(&NavigationDetails::title, kPage1Title), - Field(&NavigationDetails::url, IsSet())))) + EXPECT_CALL(navigation_observer_, DidFinishLoad(_, url)) .WillOnce(InvokeWithoutArgs([&run_loop]() { run_loop.Quit(); })); navigation_controller->Reload(chromium::web::ReloadType::PARTIAL_CACHE); run_loop.Run(); @@ -258,12 +297,14 @@ // Navigate to a page. { base::RunLoop run_loop; - EXPECT_CALL(*this, OnNavigationStateChanged(testing::AllOf( - Field(&NavigationDetails::title, kPage1Title), - Field(&NavigationDetails::url, IsSet())))) + EXPECT_CALL(navigation_observer_, + MockableOnNavigationStateChanged(testing::AllOf( + Field(&NavigationDetails::title, kPage1Title), + Field(&NavigationDetails::url, IsSet())))) .WillOnce(testing::InvokeWithoutArgs([&run_loop] { run_loop.Quit(); })); controller->LoadUrl(title1.spec(), nullptr); run_loop.Run(); + navigation_observer_.Acknowledge(); } // Verify that GetVisibleEntry() reflects the new Frame navigation state. @@ -283,12 +324,14 @@ // Navigate to another page. { base::RunLoop run_loop; - EXPECT_CALL(*this, OnNavigationStateChanged(testing::AllOf( - Field(&NavigationDetails::title, kPage2Title), - Field(&NavigationDetails::url, IsSet())))) + EXPECT_CALL(navigation_observer_, + MockableOnNavigationStateChanged(testing::AllOf( + Field(&NavigationDetails::title, kPage2Title), + Field(&NavigationDetails::url, IsSet())))) .WillOnce(testing::InvokeWithoutArgs([&run_loop] { run_loop.Quit(); })); controller->LoadUrl(title2.spec(), nullptr); run_loop.Run(); + navigation_observer_.Acknowledge(); } // Verify the navigation with GetVisibleEntry(). @@ -308,12 +351,14 @@ // Navigate back to the first page. { base::RunLoop run_loop; - EXPECT_CALL(*this, OnNavigationStateChanged(testing::AllOf( - Field(&NavigationDetails::title, kPage1Title), - Field(&NavigationDetails::url, IsSet())))) + EXPECT_CALL(navigation_observer_, + MockableOnNavigationStateChanged(testing::AllOf( + Field(&NavigationDetails::title, kPage1Title), + Field(&NavigationDetails::url, IsSet())))) .WillOnce(testing::InvokeWithoutArgs([&run_loop] { run_loop.Quit(); })); controller->GoBack(); run_loop.Run(); + navigation_observer_.Acknowledge(); } // Verify the navigation with GetVisibleEntry(). @@ -331,5 +376,189 @@ } } -} // namespace +IN_PROC_BROWSER_TEST_F(ContextImplTest, NoNavigationObserverAttached) { + chromium::web::FramePtr frame; + context()->CreateFrame(frame.NewRequest()); + base::RunLoop().RunUntilIdle(); + + chromium::web::NavigationControllerPtr controller; + frame->GetNavigationController(controller.NewRequest()); + + ASSERT_TRUE(embedded_test_server()->Start()); + GURL title1(embedded_test_server()->GetURL(kPage1Path)); + GURL title2(embedded_test_server()->GetURL(kPage2Path)); + + navigation_observer_.Observe( + context_impl()->GetFrameImplForTest(&frame)->web_contents_.get()); + + { + base::RunLoop run_loop; + EXPECT_CALL(navigation_observer_, DidFinishLoad(_, title1)) + .WillOnce(InvokeWithoutArgs([&run_loop]() { run_loop.Quit(); })); + controller->LoadUrl(title1.spec(), nullptr); + run_loop.Run(); + } + + { + base::RunLoop run_loop; + EXPECT_CALL(navigation_observer_, DidFinishLoad(_, title2)) + .WillOnce(InvokeWithoutArgs([&run_loop]() { run_loop.Quit(); })); + controller->LoadUrl(title2.spec(), nullptr); + run_loop.Run(); + } +} + +// Verifies that a Frame will handle navigation observer disconnection events +// gracefully. +IN_PROC_BROWSER_TEST_F(ContextImplTest, NavigationObserverDisconnected) { + chromium::web::FramePtr frame = CreateFrame(); + + chromium::web::NavigationControllerPtr controller; + frame->GetNavigationController(controller.NewRequest()); + + ASSERT_TRUE(embedded_test_server()->Start()); + GURL title1(embedded_test_server()->GetURL(kPage1Path)); + GURL title2(embedded_test_server()->GetURL(kPage2Path)); + + navigation_observer_.Observe( + context_impl()->GetFrameImplForTest(&frame)->web_contents_.get()); + + { + base::RunLoop run_loop; + EXPECT_CALL(navigation_observer_, DidFinishLoad(_, title1)); + EXPECT_CALL(navigation_observer_, + MockableOnNavigationStateChanged(testing::AllOf( + Field(&NavigationDetails::title, kPage1Title), + Field(&NavigationDetails::url, IsSet())))) + .WillOnce(InvokeWithoutArgs([&run_loop]() { run_loop.Quit(); })); + controller->LoadUrl(title1.spec(), nullptr); + run_loop.Run(); + } + + // Disconnect the observer & spin the runloop to propagate the disconnection + // event over IPC. + navigation_observer_binding_.Unbind(); + base::RunLoop().RunUntilIdle(); + + { + base::RunLoop run_loop; + EXPECT_CALL(navigation_observer_, DidFinishLoad(_, title2)) + .WillOnce(InvokeWithoutArgs([&run_loop]() { run_loop.Quit(); })); + controller->LoadUrl(title2.spec(), nullptr); + run_loop.Run(); + } +} + +IN_PROC_BROWSER_TEST_F(ContextImplTest, DelayedNavigationEventAck) { + chromium::web::FramePtr frame = CreateFrame(); + + chromium::web::NavigationControllerPtr controller; + frame->GetNavigationController(controller.NewRequest()); + + ASSERT_TRUE(embedded_test_server()->Start()); + GURL title1(embedded_test_server()->GetURL(kPage1Path)); + GURL title2(embedded_test_server()->GetURL(kPage2Path)); + + // Expect an navigation event here, but deliberately postpone acknowledgement + // until the end of the test. + { + base::RunLoop run_loop; + EXPECT_CALL(navigation_observer_, + MockableOnNavigationStateChanged(testing::AllOf( + Field(&NavigationDetails::title, kPage1Title), + Field(&NavigationDetails::url, IsSet())))) + .WillOnce(InvokeWithoutArgs([&run_loop]() { run_loop.Quit(); })); + controller->LoadUrl(title1.spec(), nullptr); + run_loop.Run(); + Mock::VerifyAndClearExpectations(this); + } + + // Since we have blocked NavigationEventObserver's flow, we must observe the + // WebContents events directly via a test-only seam. + navigation_observer_.Observe( + context_impl()->GetFrameImplForTest(&frame)->web_contents_.get()); + + // Navigate to a second page. + { + base::RunLoop run_loop; + EXPECT_CALL(navigation_observer_, DidFinishLoad(_, title2)) + .WillOnce(InvokeWithoutArgs([&run_loop]() { run_loop.Quit(); })); + controller->LoadUrl(title2.spec(), nullptr); + run_loop.Run(); + Mock::VerifyAndClearExpectations(this); + } + + // Navigate to the first page. + { + base::RunLoop run_loop; + EXPECT_CALL(navigation_observer_, DidFinishLoad(_, title1)) + .WillOnce(InvokeWithoutArgs([&run_loop]() { run_loop.Quit(); })); + controller->LoadUrl(title1.spec(), nullptr); + run_loop.Run(); + Mock::VerifyAndClearExpectations(this); + } + + // Since there was no observable change in navigation state since the last + // ack, there should be no more NavigationEvents generated. + { + base::RunLoop run_loop; + EXPECT_CALL(navigation_observer_, + MockableOnNavigationStateChanged(testing::AllOf( + Field(&NavigationDetails::title, kPage1Title), + Field(&NavigationDetails::url, IsSet())))) + .WillOnce(InvokeWithoutArgs([&run_loop]() { run_loop.Quit(); })); + navigation_observer_.Acknowledge(); + run_loop.Run(); + } +} + +// Observes events specific to the Stop() test case. +struct WebContentsObserverForStop : public content::WebContentsObserver { + using content::WebContentsObserver::Observe; + MOCK_METHOD1(DidStartNavigation, void(content::NavigationHandle*)); + MOCK_METHOD0(NavigationStopped, void()); +}; + +IN_PROC_BROWSER_TEST_F(ContextImplTest, Stop) { + chromium::web::FramePtr frame = CreateFrame(); + + chromium::web::NavigationControllerPtr controller; + frame->GetNavigationController(controller.NewRequest()); + + net::test_server::RegisterDefaultHandlers(embedded_test_server()); + ASSERT_TRUE(embedded_test_server()->Start()); + + // Use a request handler that will accept the connection and stall + // indefinitely. + GURL hung_url(embedded_test_server()->GetURL("/hung")); + + WebContentsObserverForStop observer; + observer.Observe( + context_impl()->GetFrameImplForTest(&frame)->web_contents_.get()); + + { + base::RunLoop run_loop; + EXPECT_CALL(observer, DidStartNavigation(_)) + .WillOnce(InvokeWithoutArgs([&run_loop]() { run_loop.Quit(); })); + controller->LoadUrl(hung_url.spec(), nullptr); + run_loop.Run(); + Mock::VerifyAndClearExpectations(this); + } + + EXPECT_TRUE( + context_impl()->GetFrameImplForTest(&frame)->web_contents_->IsLoading()); + + { + base::RunLoop run_loop; + EXPECT_CALL(observer, NavigationStopped()) + .WillOnce(InvokeWithoutArgs([&run_loop]() { run_loop.Quit(); })); + controller->Stop(); + run_loop.Run(); + Mock::VerifyAndClearExpectations(this); + } + + EXPECT_FALSE( + context_impl()->GetFrameImplForTest(&frame)->web_contents_->IsLoading()); +} + } // namespace webrunner
diff --git a/webrunner/browser/frame_impl.cc b/webrunner/browser/frame_impl.cc index b594100..9680537 100644 --- a/webrunner/browser/frame_impl.cc +++ b/webrunner/browser/frame_impl.cc
@@ -10,6 +10,7 @@ #include "base/run_loop.h" #include "base/strings/utf_string_conversions.h" #include "content/public/browser/navigation_entry.h" +#include "content/public/browser/navigation_handle.h" #include "content/public/browser/web_contents.h" #include "ui/aura/layout_manager.h" #include "ui/aura/window.h" @@ -69,6 +70,29 @@ return converted; } +// Computes the observable differences between |entry_1| and |entry_2|. +// Returns true if they are different, |false| if their observable fields are +// identical. +bool ComputeNavigationEvent(const chromium::web::NavigationEntry& old_entry, + const chromium::web::NavigationEntry& new_entry, + chromium::web::NavigationEvent* computed_event) { + DCHECK(computed_event); + + bool is_changed = false; + + if (old_entry.title != new_entry.title) { + is_changed = true; + computed_event->title = new_entry.title; + } + + if (old_entry.url != new_entry.url) { + is_changed = true; + computed_event->url = new_entry.url; + } + + return is_changed; +} + } // namespace FrameImpl::FrameImpl(std::unique_ptr<content::WebContents> web_contents, @@ -78,7 +102,6 @@ context_(context), binding_(this, std::move(frame_request)) { binding_.set_error_handler([this]() { context_->DestroyFrame(this); }); - Observe(web_contents_.get()); } FrameImpl::~FrameImpl() { @@ -138,7 +161,7 @@ } void FrameImpl::Stop() { - NOTIMPLEMENTED(); + web_contents_->Stop(); } void FrameImpl::Reload(chromium::web::ReloadType type) { @@ -166,28 +189,64 @@ callback(std::make_unique<chromium::web::NavigationEntry>(std::move(output))); } +void FrameImpl::SetNavigationEventObserver( + fidl::InterfaceHandle<chromium::web::NavigationEventObserver> observer) { + // Reset the event buffer state. + waiting_for_navigation_event_ack_ = false; + cached_navigation_state_ = {}; + pending_navigation_event_ = {}; + pending_navigation_event_is_dirty_ = false; + + if (observer) { + navigation_observer_.Bind(std::move(observer)); + navigation_observer_.set_error_handler([this]() { + // Stop observing on Observer connection loss. + SetNavigationEventObserver(nullptr); + }); + Observe(web_contents_.get()); + } else { + navigation_observer_.Unbind(); + Observe(nullptr); // Stop receiving WebContentsObserver events. + } +} + void FrameImpl::DidFinishLoad(content::RenderFrameHost* render_frame_host, const GURL& validated_url) { if (web_contents_->GetMainFrame() != render_frame_host) { return; } - std::string current_url = validated_url.spec(); - std::string current_title = base::UTF16ToUTF8(web_contents_->GetTitle()); + // TODO(kmarshall): Get NavigationEntry from NavigationController. + chromium::web::NavigationEntry current_navigation_state; + current_navigation_state.url = validated_url.spec(); + current_navigation_state.title = base::UTF16ToUTF8(web_contents_->GetTitle()); - bool is_changed; - chromium::web::NavigationStateChangeDetails delta; - if (current_title != cached_navigation_state_.title) { - is_changed = true; - delta.title = current_title; + pending_navigation_event_is_dirty_ |= + ComputeNavigationEvent(cached_navigation_state_, current_navigation_state, + &pending_navigation_event_); + cached_navigation_state_ = std::move(current_navigation_state); + + if (pending_navigation_event_is_dirty_ && + !waiting_for_navigation_event_ack_) { + MaybeSendNavigationEvent(); } +} - if (current_url != cached_navigation_state_.url) { - is_changed = true; - delta.url = current_url; +void FrameImpl::MaybeSendNavigationEvent() { + if (pending_navigation_event_is_dirty_) { + pending_navigation_event_is_dirty_ = false; + waiting_for_navigation_event_ack_ = true; + + // Send the event to the observer and, upon acknowledgement, revisit this + // function to send another update. + navigation_observer_->OnNavigationStateChanged( + std::move(pending_navigation_event_), + [this]() { MaybeSendNavigationEvent(); }); + return; + } else { + // No more changes to report. + waiting_for_navigation_event_ack_ = false; } - - binding_.events().OnNavigationStateChanged(std::move(delta)); } } // namespace webrunner
diff --git a/webrunner/browser/frame_impl.h b/webrunner/browser/frame_impl.h index b4c640ad..8574c29 100644 --- a/webrunner/browser/frame_impl.h +++ b/webrunner/browser/frame_impl.h
@@ -62,17 +62,33 @@ void Stop() override; void Reload(chromium::web::ReloadType type) override; void GetVisibleEntry(GetVisibleEntryCallback callback) override; + void SetNavigationEventObserver( + fidl::InterfaceHandle<chromium::web::NavigationEventObserver> observer) + override; // content::WebContentsObserver implementation. void DidFinishLoad(content::RenderFrameHost* render_frame_host, const GURL& validated_url) override; private: + FRIEND_TEST_ALL_PREFIXES(ContextImplTest, DelayedNavigationEventAck); + FRIEND_TEST_ALL_PREFIXES(ContextImplTest, NavigationObserverDisconnected); + FRIEND_TEST_ALL_PREFIXES(ContextImplTest, NoNavigationObserverAttached); + FRIEND_TEST_ALL_PREFIXES(ContextImplTest, ReloadFrame); + FRIEND_TEST_ALL_PREFIXES(ContextImplTest, Stop); + + // Sends |pending_navigation_event_| to the observer if there are any changes + // to be reported. + void MaybeSendNavigationEvent(); + std::unique_ptr<aura::WindowTreeHost> window_tree_host_; std::unique_ptr<content::WebContents> web_contents_; - // Cached navigation event details. + chromium::web::NavigationEventObserverPtr navigation_observer_; chromium::web::NavigationEntry cached_navigation_state_; + chromium::web::NavigationEvent pending_navigation_event_; + bool waiting_for_navigation_event_ack_; + bool pending_navigation_event_is_dirty_; ContextImpl* context_ = nullptr; fidl::Binding<chromium::web::Frame> binding_;
diff --git a/webrunner/fidl/frame.fidl b/webrunner/fidl/frame.fidl index 74a3a1d..2597e9f 100644 --- a/webrunner/fidl/frame.fidl +++ b/webrunner/fidl/frame.fidl
@@ -4,14 +4,6 @@ library chromium.web; -// Indicates which properties of the NavigationController's visible content -// that have changed since the last OnNavigationStateChanged() event. -// Properties which remain unchanged are left unset. -struct NavigationStateChangeDetails { - string? url; - string? title; -}; - interface Frame { // Creates and registers a view with the view manager and returns its // view owner which may subsequently be passed to |View.AddChild()| @@ -29,6 +21,10 @@ // NavigationController. 2: GetNavigationController(request<NavigationController> controller); - // Called when user-visible navigation state has changed for the Frame. - 3: -> OnNavigationStateChanged(NavigationStateChangeDetails change); + + // Sets the observer for handling page navigation events. + // + // |observer|: The observer to use. Unregisters any existing observers + // if null. + 100: SetNavigationEventObserver(NavigationEventObserver? observer); };
diff --git a/webrunner/fidl/navigation_state_change_observer.fidl b/webrunner/fidl/navigation_state_change_observer.fidl new file mode 100644 index 0000000..079b918e --- /dev/null +++ b/webrunner/fidl/navigation_state_change_observer.fidl
@@ -0,0 +1,24 @@ +// 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. + +library chromium.web; + +// Indicates the properties of the NavigationController's visible content +// which have changed since the last OnNavigationStateChanged() event. +// Any unchanged properties are left unset. +struct NavigationEvent { + string? url; + string? title; +}; + +// Interface supplied by the embedder for receiving notifications about +// navigation events in a Frame. +interface NavigationEventObserver { + // Called when user-visible navigation state has changed since Frame + // creation or the last acknowledgement callback, whichever occurred later. + // |change| will contain all the differences in navigation state since the + // last acknowledgement. + 1: OnNavigationStateChanged(NavigationEvent change) -> (); +}; +
diff --git a/webrunner/service/context_provider_impl_unittest.cc b/webrunner/service/context_provider_impl_unittest.cc index b472ead00..42f41477 100644 --- a/webrunner/service/context_provider_impl_unittest.cc +++ b/webrunner/service/context_provider_impl_unittest.cc
@@ -15,6 +15,7 @@ #include "base/base_switches.h" #include "base/bind.h" #include "base/bind_helpers.h" +#include "base/callback.h" #include "base/command_line.h" #include "base/files/file.h" #include "base/files/file_util.h" @@ -46,7 +47,11 @@ ~FakeFrame() override = default; - fidl::Binding<chromium::web::Frame>& binding() { return binding_; } + void set_on_set_observer_callback(base::OnceClosure callback) { + on_set_observer_callback_ = std::move(callback); + } + + chromium::web::NavigationEventObserver* observer() { return observer_.get(); } void CreateView( fidl::InterfaceRequest<fuchsia::ui::viewsv1token::ViewOwner> view_owner, @@ -57,8 +62,17 @@ fidl::InterfaceRequest<chromium::web::NavigationController> controller) override {} + void SetNavigationEventObserver( + fidl::InterfaceHandle<chromium::web::NavigationEventObserver> observer) + override { + observer_.Bind(std::move(observer)); + std::move(on_set_observer_callback_).Run(); + } + private: fidl::Binding<chromium::web::Frame> binding_; + chromium::web::NavigationEventObserverPtr observer_; + base::OnceClosure on_set_observer_callback_; DISALLOW_COPY_AND_ASSIGN(FakeFrame); }; @@ -109,14 +123,19 @@ &context, fidl::InterfaceRequest<chromium::web::Context>( std::move(context_handle))); - // When a Frame is bound, immediately broadcast a navigation event to its - // event listeners. + // When a Frame's NavigationEventObserver is bound, immediately broadcast a + // navigation event to its listeners. context.set_on_create_frame_callback( base::BindRepeating([](FakeFrame* frame) { - chromium::web::NavigationStateChangeDetails details; - details.url = kUrl; - details.title = kTitle; - frame->binding().events().OnNavigationStateChanged(std::move(details)); + frame->set_on_set_observer_callback(base::BindOnce( + [](FakeFrame* frame) { + chromium::web::NavigationEvent event; + event.url = kUrl; + event.title = kTitle; + frame->observer()->OnNavigationStateChanged(std::move(event), + []() {}); + }, + frame)); })); // Quit the process when the context is destroyed. @@ -158,20 +177,17 @@ ADD_FAILURE(); run_loop.Quit(); }); + (*context)->CreateFrame(frame_ptr.NewRequest()); // Create a Frame and expect to see a navigation event. - chromium::web::NavigationStateChangeDetails nav_change_stored; - frame_ptr.events().OnNavigationStateChanged = - [&nav_change_stored, - &run_loop](chromium::web::NavigationStateChangeDetails nav_change) { - nav_change_stored = nav_change; - run_loop.Quit(); - }; - (*context)->CreateFrame(frame_ptr.NewRequest()); + CapturingNavigationEventObserver change_observer(run_loop.QuitClosure()); + fidl::Binding<chromium::web::NavigationEventObserver> + change_observer_binding(&change_observer); + frame_ptr->SetNavigationEventObserver(change_observer_binding.NewBinding()); run_loop.Run(); - EXPECT_EQ(nav_change_stored.url, kUrl); - EXPECT_EQ(nav_change_stored.title, kTitle); + EXPECT_EQ(change_observer.captured_event().url, kUrl); + EXPECT_EQ(change_observer.captured_event().title, kTitle); } chromium::web::CreateContextParams BuildCreateContextParams() { @@ -194,6 +210,27 @@ chromium::web::ContextProviderPtr provider_ptr_; private: + struct CapturingNavigationEventObserver + : public chromium::web::NavigationEventObserver { + public: + CapturingNavigationEventObserver(base::OnceClosure on_change_cb) + : on_change_cb_(std::move(on_change_cb)) {} + ~CapturingNavigationEventObserver() override = default; + + void OnNavigationStateChanged( + chromium::web::NavigationEvent change, + OnNavigationStateChangedCallback callback) override { + captured_event_ = std::move(change); + std::move(on_change_cb_).Run(); + } + + chromium::web::NavigationEvent captured_event() { return captured_event_; } + + private: + base::OnceClosure on_change_cb_; + chromium::web::NavigationEvent captured_event_; + }; + DISALLOW_COPY_AND_ASSIGN(ContextProviderImplTest); };