diff --git a/AUTHORS b/AUTHORS index f661bce..522cfbd 100644 --- a/AUTHORS +++ b/AUTHORS
@@ -767,6 +767,7 @@ Salvatore Iovene <salvatore.iovene@intel.com> Sam Larison <qufighter@gmail.com> Sam McDonald <sam@sammcd.com> +Samuel Attard <samuel.r.attard@gmail.com> Sanggi Hong <sanggi.hong11@gmail.com> Sanghee Lee <sanghee.lee1992@gmail.com> Sanghyun Park <sh919.park@samsung.com>
diff --git a/DEPS b/DEPS index a0776570..8ada9bc 100644 --- a/DEPS +++ b/DEPS
@@ -139,15 +139,15 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ANGLE # and whatever else without interference from each other. - 'angle_revision': '4d153383bd3a2359a44fb0c13a65119c0087702f', + 'angle_revision': 'd838178daa4976ebd7a0af918fbe0c502e09734b', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. - 'swiftshader_revision': '823ca85404fb67037c0ecc68481fb59aa232196c', + 'swiftshader_revision': 'bb305299f4de4a87d45bb4197aded36749ebda46', # 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': 'ac0f524bb10359d2d152b2001bc33e5bdc212c49', + 'pdfium_revision': 'e8f5721133adb22716fcf1228bfa4a851ee43f20', # 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. @@ -190,7 +190,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': 'b3bee2e7d9f156928d5d2b1efa1360478e99f856', + 'catapult_revision': '7ad2d7992c7ec3a184a84e8faa97cd8492e2b928', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other. @@ -206,7 +206,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'feed_revision': '9a7f20c75b0e6ca8d669e967ec0bd6b72965df3e', + 'feed_revision': '0ac884dad3d640ac4a31ba80c7f0d25be623ab52', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling android_sdk_build-tools_version # and whatever else without interference from each other. @@ -382,7 +382,7 @@ }, 'src/ios/third_party/earl_grey2/src': { - 'url': Var('chromium_git') + '/external/github.com/google/EarlGrey.git' + '@' + '3f9a3f28029bb7547b799a74458e45484b4a55f9', + 'url': Var('chromium_git') + '/external/github.com/google/EarlGrey.git' + '@' + 'ad70b511da47793e27e77c1a69c7895e8403be45', 'condition': 'checkout_ios', }, @@ -829,7 +829,7 @@ }, 'src/third_party/glslang/src': - Var('chromium_git') + '/external/github.com/KhronosGroup/glslang.git' + '@' + 'd90d548161bc46341121b5c5bd77acb27ac1584f', + Var('chromium_git') + '/external/github.com/KhronosGroup/glslang.git' + '@' + '9390154c557e6211e273628805a1827a4738c751', 'src/third_party/google_toolbox_for_mac/src': { 'url': Var('chromium_git') + '/external/github.com/google/google-toolbox-for-mac.git' + '@' + Var('google_toolbox_for_mac_revision'), @@ -1273,7 +1273,7 @@ Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + 'a0f51b2e123f39c9ff12e621b0b47dd28dd64424', 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + '87e05b5df58c138e10faced59f7f8af16434011e', + Var('webrtc_git') + '/src.git' + '@' + 'b678940d3a444c9bf5b53a0bc2e2951f222dab6a', 'src/third_party/xdg-utils': { 'url': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d', @@ -1314,7 +1314,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@794439738e8e216493af456d390773cd86f0e135', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@0dbc324dbe30062866204f35a21a3a0ffd9f553d', 'condition': 'checkout_src_internal', },
diff --git a/PRESUBMIT.py b/PRESUBMIT.py index fcc8432..59aaaad 100644 --- a/PRESUBMIT.py +++ b/PRESUBMIT.py
@@ -1378,7 +1378,7 @@ pattern = input_api.re.compile('^(?:<<<<<<<|>>>>>>>) |^=======$') errors = [] for line_num, line in f.ChangedContents(): - if f.LocalPath().endswith('.md'): + if f.LocalPath().endswith(('.md', '.rst', '.txt')): # First-level headers in markdown look a lot like version control # conflict markers. http://daringfireball.net/projects/markdown/basics continue
diff --git a/WATCHLISTS b/WATCHLISTS index 9082155..ec5417d 100644 --- a/WATCHLISTS +++ b/WATCHLISTS
@@ -2419,7 +2419,10 @@ 'services_public': ['blundell+services-watchlist@chromium.org'], 'settings': ['dbeam+watch-settings@chromium.org', 'michaelpg+watch-md-settings@chromium.org', - 'stevenjb+watch-md-settings@chromium.org'], + 'stevenjb+watch-md-settings@chromium.org', + 'hsuregan+watch@chromium.org', + 'jordynass+watch@chromium.org', + 'maybelle+watch@chromium.org'], 'settings_reset_prompt': ['alito+watch@chromium.org'], 'site_engagement': ['dominickn+watch-engagement@chromium.org'], 'site_instance': ['ajwong+watch@chromium.org',
diff --git a/ash/BUILD.gn b/ash/BUILD.gn index 27232ea..5b86d8f 100644 --- a/ash/BUILD.gn +++ b/ash/BUILD.gn
@@ -1035,6 +1035,12 @@ "wm/default_state.h", "wm/default_window_resizer.cc", "wm/default_window_resizer.h", + "wm/desks/close_desk_button.cc", + "wm/desks/close_desk_button.h", + "wm/desks/desk.cc", + "wm/desks/desk.h", + "wm/desks/desk_mini_view.cc", + "wm/desks/desk_mini_view.h", "wm/desks/desks_bar_view.cc", "wm/desks/desks_bar_view.h", "wm/desks/desks_controller.cc", @@ -1782,6 +1788,7 @@ "wm/client_controlled_state_unittest.cc", "wm/container_finder_unittest.cc", "wm/default_window_resizer_unittest.cc", + "wm/desks/desks_unittests.cc", "wm/drag_window_resizer_unittest.cc", "wm/fullscreen_window_finder_unittest.cc", "wm/gestures/overview_gesture_handler_unittest.cc",
diff --git a/ash/accessibility/accessibility_controller.cc b/ash/accessibility/accessibility_controller.cc index d41589a57..b315ed1 100644 --- a/ash/accessibility/accessibility_controller.cc +++ b/ash/accessibility/accessibility_controller.cc
@@ -975,7 +975,7 @@ int movement_threshold = active_user_prefs_->GetInteger( prefs::kAccessibilityAutoclickMovementThreshold); - Shell::Get()->autoclick_controller()->set_movement_threshold( + Shell::Get()->autoclick_controller()->SetMovementThreshold( movement_threshold); }
diff --git a/ash/app_list/presenter/BUILD.gn b/ash/app_list/presenter/BUILD.gn index eebfebc..9f2dce6 100644 --- a/ash/app_list/presenter/BUILD.gn +++ b/ash/app_list/presenter/BUILD.gn
@@ -25,7 +25,6 @@ "//ui/aura", "//ui/compositor", "//ui/gfx/geometry", - "//ui/keyboard", "//ui/views", # Temporary dependency to fix compile flake in http://crbug.com/611898.
diff --git a/ash/app_list/presenter/app_list_presenter_impl.cc b/ash/app_list/presenter/app_list_presenter_impl.cc index ee9ab7e..8d0c30e 100644 --- a/ash/app_list/presenter/app_list_presenter_impl.cc +++ b/ash/app_list/presenter/app_list_presenter_impl.cc
@@ -28,7 +28,6 @@ #include "ui/display/types/display_constants.h" #include "ui/gfx/geometry/vector2d_conversions.h" #include "ui/gfx/presentation_feedback.h" -#include "ui/keyboard/keyboard_controller.h" #include "ui/views/widget/widget.h" namespace app_list { @@ -413,12 +412,6 @@ !switches::ShouldNotDismissOnBlur() && !delegate_->IsTabletMode()) { Dismiss(base::TimeTicks()); } - if (applist_container->Contains(gained_focus) && - keyboard::KeyboardController::HasInstance()) { - auto* const keyboard_controller = keyboard::KeyboardController::Get(); - if (keyboard_controller->IsKeyboardVisible()) - keyboard_controller->HideKeyboardImplicitlyBySystem(); - } } }
diff --git a/ash/app_list/views/assistant/dialog_plate.cc b/ash/app_list/views/assistant/dialog_plate.cc index 97bf52c..57d8952 100644 --- a/ash/app_list/views/assistant/dialog_plate.cc +++ b/ash/app_list/views/assistant/dialog_plate.cc
@@ -23,7 +23,6 @@ #include "ui/gfx/paint_vector_icon.h" #include "ui/views/border.h" #include "ui/views/controls/button/image_button.h" -#include "ui/views/controls/separator.h" #include "ui/views/controls/textfield/textfield.h" #include "ui/views/focus/focus_manager.h" #include "ui/views/layout/box_layout.h" @@ -35,14 +34,10 @@ // Appearance. // TODO(wutao): need to be finalized. -constexpr int kDialogLeftPaddingDip = 16; -constexpr int kDialogRightPaddingDip = 16; -constexpr int kSmallIconSizeDip = 18; +constexpr int kDialogPaddingDip = 16; constexpr int kIconSizeDip = 24; constexpr int kButtonSizeDip = 32; constexpr int kPreferredHeightDip = 48; -constexpr int kSeparatorPaddingDip = 18; -constexpr SkColor kSeparatorColor = SkColorSetA(SK_ColorBLACK, 0x1F); // Animation. constexpr base::TimeDelta kAnimationFadeInDelay = @@ -250,26 +245,11 @@ views::BoxLayout* layout_manager = SetLayoutManager(std::make_unique<views::BoxLayout>( views::BoxLayout::Orientation::kHorizontal, - gfx::Insets(0, kDialogLeftPaddingDip, 0, kDialogRightPaddingDip))); + gfx::Insets(0, kDialogPaddingDip))); layout_manager->set_cross_axis_alignment( views::BoxLayout::CrossAxisAlignment::CROSS_AXIS_ALIGNMENT_CENTER); - // Back button. - back_button_ = ash::AssistantButton::Create( - this, ash::kShelfBackIcon, kButtonSizeDip, kSmallIconSizeDip, - IDS_ASH_ASSISTANT_DIALOG_PLATE_BACK_ACCNAME, - ash::AssistantButtonId::kBackInLauncher); - AddChildView(back_button_); - - // Vertical separator. - views::Separator* separator = new views::Separator(); - separator->SetPreferredHeight(kIconSizeDip); - separator->SetColor(kSeparatorColor); - separator->SetBorder(views::CreateEmptyBorder(0, kSeparatorPaddingDip / 2, 0, - kSeparatorPaddingDip / 2)); - AddChildView(separator); - // Molecule icon. molecule_icon_ = ash::BaseLogoView::Create(); molecule_icon_->SetPreferredSize(gfx::Size(kIconSizeDip, kIconSizeDip)); @@ -376,14 +356,9 @@ // Spacer. // To make the mic icon in the center of the |assistant_page_view_| - // compensate for the width of back icon, separator, molecule icon, keyboard - // input toggle, and paddings. + // compensate for the width of molecule icon and keyboard input toggle. spacer = new views::View(); constexpr int spacing = - /*dialog_plate_padding=*/kDialogLeftPaddingDip - kDialogRightPaddingDip + - /*back_button_width=*/kButtonSizeDip + - /*separator_padding=*/kSeparatorPaddingDip + - /*separator_thickness=*/1 + /*molecule_icon_width=*/kIconSizeDip - /*keyboard_input_toggle_width*/ kButtonSizeDip; spacer->SetPreferredSize(gfx::Size(spacing, 1));
diff --git a/ash/app_list/views/assistant/dialog_plate.h b/ash/app_list/views/assistant/dialog_plate.h index 6c09146..cb47446 100644 --- a/ash/app_list/views/assistant/dialog_plate.h +++ b/ash/app_list/views/assistant/dialog_plate.h
@@ -41,8 +41,7 @@ // means by which a user converses with Assistant. To this end, DialogPlate // provides a textfield for use with the keyboard input modality, an // ActionView which serves to either commit a text query, or toggle voice -// interaction as appropriate for the user's current input modality, and a back -// button to go back in the launcher. +// interaction as appropriate for the user's current input modality. class APP_LIST_EXPORT DialogPlate : public views::View, public views::TextfieldController, @@ -87,7 +86,6 @@ ash::AssistantViewDelegate* const delegate_; - views::ImageButton* back_button_; // Owned by view hierarchy. ash::BaseLogoView* molecule_icon_; // Owned by view hierarchy. views::View* input_modality_layout_container_; // Owned by view hierarchy. views::View* keyboard_layout_container_; // Owned by view hierarchy.
diff --git a/ash/ash_strings.grd b/ash/ash_strings.grd index 3614ceb..c56787c 100644 --- a/ash/ash_strings.grd +++ b/ash/ash_strings.grd
@@ -693,6 +693,18 @@ <message name="IDS_ASH_DESKS_NEW_DESK_BUTTON" desc="The label of the new virtual desk (a.k.a. workspaces) button."> New Desk </message> + <message name="IDS_ASH_DESKS_DESK_1_MINI_VIEW_TITLE" desc="The label of the first virtual desk thumbnail."> + Desk 1 + </message> + <message name="IDS_ASH_DESKS_DESK_2_MINI_VIEW_TITLE" desc="The label of the second virtual desk thumbnail."> + Desk 2 + </message> + <message name="IDS_ASH_DESKS_DESK_3_MINI_VIEW_TITLE" desc="The label of the third virtual desk thumbnail."> + Desk 3 + </message> + <message name="IDS_ASH_DESKS_DESK_4_MINI_VIEW_TITLE" desc="The label of the fourth virtual desk thumbnail."> + Desk 4 + </message> <!-- Status tray charging strings. --> <message name="IDS_ASH_STATUS_TRAY_LOW_POWER_CHARGER_TITLE" desc="The title of a notification indicating that a low-current USB charger has been connected."> @@ -1744,9 +1756,6 @@ <message name="IDS_ASH_ASSISTANT_WINDOW" desc="The accessible description of the Assistant window."> Assistant </message> - <message name="IDS_ASH_ASSISTANT_DIALOG_PLATE_BACK_ACCNAME" desc="Accessibility name for a back image button when clicked back to previous launcher state."> - Back to launcher - </message> <message name="IDS_ASH_ASSISTANT_DIALOG_PLATE_HINT" desc="Message shown as a placeholder in Assistant's input textfield when empty."> Type a message </message>
diff --git a/ash/ash_strings_grd/IDS_ASH_DESKS_DESK_1_MINI_VIEW_TITLE.png.sha1 b/ash/ash_strings_grd/IDS_ASH_DESKS_DESK_1_MINI_VIEW_TITLE.png.sha1 new file mode 100644 index 0000000..4f0a00c --- /dev/null +++ b/ash/ash_strings_grd/IDS_ASH_DESKS_DESK_1_MINI_VIEW_TITLE.png.sha1
@@ -0,0 +1 @@ +9c31bc3f653f1232eae4eb54a4d10b7f9b417b15 \ No newline at end of file
diff --git a/ash/ash_strings_grd/IDS_ASH_DESKS_DESK_2_MINI_VIEW_TITLE.png.sha1 b/ash/ash_strings_grd/IDS_ASH_DESKS_DESK_2_MINI_VIEW_TITLE.png.sha1 new file mode 100644 index 0000000..4f0a00c --- /dev/null +++ b/ash/ash_strings_grd/IDS_ASH_DESKS_DESK_2_MINI_VIEW_TITLE.png.sha1
@@ -0,0 +1 @@ +9c31bc3f653f1232eae4eb54a4d10b7f9b417b15 \ No newline at end of file
diff --git a/ash/ash_strings_grd/IDS_ASH_DESKS_DESK_3_MINI_VIEW_TITLE.png.sha1 b/ash/ash_strings_grd/IDS_ASH_DESKS_DESK_3_MINI_VIEW_TITLE.png.sha1 new file mode 100644 index 0000000..4f0a00c --- /dev/null +++ b/ash/ash_strings_grd/IDS_ASH_DESKS_DESK_3_MINI_VIEW_TITLE.png.sha1
@@ -0,0 +1 @@ +9c31bc3f653f1232eae4eb54a4d10b7f9b417b15 \ No newline at end of file
diff --git a/ash/ash_strings_grd/IDS_ASH_DESKS_DESK_4_MINI_VIEW_TITLE.png.sha1 b/ash/ash_strings_grd/IDS_ASH_DESKS_DESK_4_MINI_VIEW_TITLE.png.sha1 new file mode 100644 index 0000000..4f0a00c --- /dev/null +++ b/ash/ash_strings_grd/IDS_ASH_DESKS_DESK_4_MINI_VIEW_TITLE.png.sha1
@@ -0,0 +1 @@ +9c31bc3f653f1232eae4eb54a4d10b7f9b417b15 \ No newline at end of file
diff --git a/ash/assistant/assistant_interaction_controller.h b/ash/assistant/assistant_interaction_controller.h index d8478a9..d5c2ee8 100644 --- a/ash/assistant/assistant_interaction_controller.h +++ b/ash/assistant/assistant_interaction_controller.h
@@ -103,9 +103,7 @@ // AssistantViewDelegateObserver: void OnDialogPlateButtonPressed(AssistantButtonId id) override; void OnDialogPlateContentsCommitted(const std::string& text) override; - - // Invoked on suggestion chip pressed event. - void OnSuggestionChipPressed(const AssistantSuggestion* suggestion); + void OnSuggestionChipPressed(const AssistantSuggestion* suggestion) override; private: bool HasUnprocessedPendingResponse();
diff --git a/ash/assistant/assistant_setup_controller.cc b/ash/assistant/assistant_setup_controller.cc index a9f66350..c339e14c 100644 --- a/ash/assistant/assistant_setup_controller.cc +++ b/ash/assistant/assistant_setup_controller.cc
@@ -44,6 +44,14 @@ assistant_setup_ = std::move(assistant_setup); } +void AssistantSetupController::OnAssistantControllerConstructed() { + assistant_controller_->view_delegate()->AddObserver(this); +} + +void AssistantSetupController::OnAssistantControllerDestroying() { + assistant_controller_->view_delegate()->RemoveObserver(this); +} + void AssistantSetupController::OnDeepLinkReceived( assistant::util::DeepLinkType type, const std::map<std::string, std::string>& params) {
diff --git a/ash/assistant/assistant_setup_controller.h b/ash/assistant/assistant_setup_controller.h index 986c261..2563aacb 100644 --- a/ash/assistant/assistant_setup_controller.h +++ b/ash/assistant/assistant_setup_controller.h
@@ -9,7 +9,7 @@ #include <string> #include "ash/assistant/assistant_controller_observer.h" -#include "ash/assistant/ui/main_stage/assistant_opt_in_view.h" +#include "ash/assistant/ui/assistant_view_delegate.h" #include "ash/public/interfaces/assistant_controller.mojom.h" #include "ash/public/interfaces/assistant_setup.mojom.h" #include "base/macros.h" @@ -21,7 +21,7 @@ class AssistantSetupController : public mojom::AssistantSetupController, public AssistantControllerObserver, - public AssistantOptInDelegate { + public AssistantViewDelegateObserver { public: explicit AssistantSetupController(AssistantController* assistant_controller); ~AssistantSetupController() override; @@ -32,11 +32,13 @@ void SetAssistantSetup(mojom::AssistantSetupPtr assistant_setup) override; // AssistantControllerObserver: + void OnAssistantControllerConstructed() override; + void OnAssistantControllerDestroying() override; void OnDeepLinkReceived( assistant::util::DeepLinkType type, const std::map<std::string, std::string>& params) override; - // AssistantOptInDelegate: + // AssistantViewDelegateObserver: void OnOptInButtonPressed() override; void StartOnboarding(bool relaunch,
diff --git a/ash/assistant/assistant_ui_controller.cc b/ash/assistant/assistant_ui_controller.cc index 0c96365..d601a62 100644 --- a/ash/assistant/assistant_ui_controller.cc +++ b/ash/assistant/assistant_ui_controller.cc
@@ -146,17 +146,6 @@ container_view_->GetWidget()->Activate(); } -void AssistantUiController::OnAssistantMiniViewPressed() { - InputModality input_modality = assistant_controller_->interaction_controller() - ->model() - ->input_modality(); - - // When not using stylus input modality, pressing the Assistant mini view - // will cause the UI to expand. - if (input_modality != InputModality::kStylus) - UpdateUiMode(AssistantUiMode::kMainUi); -} - bool AssistantUiController::OnCaptionButtonPressed(AssistantButtonId id) { switch (id) { case AssistantButtonId::kBack: @@ -178,11 +167,6 @@ // TODO(dmblack): This event doesn't need to be handled here anymore. Move it // out of AssistantUiController. void AssistantUiController::OnDialogPlateButtonPressed(AssistantButtonId id) { - if (id == AssistantButtonId::kBackInLauncher) { - CloseUi(AssistantExitPoint::kBackInLauncher); - return; - } - if (id != AssistantButtonId::kSettings) return; @@ -191,6 +175,17 @@ assistant::util::CreateAssistantSettingsDeepLink()); } +void AssistantUiController::OnMiniViewPressed() { + InputModality input_modality = assistant_controller_->interaction_controller() + ->model() + ->input_modality(); + + // When not using stylus input modality, pressing the Assistant mini view + // will cause the UI to expand. + if (input_modality != InputModality::kStylus) + UpdateUiMode(AssistantUiMode::kMainUi); +} + void AssistantUiController::OnHighlighterEnabledChanged( HighlighterEnabledState state) { // TODO(wutao): Behavior is not defined.
diff --git a/ash/assistant/assistant_ui_controller.h b/ash/assistant/assistant_ui_controller.h index 6034e0fc..e6a6131 100644 --- a/ash/assistant/assistant_ui_controller.h +++ b/ash/assistant/assistant_ui_controller.h
@@ -15,10 +15,8 @@ #include "ash/assistant/model/assistant_screen_context_model_observer.h" #include "ash/assistant/model/assistant_ui_model.h" #include "ash/assistant/model/assistant_ui_model_observer.h" -#include "ash/assistant/ui/assistant_mini_view.h" #include "ash/assistant/ui/assistant_view_delegate.h" #include "ash/assistant/ui/caption_bar.h" -#include "ash/assistant/ui/dialog_plate/dialog_plate.h" #include "ash/highlighter/highlighter_controller.h" #include "base/macros.h" #include "base/optional.h" @@ -53,7 +51,6 @@ public AssistantInteractionModelObserver, public AssistantScreenContextModelObserver, public AssistantUiModelObserver, - public AssistantMiniViewDelegate, public AssistantViewDelegateObserver, public CaptionBarDelegate, public HighlighterController::Observer, @@ -88,14 +85,12 @@ void OnScreenContextRequestStateChanged( ScreenContextRequestState request_state) override; - // AssistantMiniViewDelegate: - void OnAssistantMiniViewPressed() override; - // CaptionBarDelegate: bool OnCaptionButtonPressed(AssistantButtonId id) override; // AssistantViewDelegateObserver: void OnDialogPlateButtonPressed(AssistantButtonId id) override; + void OnMiniViewPressed() override; // HighlighterController::Observer: void OnHighlighterEnabledChanged(HighlighterEnabledState state) override;
diff --git a/ash/assistant/assistant_view_delegate_impl.cc b/ash/assistant/assistant_view_delegate_impl.cc index b811530..cc263c9 100644 --- a/ash/assistant/assistant_view_delegate_impl.cc +++ b/ash/assistant/assistant_view_delegate_impl.cc
@@ -105,14 +105,6 @@ return assistant_controller_->ui_controller(); } -AssistantMiniViewDelegate* AssistantViewDelegateImpl::GetMiniViewDelegate() { - return assistant_controller_->ui_controller(); -} - -AssistantOptInDelegate* AssistantViewDelegateImpl::GetOptInDelegate() { - return assistant_controller_->setup_controller(); -} - void AssistantViewDelegateImpl::DownloadImage( const GURL& url, mojom::AssistantImageDownloader::DownloadCallback callback) { @@ -157,6 +149,11 @@ observer.OnDialogPlateContentsCommitted(text); } +void AssistantViewDelegateImpl::OnMiniViewPressed() { + for (auto& observer : view_delegate_observers_) + observer.OnMiniViewPressed(); +} + void AssistantViewDelegateImpl::OnNotificationButtonPressed( const std::string& notification_id, int notification_button_index) { @@ -164,10 +161,15 @@ notification_id, notification_button_index, /*reply=*/base::nullopt); } +void AssistantViewDelegateImpl::OnOptInButtonPressed() { + for (auto& observer : view_delegate_observers_) + observer.OnOptInButtonPressed(); +} + void AssistantViewDelegateImpl::OnSuggestionChipPressed( const AssistantSuggestion* suggestion) { - assistant_controller_->interaction_controller()->OnSuggestionChipPressed( - suggestion); + for (AssistantViewDelegateObserver& observer : view_delegate_observers_) + observer.OnSuggestionChipPressed(suggestion); } void AssistantViewDelegateImpl::OpenUrlFromView(const GURL& url) {
diff --git a/ash/assistant/assistant_view_delegate_impl.h b/ash/assistant/assistant_view_delegate_impl.h index 212f16c..ca21607 100644 --- a/ash/assistant/assistant_view_delegate_impl.h +++ b/ash/assistant/assistant_view_delegate_impl.h
@@ -46,8 +46,6 @@ void RemoveVoiceInteractionControllerObserver( DefaultVoiceInteractionObserver* observer) override; CaptionBarDelegate* GetCaptionBarDelegate() override; - AssistantMiniViewDelegate* GetMiniViewDelegate() override; - AssistantOptInDelegate* GetOptInDelegate() override; void DownloadImage( const GURL& url, mojom::AssistantImageDownloader::DownloadCallback callback) override; @@ -59,8 +57,10 @@ bool IsTabletMode() const override; void OnDialogPlateButtonPressed(AssistantButtonId id) override; void OnDialogPlateContentsCommitted(const std::string& text) override; + void OnMiniViewPressed() override; void OnNotificationButtonPressed(const std::string& notification_id, int notification_button_index) override; + void OnOptInButtonPressed() override; void OnSuggestionChipPressed(const AssistantSuggestion* suggestion) override; void OpenUrlFromView(const GURL& url) override;
diff --git a/ash/assistant/model/assistant_ui_model.h b/ash/assistant/model/assistant_ui_model.h index 2e4b61c..a4974aa 100644 --- a/ash/assistant/model/assistant_ui_model.h +++ b/ash/assistant/model/assistant_ui_model.h
@@ -78,8 +78,8 @@ kKeyboardInputToggle = 4, kVoiceInputToggle = 5, kSettings = 6, - kBackInLauncher = 7, - kMaxValue = kBackInLauncher + kBackInLauncherDeprecated = 7, + kMaxValue = kBackInLauncherDeprecated }; // Models the Assistant UI.
diff --git a/ash/assistant/ui/assistant_container_view.cc b/ash/assistant/ui/assistant_container_view.cc index 7c77f1c4..083a107 100644 --- a/ash/assistant/ui/assistant_container_view.cc +++ b/ash/assistant/ui/assistant_container_view.cc
@@ -348,8 +348,6 @@ // Mini view. assistant_mini_view_ = new AssistantMiniView(delegate_); - assistant_mini_view_->set_mini_view_delegate( - delegate_->GetMiniViewDelegate()); AddChildView(assistant_mini_view_); // Web view.
diff --git a/ash/assistant/ui/assistant_mini_view.cc b/ash/assistant/ui/assistant_mini_view.cc index da7af5e..17728d1e 100644 --- a/ash/assistant/ui/assistant_mini_view.cc +++ b/ash/assistant/ui/assistant_mini_view.cc
@@ -97,8 +97,7 @@ void AssistantMiniView::ButtonPressed(views::Button* sender, const ui::Event& event) { - if (mini_view_delegate_) - mini_view_delegate_->OnAssistantMiniViewPressed(); + delegate_->OnMiniViewPressed(); } void AssistantMiniView::OnInputModalityChanged(InputModality input_modality) {
diff --git a/ash/assistant/ui/assistant_mini_view.h b/ash/assistant/ui/assistant_mini_view.h index 4280cc5..3854596b 100644 --- a/ash/assistant/ui/assistant_mini_view.h +++ b/ash/assistant/ui/assistant_mini_view.h
@@ -23,19 +23,6 @@ class AssistantViewDelegate; -// AssistantMiniViewDelegate --------------------------------------------------- - -// TODO(wutao): Remove this class and call methods on AssistantViewDelegate -// derectly. -class COMPONENT_EXPORT(ASSISTANT_UI) AssistantMiniViewDelegate { - public: - // Invoked when the AssistantMiniView is pressed. - virtual void OnAssistantMiniViewPressed() {} - - protected: - virtual ~AssistantMiniViewDelegate() = default; -}; - // AssistantMiniView ----------------------------------------------------------- class COMPONENT_EXPORT(ASSISTANT_UI) AssistantMiniView @@ -68,10 +55,6 @@ base::Optional<AssistantEntryPoint> entry_point, base::Optional<AssistantExitPoint> exit_point) override; - void set_mini_view_delegate(AssistantMiniViewDelegate* delegate) { - mini_view_delegate_ = delegate; - } - private: void InitLayout(); void UpdatePrompt(); @@ -79,8 +62,6 @@ AssistantViewDelegate* const delegate_; views::Label* label_; // Owned by view hierarchy. - AssistantMiniViewDelegate* mini_view_delegate_ = nullptr; - // The most recent active query for the current Assistant UI session. If there // has been no active query for the current UI session, this is empty. base::Optional<std::string> last_active_query_;
diff --git a/ash/assistant/ui/assistant_view_delegate.h b/ash/assistant/ui/assistant_view_delegate.h index 53da6de..540d79a 100644 --- a/ash/assistant/ui/assistant_view_delegate.h +++ b/ash/assistant/ui/assistant_view_delegate.h
@@ -39,6 +39,8 @@ class COMPONENT_EXPORT(ASSISTANT_UI) AssistantViewDelegateObserver : public base::CheckedObserver { public: + using AssistantSuggestion = chromeos::assistant::mojom::AssistantSuggestion; + // Invoked when Assistant has received a deep link of the specified |type| // with the given |params|. virtual void OnDeepLinkReceived( @@ -50,6 +52,15 @@ // Invoked when the dialog plate contents have been committed. virtual void OnDialogPlateContentsCommitted(const std::string& text) {} + + // Invoked when the mini view is pressed. + virtual void OnMiniViewPressed() {} + + // Invoked when the opt in button is pressed. + virtual void OnOptInButtonPressed() {} + + // Invoked when a suggestion chip is pressed. + virtual void OnSuggestionChipPressed(const AssistantSuggestion* suggestion) {} }; // A delegate of views in assistant/ui that handles views related actions e.g. @@ -110,12 +121,6 @@ // Gets the caption bar delegate associated with the view delegate. virtual CaptionBarDelegate* GetCaptionBarDelegate() = 0; - // Gets the mini view delegate associated with the view delegate. - virtual AssistantMiniViewDelegate* GetMiniViewDelegate() = 0; - - // Gets the opt in delegate associated with the view delegate. - virtual AssistantOptInDelegate* GetOptInDelegate() = 0; - // Downloads the image found at the specified |url|. On completion, the // supplied |callback| will be run with the downloaded image. If the download // attempt is unsuccessful, a NULL image is returned. @@ -146,10 +151,16 @@ // Invoked when the dialog plate contents have been committed. virtual void OnDialogPlateContentsCommitted(const std::string& text) = 0; + // Invoked when the mini view is pressed. + virtual void OnMiniViewPressed() = 0; + // Invoked when an in-Assistant notification button is pressed. virtual void OnNotificationButtonPressed(const std::string& notification_id, int notification_button_index) = 0; + // Invoked when the opt in button is pressed. + virtual void OnOptInButtonPressed() {} + // Invoked when suggestion chip is pressed. virtual void OnSuggestionChipPressed( const AssistantSuggestion* suggestion) = 0;
diff --git a/ash/assistant/ui/main_stage/assistant_opt_in_view.cc b/ash/assistant/ui/main_stage/assistant_opt_in_view.cc index ee5e9b5..1f19769 100644 --- a/ash/assistant/ui/main_stage/assistant_opt_in_view.cc +++ b/ash/assistant/ui/main_stage/assistant_opt_in_view.cc
@@ -36,12 +36,10 @@ } base::string16 GetAction(mojom::ConsentStatus consent_status) { - if (consent_status == mojom::ConsentStatus::kUnauthorized) { - return l10n_util::GetStringUTF16( - IDS_ASH_ASSISTANT_OPT_IN_ASK_ADMINISTRATOR); - } else { - return l10n_util::GetStringUTF16(IDS_ASH_ASSISTANT_OPT_IN_GET_STARTED); - } + return consent_status == mojom::ConsentStatus::kUnauthorized + ? l10n_util::GetStringUTF16( + IDS_ASH_ASSISTANT_OPT_IN_ASK_ADMINISTRATOR) + : l10n_util::GetStringUTF16(IDS_ASH_ASSISTANT_OPT_IN_GET_STARTED); } // AssistantOptInContainer ----------------------------------------------------- @@ -109,6 +107,16 @@ label_->SizeToFit(width()); } +void AssistantOptInView::ButtonPressed(views::Button* sender, + const ui::Event& event) { + delegate_->OnOptInButtonPressed(); +} + +void AssistantOptInView::OnVoiceInteractionConsentStatusUpdated( + mojom::ConsentStatus consent_status) { + UpdateLabel(consent_status); +} + void AssistantOptInView::InitLayout() { views::BoxLayout* layout_manager = SetLayoutManager(std::make_unique<views::BoxLayout>( @@ -172,14 +180,4 @@ container_->SetAccessibleName(label_text); } -void AssistantOptInView::ButtonPressed(views::Button* sender, - const ui::Event& event) { - delegate_->GetOptInDelegate()->OnOptInButtonPressed(); -} - -void AssistantOptInView::OnVoiceInteractionConsentStatusUpdated( - mojom::ConsentStatus consent_status) { - UpdateLabel(consent_status); -} - } // namespace ash
diff --git a/ash/assistant/ui/main_stage/assistant_opt_in_view.h b/ash/assistant/ui/main_stage/assistant_opt_in_view.h index b69e2aa..69ba51f 100644 --- a/ash/assistant/ui/main_stage/assistant_opt_in_view.h +++ b/ash/assistant/ui/main_stage/assistant_opt_in_view.h
@@ -19,17 +19,6 @@ class AssistantViewDelegate; -// AssistantOptInDelegate ------------------------------------------------------ - -class COMPONENT_EXPORT(ASSISTANT_UI) AssistantOptInDelegate { - public: - // Invoked when the Assistant opt in button is pressed. - virtual void OnOptInButtonPressed() = 0; - - protected: - virtual ~AssistantOptInDelegate() = default; -}; - // AssistantOptInView ---------------------------------------------------------- class COMPONENT_EXPORT(ASSISTANT_UI) AssistantOptInView
diff --git a/ash/assistant/ui/main_stage/suggestion_container_view.cc b/ash/assistant/ui/main_stage/suggestion_container_view.cc index 218ed367..5d54828 100644 --- a/ash/assistant/ui/main_stage/suggestion_container_view.cc +++ b/ash/assistant/ui/main_stage/suggestion_container_view.cc
@@ -181,7 +181,6 @@ sender->id()); } - // TODO(dmblack): Use a delegate pattern here similar to CaptionBar. delegate_->OnSuggestionChipPressed(suggestion); }
diff --git a/ash/autoclick/autoclick_controller.cc b/ash/autoclick/autoclick_controller.cc index e6ee08d0..d9a3a46 100644 --- a/ash/autoclick/autoclick_controller.cc +++ b/ash/autoclick/autoclick_controller.cc
@@ -15,9 +15,11 @@ #include "ash/system/status_area_widget.h" #include "ash/wm/root_window_finder.h" #include "base/bind.h" +#include "base/command_line.h" #include "base/metrics/histogram_macros.h" #include "base/metrics/user_metrics.h" #include "base/timer/timer.h" +#include "ui/accessibility/accessibility_switches.h" #include "ui/aura/window_tree_host.h" #include "ui/events/event.h" #include "ui/events/event_sink.h" @@ -79,6 +81,7 @@ Shell::GetPrimaryRootWindow()->GetHost()->GetEventSource()->AddEventRewriter( drag_event_rewriter_.get()); InitClickTimers(); + UpdateRingSize(); } AutoclickController::~AutoclickController() { @@ -139,6 +142,11 @@ event_type_ = type; } +void AutoclickController::SetMovementThreshold(int movement_threshold) { + movement_threshold_ = movement_threshold; + UpdateRingSize(); +} + void AutoclickController::CreateAutoclickRingWidget( const gfx::Point& point_in_screen) { aura::Window* target = ash::wm::GetRootWindowAt(point_in_screen); @@ -329,6 +337,15 @@ } } +void AutoclickController::UpdateRingSize() { + if (!base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kEnableExperimentalAccessibilityAutoclick)) { + return; + } + autoclick_ring_handler_->SetSize(movement_threshold_, + movement_threshold_ + 10); +} + bool AutoclickController::DragInProgress() const { return event_type_ == mojom::AutoclickEventType::kDragAndDrop && drag_event_rewriter_->IsEnabled();
diff --git a/ash/autoclick/autoclick_controller.h b/ash/autoclick/autoclick_controller.h index dbc5022..ef85ba3f 100644 --- a/ash/autoclick/autoclick_controller.h +++ b/ash/autoclick/autoclick_controller.h
@@ -52,17 +52,15 @@ // Sets the event type. void SetAutoclickEventType(mojom::AutoclickEventType type); + // Sets the movement threshold beyond which mouse movements cancel or begin + // a new Autoclick event. + void SetMovementThreshold(int movement_threshold); + // Sets whether to revert to a left click after any other event type. void set_revert_to_left_click(bool revert_to_left_click) { revert_to_left_click_ = revert_to_left_click; } - // Sets the movement threshold beyond which mouse movements cancel or begin - // a new Autoclick event. - void set_movement_threshold(int movement_threshold) { - movement_threshold_ = movement_threshold; - } - // Functionality for testing. static float GetStartGestureDelayRatioForTesting(); @@ -77,6 +75,7 @@ void OnActionCompleted(mojom::AutoclickEventType event_type); void InitClickTimers(); void UpdateRingWidget(const gfx::Point& mouse_location); + void UpdateRingSize(); void RecordUserAction(mojom::AutoclickEventType event_type) const; bool DragInProgress() const;
diff --git a/ash/autoclick/autoclick_ring_handler.cc b/ash/autoclick/autoclick_ring_handler.cc index 67f2bdf2..85d6579 100644 --- a/ash/autoclick/autoclick_ring_handler.cc +++ b/ash/autoclick/autoclick_ring_handler.cc
@@ -16,6 +16,7 @@ namespace ash { namespace { +// The default values of the autoclick ring widget size. const int kAutoclickRingOuterRadius = 30; const int kAutoclickRingInnerRadius = 20; @@ -79,11 +80,15 @@ class AutoclickRingHandler::AutoclickRingView : public views::View { public: AutoclickRingView(const gfx::Point& event_location, - views::Widget* ring_widget) + views::Widget* ring_widget, + int outer_radius, + int inner_radius) : views::View(), widget_(ring_widget), current_angle_(kAutoclickRingAngleStartValue), - current_scale_(kAutoclickRingScaleStartValue) { + current_scale_(kAutoclickRingScaleStartValue), + outer_radius_(outer_radius), + inner_radius_(inner_radius) { widget_->SetContentsView(this); // We are owned by the AutoclickRingHandler. @@ -95,10 +100,10 @@ void SetNewLocation(const gfx::Point& new_event_location) { gfx::Point point = new_event_location; - widget_->SetBounds(gfx::Rect( - point.x() - (kAutoclickRingOuterRadius + kAutoclickRingGlowWidth), - point.y() - (kAutoclickRingOuterRadius + kAutoclickRingGlowWidth), - GetPreferredSize().width(), GetPreferredSize().height())); + widget_->SetBounds( + gfx::Rect(point.x() - (outer_radius_ + kAutoclickRingGlowWidth), + point.y() - (outer_radius_ + kAutoclickRingGlowWidth), + GetPreferredSize().width(), GetPreferredSize().height())); widget_->Show(); widget_->GetNativeView()->layer()->SetOpacity( kAutoclickRingOpacityStartValue); @@ -127,11 +132,16 @@ SchedulePaint(); } + void SetSize(int outer_radius, int inner_radius) { + outer_radius_ = outer_radius; + inner_radius_ = inner_radius; + } + private: // Overridden from views::View. gfx::Size CalculatePreferredSize() const override { - return gfx::Size(2 * (kAutoclickRingOuterRadius + kAutoclickRingGlowWidth), - 2 * (kAutoclickRingOuterRadius + kAutoclickRingGlowWidth)); + return gfx::Size(2 * (outer_radius_ + kAutoclickRingGlowWidth), + 2 * (outer_radius_ + kAutoclickRingGlowWidth)); } void OnPaint(gfx::Canvas* canvas) override { @@ -147,10 +157,10 @@ canvas->Translate(-center.OffsetFromOrigin()); // Paint inner circle. - PaintAutoclickRingArc(canvas, center, kAutoclickRingInnerRadius, + PaintAutoclickRingArc(canvas, center, inner_radius_, kAutoclickRingInnerStartAngle, current_angle_); // Paint outer circle. - PaintAutoclickRingCircle(canvas, center, kAutoclickRingOuterRadius); + PaintAutoclickRingCircle(canvas, center, outer_radius_); canvas->Restore(); } @@ -158,6 +168,8 @@ views::Widget* widget_; int current_angle_; double current_scale_; + int outer_radius_; + int inner_radius_; DISALLOW_COPY_AND_ASSIGN(AutoclickRingView); }; @@ -168,7 +180,9 @@ AutoclickRingHandler::AutoclickRingHandler() : gfx::LinearAnimation(nullptr), ring_widget_(nullptr), - current_animation_type_(AnimationType::NONE) {} + current_animation_type_(AnimationType::NONE), + outer_radius_(kAutoclickRingOuterRadius), + inner_radius_(kAutoclickRingInnerRadius) {} AutoclickRingHandler::~AutoclickRingHandler() { StopAutoclickRing(); @@ -196,19 +210,28 @@ tap_down_location_ = center_point_in_screen; ring_widget_ = widget; } + +void AutoclickRingHandler::SetSize(int outer_radius, int inner_radius) { + outer_radius_ = outer_radius; + inner_radius_ = inner_radius; + if (view_) + view_->SetSize(outer_radius, inner_radius); +} //////////////////////////////////////////////////////////////////////////////// // AutoclickRingHandler, private void AutoclickRingHandler::StartAnimation(base::TimeDelta delay) { switch (current_animation_type_) { case AnimationType::GROW_ANIMATION: { - view_.reset(new AutoclickRingView(tap_down_location_, ring_widget_)); + view_.reset(new AutoclickRingView(tap_down_location_, ring_widget_, + outer_radius_, inner_radius_)); SetDuration(delay); Start(); break; } case AnimationType::SHRINK_ANIMATION: { - view_.reset(new AutoclickRingView(tap_down_location_, ring_widget_)); + view_.reset(new AutoclickRingView(tap_down_location_, ring_widget_, + outer_radius_, inner_radius_)); SetDuration(delay); Start(); break;
diff --git a/ash/autoclick/autoclick_ring_handler.h b/ash/autoclick/autoclick_ring_handler.h index c17a565a..7d624f9 100644 --- a/ash/autoclick/autoclick_ring_handler.h +++ b/ash/autoclick/autoclick_ring_handler.h
@@ -28,6 +28,8 @@ void SetGestureCenter(const gfx::Point& center_point_in_screen, views::Widget* widget); + void SetSize(int outer_radius, int inner_radius); + private: class AutoclickRingView; @@ -51,6 +53,8 @@ gfx::Point tap_down_location_; AnimationType current_animation_type_; base::TimeDelta animation_duration_; + int outer_radius_; + int inner_radius_; DISALLOW_COPY_AND_ASSIGN(AutoclickRingHandler); };
diff --git a/ash/autoclick/autoclick_unittest.cc b/ash/autoclick/autoclick_unittest.cc index 62ab94a..900d90e 100644 --- a/ash/autoclick/autoclick_unittest.cc +++ b/ash/autoclick/autoclick_unittest.cc
@@ -222,7 +222,7 @@ // Try at a couple different thresholds. for (int movement_threshold = 10; movement_threshold < 50; movement_threshold += 10) { - GetAutoclickController()->set_movement_threshold(movement_threshold); + GetAutoclickController()->SetMovementThreshold(movement_threshold); // Run test for the secondary display too to test fix for crbug.com/449870. for (auto* root_window : root_windows) { @@ -256,7 +256,7 @@ } // Reset to default threshold. - GetAutoclickController()->set_movement_threshold(20); + GetAutoclickController()->SetMovementThreshold(20); } TEST_F(AutoclickTest, SingleKeyModifier) {
diff --git a/ash/display/window_tree_host_manager.cc b/ash/display/window_tree_host_manager.cc index 1a17ba6..40f815a 100644 --- a/ash/display/window_tree_host_manager.cc +++ b/ash/display/window_tree_host_manager.cc
@@ -112,6 +112,14 @@ return width >= 3000 ? "1024" : "512"; } +// Returns the Shell's WindowService instance or nullptr if Shell's +// |window_service_owner_| is not yet created. +ws::WindowService* GetWindowService() { + return Shell::Get()->window_service_owner() + ? Shell::Get()->window_service_owner()->window_service() + : nullptr; +} + } // namespace // A utility class to store/restore focused/active window @@ -600,15 +608,14 @@ // Shell creates |window_service_owner_| from Shell::Init(), but this // function may be called before |window_service_owner_| is created. It's safe // to ignore the call in this case as no clients have connected yet. - ws::WindowService* window_service = - Shell::Get()->window_service_owner() - ? Shell::Get()->window_service_owner()->window_service() - : nullptr; - if (window_service) + if (auto* window_service = GetWindowService()) window_service->OnDisplayMetricsChanged(display, metrics); + if (!(metrics & (DISPLAY_METRIC_BOUNDS | DISPLAY_METRIC_ROTATION | - DISPLAY_METRIC_DEVICE_SCALE_FACTOR))) + DISPLAY_METRIC_DEVICE_SCALE_FACTOR))) { return; + } + const display::ManagedDisplayInfo& display_info = GetDisplayManager()->GetDisplayInfo(display.id()); DCHECK(!display_info.bounds_in_native().IsEmpty()); @@ -721,6 +728,10 @@ for (auto& observer : observers_) observer.OnWindowTreeHostsSwappedDisplays(primary_host, non_primary_host); + if (auto* window_service = GetWindowService()) { + window_service->OnWindowTreeHostsSwappedDisplays(primary_window, + non_primary_window); + } const display::DisplayLayout& layout = GetDisplayManager()->GetCurrentDisplayLayout();
diff --git a/ash/display/window_tree_host_manager_unittest.cc b/ash/display/window_tree_host_manager_unittest.cc index fe85b10..0b71c1e9 100644 --- a/ash/display/window_tree_host_manager_unittest.cc +++ b/ash/display/window_tree_host_manager_unittest.cc
@@ -22,6 +22,7 @@ #include "base/command_line.h" #include "base/run_loop.h" #include "base/test/scoped_feature_list.h" +#include "services/ws/test_window_tree_client.h" #include "ui/aura/client/focus_change_observer.h" #include "ui/aura/client/focus_client.h" #include "ui/aura/env.h" @@ -1086,6 +1087,52 @@ } } +// Tests that SetPrimaryDisplayId updates the Window Service client. +TEST_F(WindowTreeHostManagerTest, SetPrimaryDisplayIdUpdateWSClientDisplayId) { + // Create two displays. + UpdateDisplay("200x200,300x300"); + ASSERT_EQ(2200000000, display::Screen::GetScreen()->GetPrimaryDisplay().id()); + int64_t non_primary_display_id = + display_manager()->GetSecondaryDisplay().id(); + ASSERT_EQ(2200000001, non_primary_display_id); + + std::vector<ws::Change>* ws_client_changes = + GetTestWindowTreeClient()->tracker()->changes(); + + // Create the first window (0,1) on primary display 2200000000. + ws_client_changes->clear(); + std::unique_ptr<aura::Window> window_in_primary = + CreateTestWindow(gfx::Rect(0, 0, 10, 20)); + auto iter = FirstChangeOfType(*ws_client_changes, + ws::CHANGE_TYPE_ON_TOP_LEVEL_CREATED); + ASSERT_NE(iter, ws_client_changes->end()); + ASSERT_EQ(1, static_cast<int>(iter->window_id)); + ASSERT_EQ(2200000000, iter->display_id); + + // Create the second window (0,2) on non-primary display 2200000001. + ws_client_changes->clear(); + std::unique_ptr<aura::Window> window_in_non_primary = + CreateTestWindow(gfx::Rect(300, 0, 30, 40)); + iter = FirstChangeOfType(*ws_client_changes, + ws::CHANGE_TYPE_ON_TOP_LEVEL_CREATED); + ASSERT_NE(iter, ws_client_changes->end()); + ASSERT_EQ(2, static_cast<int>(iter->window_id)); + ASSERT_EQ(2200000001, iter->display_id); + + // Set primary display id to the non-primary 2200000001. This triggers + // swapping of WindowTreeHosts and client should receive updates about the + // display id change. + ws_client_changes->clear(); + Shell::Get()->window_tree_host_manager()->SetPrimaryDisplayId( + non_primary_display_id); + EXPECT_TRUE( + ContainsChange(*ws_client_changes, + "DisplayChanged window_id=0,1 display_id=2200000001")); + EXPECT_TRUE( + ContainsChange(*ws_client_changes, + "DisplayChanged window_id=0,2 display_id=2200000000")); +} + TEST_F(WindowTreeHostManagerTest, OverscanInsets) { WindowTreeHostManager* window_tree_host_manager = Shell::Get()->window_tree_host_manager();
diff --git a/ash/resources/vector_icons/BUILD.gn b/ash/resources/vector_icons/BUILD.gn index 01de1b7..bcbbf0a 100644 --- a/ash/resources/vector_icons/BUILD.gn +++ b/ash/resources/vector_icons/BUILD.gn
@@ -19,6 +19,8 @@ "autoclick_pause.icon", "captive_portal.icon", "check_circle.icon", + "desks_close_desk_button.icon", + "desks_new_desk_button.icon", "dictation_menu.icon", "dictation_off.icon", "dictation_off_newui.icon", @@ -61,7 +63,6 @@ "network_ethernet.icon", "network_mobile_not_connected_x.icon", "network_vpn.icon", - "new_desk_button.icon", "notification_accessibility.icon", "notification_accessibility_braille.icon", "notification_battery_critical.icon",
diff --git a/ash/resources/vector_icons/desks_close_desk_button.icon b/ash/resources/vector_icons/desks_close_desk_button.icon new file mode 100644 index 0000000..f721d41 --- /dev/null +++ b/ash/resources/vector_icons/desks_close_desk_button.icon
@@ -0,0 +1,18 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +CANVAS_DIMENSIONS, 24, +MOVE_TO, 19, 6.41f, +LINE_TO, 17.59f, 5, +LINE_TO, 12, 10.59f, +LINE_TO, 6.41f, 5, +LINE_TO, 5, 6.41f, +LINE_TO, 10.59f, 12, +LINE_TO, 5, 17.59f, +LINE_TO, 6.41f, 19, +LINE_TO, 12, 13.41f, +LINE_TO, 17.59f, 19, +LINE_TO, 19, 17.59f, +LINE_TO, 13.41f, 12, +CLOSE
diff --git a/ash/resources/vector_icons/new_desk_button.icon b/ash/resources/vector_icons/desks_new_desk_button.icon similarity index 100% rename from ash/resources/vector_icons/new_desk_button.icon rename to ash/resources/vector_icons/desks_new_desk_button.icon
diff --git a/ash/shelf/shelf_unittest.cc b/ash/shelf/shelf_unittest.cc index 79ac807f..fecdab0 100644 --- a/ash/shelf/shelf_unittest.cc +++ b/ash/shelf/shelf_unittest.cc
@@ -7,6 +7,7 @@ #include "ash/public/cpp/shelf_model.h" #include "ash/root_window_controller.h" #include "ash/session/test_session_controller_client.h" +#include "ash/shelf/overflow_button.h" #include "ash/shelf/shelf.h" #include "ash/shelf/shelf_app_button.h" #include "ash/shelf/shelf_controller.h" @@ -30,12 +31,13 @@ void SetUp() override { AshTestBase::SetUp(); - ShelfView* shelf_view = GetPrimaryShelf()->GetShelfViewForTesting(); - shelf_model_ = shelf_view->model(); + shelf_view_ = GetPrimaryShelf()->GetShelfViewForTesting(); + shelf_model_ = shelf_view_->model(); - test_.reset(new ShelfViewTestAPI(shelf_view)); + test_.reset(new ShelfViewTestAPI(shelf_view_)); } + ShelfView* shelf_view() { return shelf_view_; } ShelfModel* shelf_model() { return shelf_model_; } ShelfViewTestAPI* test_api() { return test_.get(); } @@ -48,6 +50,7 @@ } private: + ShelfView* shelf_view_ = nullptr; ShelfModel* shelf_model_ = nullptr; std::unique_ptr<ShelfViewTestAPI> test_; @@ -104,7 +107,7 @@ ShelfItem item; item.type = TYPE_APP; item.status = STATUS_RUNNING; - while (!test_api()->IsOverflowButtonVisible()) { + while (!shelf_view()->GetOverflowButton()->visible()) { item.id = ShelfID(base::NumberToString(shelf_model()->item_count())); shelf_model()->Add(item); ASSERT_LT(shelf_model()->item_count(), 10000);
diff --git a/ash/shelf/shelf_view_test_api.cc b/ash/shelf/shelf_view_test_api.cc index 8976f940f..14403a9a 100644 --- a/ash/shelf/shelf_view_test_api.cc +++ b/ash/shelf/shelf_view_test_api.cc
@@ -59,18 +59,6 @@ return shelf_view_->view_model_->view_at(index); } -int ShelfViewTestAPI::GetFirstVisibleIndex() { - return shelf_view_->first_visible_index_; -} - -int ShelfViewTestAPI::GetLastVisibleIndex() { - return shelf_view_->last_visible_index_; -} - -bool ShelfViewTestAPI::IsOverflowButtonVisible() { - return shelf_view_->overflow_button_->visible(); -} - void ShelfViewTestAPI::ShowOverflowBubble() { DCHECK(!shelf_view_->IsShowingOverflowBubble()); shelf_view_->ToggleOverflowBubble(); @@ -81,10 +69,6 @@ shelf_view_->ToggleOverflowBubble(); } -bool ShelfViewTestAPI::IsShowingOverflowBubble() const { - return shelf_view_->IsShowingOverflowBubble(); -} - const gfx::Rect& ShelfViewTestAPI::GetBoundsByIndex(int index) { return shelf_view_->view_model_->view_at(index)->bounds(); } @@ -135,10 +119,6 @@ return shelf_view_->overflow_bubble_.get(); } -OverflowButton* ShelfViewTestAPI::overflow_button() const { - return shelf_view_->overflow_button_; -} - ShelfTooltipManager* ShelfViewTestAPI::tooltip_manager() { return &shelf_view_->tooltip_; }
diff --git a/ash/shelf/shelf_view_test_api.h b/ash/shelf/shelf_view_test_api.h index f70c7fa..ac633791 100644 --- a/ash/shelf/shelf_view_test_api.h +++ b/ash/shelf/shelf_view_test_api.h
@@ -20,7 +20,6 @@ namespace ash { class OverflowBubble; -class OverflowButton; class ShelfAppButton; class ShelfButtonPressedMetricTracker; class ShelfTooltipManager; @@ -42,28 +41,16 @@ // Retrieve the view at |index|. views::View* GetViewAt(int index); - // First visible button index. - int GetFirstVisibleIndex(); - - // Last visible button index. - int GetLastVisibleIndex(); - // Gets current/ideal bounds for button at |index|. const gfx::Rect& GetBoundsByIndex(int index); const gfx::Rect& GetIdealBoundsByIndex(int index); - // Returns true if overflow button is visible. - bool IsOverflowButtonVisible(); - // Makes shelf view show its overflow bubble. void ShowOverflowBubble(); // Makes shelf view hide its overflow bubble. void HideOverflowBubble(); - // Returns true if the overflow bubble is visible. - bool IsShowingOverflowBubble() const; - // An accessor for the |bounds_animator_| duration. int GetAnimationDuration() const; @@ -91,9 +78,6 @@ // An accessor for overflow bubble. OverflowBubble* overflow_bubble(); - // An accessor for overflow button. - OverflowButton* overflow_button() const; - // Returns minimum distance before drag starts. int GetMinimumDragDistance() const;
diff --git a/ash/shelf/shelf_view_unittest.cc b/ash/shelf/shelf_view_unittest.cc index 568b350d..99b7ed55 100644 --- a/ash/shelf/shelf_view_unittest.cc +++ b/ash/shelf/shelf_view_unittest.cc
@@ -355,7 +355,7 @@ } void VerifyShelfItemBoundsAreValid() { - for (int i = 0; i <= test_api_->GetLastVisibleIndex(); ++i) { + for (int i = 0; i <= shelf_view_->last_visible_index(); ++i) { if (test_api_->GetButton(i)) { gfx::Rect shelf_view_bounds = shelf_view_->GetLocalBounds(); gfx::Rect item_bounds = test_api_->GetBoundsByIndex(i); @@ -511,7 +511,7 @@ void AddButtonsUntilOverflow() { int items_added = 0; - while (!test_api_->IsOverflowButtonVisible()) { + while (!shelf_view_->GetOverflowButton()->visible()) { AddAppShortcut(); ++items_added; ASSERT_LT(items_added, 10000); @@ -526,10 +526,11 @@ void TestDraggingAnItemFromShelfToOtherShelf(bool main_to_overflow, bool cancel) { test_api_->ShowOverflowBubble(); - ASSERT_TRUE(test_api_->IsShowingOverflowBubble()); + ASSERT_TRUE(shelf_view_->IsShowingOverflowBubble()); ShelfViewTestAPI test_api_for_overflow( test_api_->overflow_bubble()->bubble_view()->shelf_view()); + const ShelfView* overflow_shelf_view = shelf_view_->overflow_shelf(); int total_item_count = model_->item_count(); @@ -537,24 +538,29 @@ // completed. These ids are set assuming the both the main shelf and // overflow shelf has more than 3 items. ShelfID last_visible_item_id_in_shelf = - GetItemId(test_api_->GetLastVisibleIndex()); + GetItemId(shelf_view_->last_visible_index()); ShelfID second_last_visible_item_id_in_shelf = - GetItemId(test_api_->GetLastVisibleIndex() - 1); + GetItemId(shelf_view_->last_visible_index() - 1); ShelfID first_visible_item_id_in_overflow = - GetItemId(test_api_for_overflow.GetFirstVisibleIndex()); + GetItemId(overflow_shelf_view->first_visible_index()); ShelfID second_last_visible_item_id_in_overflow = - GetItemId(test_api_for_overflow.GetLastVisibleIndex() - 1); + GetItemId(overflow_shelf_view->last_visible_index() - 1); // |src_api| represents the test api of the shelf we are moving the item // from. |dest_api| represents the test api of the shelf we are moving the // item too. ShelfViewTestAPI* src_api = main_to_overflow ? test_api_.get() : &test_api_for_overflow; + const ShelfView* src_shelf_view = + main_to_overflow ? shelf_view_ : overflow_shelf_view; ShelfViewTestAPI* dest_api = main_to_overflow ? &test_api_for_overflow : test_api_.get(); + const ShelfView* dest_shelf_view = + main_to_overflow ? overflow_shelf_view : shelf_view_; // Set the item to be dragged depending on |main_to_overflow|. - int drag_item_index = main_to_overflow ? 3 : src_api->GetLastVisibleIndex(); + int drag_item_index = + main_to_overflow ? 3 : src_shelf_view->last_visible_index(); ShelfID drag_item_id = GetItemId(drag_item_index); ShelfAppButton* drag_button = src_api->GetButton(drag_item_index); gfx::Point center_point_of_drag_item = GetButtonCenter(drag_button); @@ -571,7 +577,8 @@ ASSERT_FALSE(src_api->DraggedItemToAnotherShelf()); // Move a dragged item into the destination shelf at |drop_index|. - int drop_index = main_to_overflow ? dest_api->GetLastVisibleIndex() : 3; + int drop_index = + main_to_overflow ? dest_shelf_view->last_visible_index() : 3; ShelfAppButton* drop_button = dest_api->GetButton(drop_index); gfx::Point drop_point = GetButtonCenter(drop_button); // To insert at |drop_index|, a smaller x-axis value of |drop_point| @@ -603,13 +610,13 @@ if (cancel) { // Item ids should remain unchanged if operation was canceled. EXPECT_EQ(last_visible_item_id_in_shelf, - GetItemId(test_api_->GetLastVisibleIndex())); + GetItemId(shelf_view_->last_visible_index())); EXPECT_EQ(second_last_visible_item_id_in_shelf, - GetItemId(test_api_->GetLastVisibleIndex() - 1)); + GetItemId(shelf_view_->last_visible_index() - 1)); EXPECT_EQ(first_visible_item_id_in_overflow, - GetItemId(test_api_for_overflow.GetFirstVisibleIndex())); + GetItemId(overflow_shelf_view->first_visible_index())); EXPECT_EQ(second_last_visible_item_id_in_overflow, - GetItemId(test_api_for_overflow.GetLastVisibleIndex() - 1)); + GetItemId(overflow_shelf_view->last_visible_index() - 1)); } else { EXPECT_EQ(drag_item_id, GetItemId(drop_index)); EXPECT_EQ(total_item_count, model_->item_count()); @@ -623,11 +630,11 @@ // item on the main shelf. // 3) The dragged item should now be the last item on the main shelf. EXPECT_EQ(last_visible_item_id_in_shelf, - GetItemId(test_api_->GetLastVisibleIndex() - 1)); + GetItemId(shelf_view_->last_visible_index() - 1)); EXPECT_EQ(first_visible_item_id_in_overflow, - GetItemId(test_api_->GetLastVisibleIndex())); + GetItemId(shelf_view_->last_visible_index())); EXPECT_EQ(drag_item_id, - GetItemId(test_api_for_overflow.GetLastVisibleIndex())); + GetItemId(overflow_shelf_view->last_visible_index())); } else { // If we move an item from the overflow shelf to the main shelf, the // following should happen: @@ -641,13 +648,13 @@ // last item on the overflow shelf (since there are 3 items on the // overflow shelf). EXPECT_EQ(last_visible_item_id_in_shelf, - GetItemId(test_api_for_overflow.GetFirstVisibleIndex())); + GetItemId(overflow_shelf_view->first_visible_index())); EXPECT_EQ(second_last_visible_item_id_in_shelf, - GetItemId(test_api_->GetLastVisibleIndex())); + GetItemId(shelf_view_->last_visible_index())); EXPECT_EQ(first_visible_item_id_in_overflow, - GetItemId(test_api_for_overflow.GetFirstVisibleIndex() + 1)); + GetItemId(overflow_shelf_view->first_visible_index() + 1)); EXPECT_EQ(second_last_visible_item_id_in_overflow, - GetItemId(test_api_for_overflow.GetLastVisibleIndex())); + GetItemId(overflow_shelf_view->last_visible_index())); } } test_api_->HideOverflowBubble(); @@ -713,10 +720,10 @@ shelf_view_->GetBackButton()->GetMirroredBounds()); // Just items in the overflow area return the overflow button's ideal bounds. - EXPECT_NE(bounds_1, test_api_->overflow_button()->GetMirroredBounds()); + EXPECT_NE(bounds_1, shelf_view_->GetOverflowButton()->GetMirroredBounds()); EXPECT_TRUE(GetButtonByID(id_1)->GetMirroredBounds().Contains(bounds_1)); - EXPECT_EQ(bounds_2, test_api_->overflow_button()->GetMirroredBounds()); - EXPECT_EQ(bounds_3, test_api_->overflow_button()->GetMirroredBounds()); + EXPECT_EQ(bounds_2, shelf_view_->GetOverflowButton()->GetMirroredBounds()); + EXPECT_EQ(bounds_3, shelf_view_->GetOverflowButton()->GetMirroredBounds()); } // Checks that shelf view contents are considered in the correct drag group. @@ -741,12 +748,12 @@ // platform app button is hidden. TEST_F(ShelfViewTest, AddBrowserUntilOverflow) { // All buttons should be visible. - ASSERT_EQ(test_api_->GetButtonCount(), test_api_->GetLastVisibleIndex() + 1); + ASSERT_EQ(test_api_->GetButtonCount(), shelf_view_->last_visible_index() + 1); // Add platform app button until overflow. int items_added = 0; ShelfID last_added = AddApp(); - while (!test_api_->IsOverflowButtonVisible()) { + while (!shelf_view_->GetOverflowButton()->visible()) { // Added button is visible after animation while in this loop. EXPECT_TRUE(GetButtonByID(last_added)->visible()); @@ -761,8 +768,8 @@ TEST_F(ShelfViewTest, OverflowVisibleIndex) { AddButtonsUntilOverflow(); - ASSERT_TRUE(test_api_->IsOverflowButtonVisible()); - const int last_visible_index = test_api_->GetLastVisibleIndex(); + ASSERT_TRUE(shelf_view_->GetOverflowButton()->visible()); + const int last_visible_index = shelf_view_->last_visible_index(); test_api_->ShowOverflowBubble(); auto overflow_test_api = std::make_unique<ShelfViewTestAPI>( @@ -770,7 +777,7 @@ base::RunLoop().RunUntilIdle(); // Opening overflow doesn't change last visible index. - EXPECT_EQ(last_visible_index, test_api_->GetLastVisibleIndex()); + EXPECT_EQ(last_visible_index, shelf_view_->last_visible_index()); test_api_->HideOverflowBubble(); AddAppShortcut(); @@ -781,7 +788,7 @@ // Adding another shortcut should go into overflow bubble and not change // shelf index. - EXPECT_EQ(last_visible_index, test_api_->GetLastVisibleIndex()); + EXPECT_EQ(last_visible_index, shelf_view_->last_visible_index()); } // Adds one platform app button then adds app shortcut until overflow. Verifies @@ -789,14 +796,14 @@ // is still visible. TEST_F(ShelfViewTest, AddAppShortcutWithBrowserButtonUntilOverflow) { // All buttons should be visible. - ASSERT_EQ(test_api_->GetButtonCount(), test_api_->GetLastVisibleIndex() + 1); + ASSERT_EQ(test_api_->GetButtonCount(), shelf_view_->last_visible_index() + 1); ShelfID browser_button_id = AddApp(); // Add app shortcut until overflow. int items_added = 0; ShelfID last_added = AddAppShortcut(); - while (!test_api_->IsOverflowButtonVisible()) { + while (!shelf_view_->GetOverflowButton()->visible()) { // Added button is visible after animation while in this loop. EXPECT_TRUE(GetButtonByID(last_added)->visible()); @@ -814,7 +821,7 @@ TEST_F(ShelfViewTest, AssertNoButtonsOverlap) { std::vector<ShelfID> button_ids; // Add app icons until the overflow button is visible. - while (!test_api_->IsOverflowButtonVisible()) { + while (!shelf_view_->GetOverflowButton()->visible()) { ShelfID id = AddApp(); button_ids.push_back(id); } @@ -827,7 +834,7 @@ RemoveByID(id); button_ids.pop_back(); } - EXPECT_FALSE(test_api_->IsOverflowButtonVisible()); + EXPECT_FALSE(shelf_view_->GetOverflowButton()->visible()); EXPECT_TRUE(GetButtonByID(button_ids.back())->visible()); // Add 20 app icons, and expect to have overflow. @@ -836,7 +843,7 @@ button_ids.push_back(id); } ASSERT_LT(button_ids.size(), 10000U); - EXPECT_TRUE(test_api_->IsOverflowButtonVisible()); + EXPECT_TRUE(shelf_view_->GetOverflowButton()->visible()); // Test that any two successive visible icons never overlap in all shelf // alignment types. @@ -867,13 +874,13 @@ // chevron is gone. TEST_F(ShelfViewTest, RemoveButtonRevealsOverflowed) { // All buttons should be visible. - ASSERT_EQ(test_api_->GetButtonCount(), test_api_->GetLastVisibleIndex() + 1); + ASSERT_EQ(test_api_->GetButtonCount(), shelf_view_->last_visible_index() + 1); // Add platform app buttons until overflow. int items_added = 0; ShelfID first_added = AddApp(); ShelfID last_added = first_added; - while (!test_api_->IsOverflowButtonVisible()) { + while (!shelf_view_->GetOverflowButton()->visible()) { last_added = AddApp(); ++items_added; ASSERT_LT(items_added, 10000); @@ -890,25 +897,25 @@ // Last added button becomes visible and overflow chevron is gone. EXPECT_TRUE(GetButtonByID(last_added)->visible()); EXPECT_EQ(1.0f, GetButtonByID(last_added)->layer()->opacity()); - EXPECT_FALSE(test_api_->IsOverflowButtonVisible()); + EXPECT_FALSE(shelf_view_->GetOverflowButton()->visible()); } // Verifies that remove last overflowed button should hide overflow chevron. TEST_F(ShelfViewTest, RemoveLastOverflowed) { // All buttons should be visible. - ASSERT_EQ(test_api_->GetButtonCount(), test_api_->GetLastVisibleIndex() + 1); + ASSERT_EQ(test_api_->GetButtonCount(), shelf_view_->last_visible_index() + 1); // Add platform app button until overflow. int items_added = 0; ShelfID last_added = AddApp(); - while (!test_api_->IsOverflowButtonVisible()) { + while (!shelf_view_->GetOverflowButton()->visible()) { last_added = AddApp(); ++items_added; ASSERT_LT(items_added, 10000); } RemoveByID(last_added); - EXPECT_FALSE(test_api_->IsOverflowButtonVisible()); + EXPECT_FALSE(shelf_view_->GetOverflowButton()->visible()); } // Tests the visiblity of certain shelf items when the overflow bubble is open @@ -930,7 +937,7 @@ test_api_->overflow_bubble()->bubble_view()->shelf_view()); // The main shelf is currently showing the item at |last_visible_index|. - const int last_visible_index = test_api_->GetLastVisibleIndex(); + const int last_visible_index = shelf_view_->last_visible_index(); EXPECT_TRUE(is_visible_on_shelf(last_visible_index, test_api_.get())); EXPECT_FALSE(is_visible_on_shelf(last_visible_index, &overflow_test_api)); @@ -941,7 +948,7 @@ Shell::Get()->tablet_mode_controller()->EnableTabletModeWindowManager(true); test_api_->RunMessageLoopUntilAnimationsDone(); overflow_test_api.RunMessageLoopUntilAnimationsDone(); - ASSERT_TRUE(test_api_->IsShowingOverflowBubble()); + ASSERT_TRUE(shelf_view_->IsShowingOverflowBubble()); EXPECT_FALSE(is_visible_on_shelf(last_visible_index, test_api_.get())); EXPECT_TRUE(is_visible_on_shelf(last_visible_index, &overflow_test_api)); @@ -950,7 +957,7 @@ Shell::Get()->tablet_mode_controller()->EnableTabletModeWindowManager(false); test_api_->RunMessageLoopUntilAnimationsDone(); overflow_test_api.RunMessageLoopUntilAnimationsDone(); - ASSERT_TRUE(test_api_->IsShowingOverflowBubble()); + ASSERT_TRUE(shelf_view_->IsShowingOverflowBubble()); EXPECT_TRUE(is_visible_on_shelf(last_visible_index, test_api_.get())); EXPECT_FALSE(is_visible_on_shelf(last_visible_index, &overflow_test_api)); } @@ -959,11 +966,11 @@ // that all added buttons are visible. TEST_F(ShelfViewTest, AddButtonQuickly) { // All buttons should be visible. - ASSERT_EQ(test_api_->GetButtonCount(), test_api_->GetLastVisibleIndex() + 1); + ASSERT_EQ(test_api_->GetButtonCount(), shelf_view_->last_visible_index() + 1); // Add a few platform buttons quickly without wait for animation. int added_count = 0; - while (!test_api_->IsOverflowButtonVisible()) { + while (!shelf_view_->GetOverflowButton()->visible()) { AddAppNoWait(); ++added_count; ASSERT_LT(added_count, 10000); @@ -977,7 +984,7 @@ // Verifies non-overflow buttons are visible. The back button at index 0 is // not visible. - for (int i = 1; i <= test_api_->GetLastVisibleIndex(); ++i) { + for (int i = 1; i <= shelf_view_->last_visible_index(); ++i) { ShelfAppButton* button = test_api_->GetButton(i); if (button) { EXPECT_TRUE(button->visible()) << "button index=" << i; @@ -1185,7 +1192,7 @@ // Confirm that item status changes are reflected in the buttons. TEST_F(ShelfViewTest, ShelfItemStatus) { // All buttons should be visible. - ASSERT_EQ(test_api_->GetButtonCount(), test_api_->GetLastVisibleIndex() + 1); + ASSERT_EQ(test_api_->GetButtonCount(), shelf_view_->last_visible_index() + 1); // Add platform app button. ShelfID last_added = AddApp(); @@ -1234,7 +1241,7 @@ // Open overflow shelf and test api for it. test_api_->ShowOverflowBubble(); - ASSERT_TRUE(test_api_->IsShowingOverflowBubble()); + ASSERT_TRUE(shelf_view_->IsShowingOverflowBubble()); ShelfViewTestAPI test_api_for_overflow( test_api_->overflow_bubble()->bubble_view()->shelf_view()); @@ -1254,7 +1261,7 @@ // Verify that when an app from the overflow shelf is dragged to a location on // the main shelf, it is ripped off. - ASSERT_TRUE(test_api_->IsShowingOverflowBubble()); + ASSERT_TRUE(shelf_view_->IsShowingOverflowBubble()); generator->set_current_screen_location(overflow_app_location); generator->PressLeftButton(); generator->MoveMouseTo(second_app_location); @@ -1298,7 +1305,7 @@ // for platform apps. TEST_F(ShelfViewTest, ShelfItemStatusPlatformApp) { // All buttons should be visible. - ASSERT_EQ(test_api_->GetButtonCount(), test_api_->GetLastVisibleIndex() + 1); + ASSERT_EQ(test_api_->GetButtonCount(), shelf_view_->last_visible_index() + 1); // Add platform app button. ShelfID last_added = AddApp(); @@ -1323,7 +1330,7 @@ } TEST_F(ShelfViewTest, ShelfTooltipTest) { - ASSERT_EQ(test_api_->GetLastVisibleIndex() + 1, test_api_->GetButtonCount()); + ASSERT_EQ(shelf_view_->last_visible_index() + 1, test_api_->GetButtonCount()); // Prepare some items to the shelf. ShelfID app_button_id = AddAppShortcut(); @@ -1570,13 +1577,13 @@ // new ideal bounds. TEST_F(ShelfViewTest, ResizeDuringOverflowAddAnimation) { // All buttons should be visible. - ASSERT_EQ(test_api_->GetButtonCount(), test_api_->GetLastVisibleIndex() + 1); + ASSERT_EQ(test_api_->GetButtonCount(), shelf_view_->last_visible_index() + 1); // Add buttons until overflow. Let the non-overflow add animations finish but // leave the last running. int items_added = 0; AddAppNoWait(); - while (!test_api_->IsOverflowButtonVisible()) { + while (!shelf_view_->GetOverflowButton()->visible()) { test_api_->RunMessageLoopUntilAnimationsDone(); AddAppNoWait(); ++items_added; @@ -1587,7 +1594,7 @@ gfx::Rect bounds = shelf_view_->bounds(); bounds.set_width(bounds.width() - ShelfConstants::shelf_size()); shelf_view_->SetBoundsRect(bounds); - ASSERT_TRUE(test_api_->IsOverflowButtonVisible()); + ASSERT_TRUE(shelf_view_->GetOverflowButton()->visible()); // Finish the animation. test_api_->RunMessageLoopUntilAnimationsDone(); @@ -1610,14 +1617,14 @@ // Show overflow bubble. test_api_->ShowOverflowBubble(); - ASSERT_TRUE(test_api_->IsShowingOverflowBubble()); + ASSERT_TRUE(shelf_view_->IsShowingOverflowBubble()); ShelfViewTestAPI test_for_overflow_view( test_api_->overflow_bubble()->bubble_view()->shelf_view()); + const ShelfView* overflow_shelf_view = shelf_view_->overflow_shelf(); - int ripped_index = test_for_overflow_view.GetLastVisibleIndex(); - gfx::Size bubble_size = - test_for_overflow_view.shelf_view()->GetPreferredSize(); + int ripped_index = overflow_shelf_view->last_visible_index(); + gfx::Size bubble_size = overflow_shelf_view->GetPreferredSize(); int item_width = ShelfConstants::button_size() + ShelfConstants::button_spacing(); @@ -1636,23 +1643,23 @@ // Check the overflow bubble size when an item is ripped off. EXPECT_EQ(bubble_size.width() - item_width, - test_for_overflow_view.shelf_view()->GetPreferredSize().width()); - ASSERT_TRUE(test_api_->IsShowingOverflowBubble()); + overflow_shelf_view->GetPreferredSize().width()); + ASSERT_TRUE(shelf_view_->IsShowingOverflowBubble()); // Re-insert an item into the overflow bubble. - int first_index = test_for_overflow_view.GetFirstVisibleIndex(); + int first_index = overflow_shelf_view->first_visible_index(); button = test_for_overflow_view.GetButton(first_index); // Check the bubble size after an item is re-inserted. generator->MoveMouseTo(button->GetBoundsInScreen().CenterPoint()); test_for_overflow_view.RunMessageLoopUntilAnimationsDone(); EXPECT_EQ(bubble_size.width(), - test_for_overflow_view.shelf_view()->GetPreferredSize().width()); + overflow_shelf_view->GetPreferredSize().width()); generator->ReleaseLeftButton(); test_for_overflow_view.RunMessageLoopUntilAnimationsDone(); EXPECT_EQ(bubble_size.width(), - test_for_overflow_view.shelf_view()->GetPreferredSize().width()); + overflow_shelf_view->GetPreferredSize().width()); } TEST_F(ShelfViewTest, OverflowShelfColorIsDerivedFromWallpaper) { @@ -1676,7 +1683,7 @@ // Show overflow bubble. test_api_->ShowOverflowBubble(); - ASSERT_TRUE(test_api_->IsShowingOverflowBubble()); + ASSERT_TRUE(shelf_view_->IsShowingOverflowBubble()); int item_width = ShelfConstants::button_size() + ShelfConstants::button_spacing(); @@ -1690,12 +1697,13 @@ AddAppShortcut(); } - ASSERT_TRUE(test_api_->IsShowingOverflowBubble()); + ASSERT_TRUE(shelf_view_->IsShowingOverflowBubble()); ShelfViewTestAPI test_for_overflow_view( test_api_->overflow_bubble()->bubble_view()->shelf_view()); - int first_index = test_for_overflow_view.GetFirstVisibleIndex(); - int last_index = test_for_overflow_view.GetLastVisibleIndex(); + const ShelfView* overflow_shelf_view = shelf_view_->overflow_shelf(); + int first_index = overflow_shelf_view->first_visible_index(); + int last_index = overflow_shelf_view->last_visible_index(); ShelfAppButton* first_button = test_for_overflow_view.GetButton(first_index); ShelfAppButton* last_button = test_for_overflow_view.GetButton(last_index); @@ -1736,13 +1744,14 @@ // Test #1: Test drag insertion bounds of primary shelf. // Show overflow bubble. test_api_->ShowOverflowBubble(); - ASSERT_TRUE(test_api_->IsShowingOverflowBubble()); + ASSERT_TRUE(shelf_view_->IsShowingOverflowBubble()); ShelfViewTestAPI test_api_for_overflow_view( test_api_->overflow_bubble()->bubble_view()->shelf_view()); + const ShelfView* overflow_shelf_view = shelf_view_->overflow_shelf(); ShelfAppButton* button = test_api_for_overflow_view.GetButton( - test_api_for_overflow_view.GetLastVisibleIndex()); + overflow_shelf_view->last_visible_index()); // Checks that a point in shelf is contained in drag insert bounds. gfx::Point point_in_shelf_view = button->GetBoundsInScreen().CenterPoint(); @@ -1756,14 +1765,16 @@ // Test #2: Test drag insertion bounds of secondary shelf. // Show overflow bubble. test_api_for_secondary.ShowOverflowBubble(); - ASSERT_TRUE(test_api_for_secondary.IsShowingOverflowBubble()); + ASSERT_TRUE(shelf_view_for_secondary->IsShowingOverflowBubble()); ShelfViewTestAPI test_api_for_overflow_view_of_secondary( test_api_for_secondary.overflow_bubble()->bubble_view()->shelf_view()); + const ShelfView* overflow_shelf_view_of_secondary = + shelf_view_for_secondary->overflow_shelf(); ShelfAppButton* button_in_secondary = test_api_for_overflow_view_of_secondary.GetButton( - test_api_for_overflow_view_of_secondary.GetLastVisibleIndex()); + overflow_shelf_view_of_secondary->last_visible_index()); // Checks that a point in shelf is contained in drag insert bounds. gfx::Point point_in_secondary_shelf_view = @@ -1839,14 +1850,14 @@ test_api_->ShowOverflowBubble(); ShelfView* overflow_shelf_view = shelf_view_->overflow_bubble()->bubble_view()->shelf_view(); - ASSERT_TRUE(test_api_->IsShowingOverflowBubble()); + ASSERT_TRUE(shelf_view_->IsShowingOverflowBubble()); ShelfViewTestAPI overflow_api(overflow_shelf_view); // We are going to drag the first item in the overflow (A) onto the last // one (B). - int item_a_initial_index = overflow_api.GetFirstVisibleIndex(); - int item_b_initial_index = overflow_api.GetLastVisibleIndex(); + int item_a_initial_index = overflow_shelf_view->first_visible_index(); + int item_b_initial_index = overflow_shelf_view->last_visible_index(); ShelfID item_a = GetItemId(item_a_initial_index); ShelfID item_b = GetItemId(item_b_initial_index); ShelfAppButton* item_a_button = overflow_api.GetButton(item_a_initial_index); @@ -1868,10 +1879,10 @@ // Now, item A should be the last item, and item B should be just before it. ShelfID new_first_visible_item = - GetItemId(overflow_api.GetFirstVisibleIndex()); + GetItemId(overflow_shelf_view->first_visible_index()); EXPECT_NE(item_a, new_first_visible_item); - EXPECT_EQ(item_a, GetItemId(overflow_api.GetLastVisibleIndex())); - EXPECT_EQ(item_b, GetItemId(overflow_api.GetLastVisibleIndex() - 1)); + EXPECT_EQ(item_a, GetItemId(overflow_shelf_view->last_visible_index())); + EXPECT_EQ(item_b, GetItemId(overflow_shelf_view->last_visible_index() - 1)); test_api_->HideOverflowBubble(); } @@ -1959,7 +1970,7 @@ // Verify that by pressing anywhere outside the shelf and overflow bubble, the // overflow bubble will close if it were open. - EXPECT_FALSE(test_api_->IsShowingOverflowBubble()); + EXPECT_FALSE(shelf_view_->IsShowingOverflowBubble()); test_api_->ShowOverflowBubble(); // Make sure the point we chose is not on the shelf or its overflow bubble. @@ -1971,20 +1982,20 @@ ->GetBoundsInScreen() .Contains(generator->current_screen_location())); generator->PressLeftButton(); - EXPECT_FALSE(test_api_->IsShowingOverflowBubble()); + EXPECT_FALSE(shelf_view_->IsShowingOverflowBubble()); generator->ReleaseLeftButton(); // Verify that by clicking a app which is on the main shelf while the overflow // bubble is opened, the overflow bubble will close. - EXPECT_FALSE(test_api_->IsShowingOverflowBubble()); + EXPECT_FALSE(shelf_view_->IsShowingOverflowBubble()); test_api_->ShowOverflowBubble(); generator->set_current_screen_location(GetButtonCenter(first_app_id)); generator->ClickLeftButton(); - EXPECT_FALSE(test_api_->IsShowingOverflowBubble()); + EXPECT_FALSE(shelf_view_->IsShowingOverflowBubble()); // Verify that by clicking a app which is on the overflow shelf, the overflow // bubble will close. - EXPECT_FALSE(test_api_->IsShowingOverflowBubble()); + EXPECT_FALSE(shelf_view_->IsShowingOverflowBubble()); test_api_->ShowOverflowBubble(); ShelfViewTestAPI test_api_for_overflow( test_api_->overflow_bubble()->bubble_view()->shelf_view()); @@ -1993,20 +2004,20 @@ generator->set_current_screen_location( GetButtonCenter(button_on_overflow_shelf)); generator->ClickLeftButton(); - EXPECT_FALSE(test_api_->IsShowingOverflowBubble()); + EXPECT_FALSE(shelf_view_->IsShowingOverflowBubble()); // Verify that dragging apps on the main shelf does not close the overflow // bubble. - EXPECT_FALSE(test_api_->IsShowingOverflowBubble()); + EXPECT_FALSE(shelf_view_->IsShowingOverflowBubble()); test_api_->ShowOverflowBubble(); generator->set_current_screen_location(GetButtonCenter(first_app_id)); generator->DragMouseTo(GetButtonCenter(second_app_id)); - EXPECT_TRUE(test_api_->IsShowingOverflowBubble()); + EXPECT_TRUE(shelf_view_->IsShowingOverflowBubble()); test_api_->HideOverflowBubble(); // Verify dragging apps on the overflow shelf does not close the overflow // bubble. - EXPECT_FALSE(test_api_->IsShowingOverflowBubble()); + EXPECT_FALSE(shelf_view_->IsShowingOverflowBubble()); test_api_->ShowOverflowBubble(); ShelfViewTestAPI test_api_for_overflow2( test_api_->overflow_bubble()->bubble_view()->shelf_view()); @@ -2017,7 +2028,7 @@ generator->set_current_screen_location( GetButtonCenter(button_on_overflow_shelf)); generator->DragMouseTo(GetButtonCenter(button_on_overflow_shelf1)); - EXPECT_TRUE(test_api_->IsShowingOverflowBubble()); + EXPECT_TRUE(shelf_view_->IsShowingOverflowBubble()); } TEST_F(ShelfViewTest, UnpinningCancelsOverflow) { @@ -2025,14 +2036,14 @@ const ShelfID first_shelf_id = AddAppShortcut(); AddButtonsUntilOverflow(); test_api_->ShowOverflowBubble(); - EXPECT_TRUE(test_api_->IsOverflowButtonVisible()); - EXPECT_TRUE(test_api_->IsShowingOverflowBubble()); + EXPECT_TRUE(shelf_view_->GetOverflowButton()->visible()); + EXPECT_TRUE(shelf_view_->IsShowingOverflowBubble()); // Unpinning an item should hide the overflow button and close the bubble. model_->UnpinAppWithID(first_shelf_id.app_id); test_api_->RunMessageLoopUntilAnimationsDone(); - EXPECT_FALSE(test_api_->IsOverflowButtonVisible()); - EXPECT_FALSE(test_api_->IsShowingOverflowBubble()); + EXPECT_FALSE(shelf_view_->GetOverflowButton()->visible()); + EXPECT_FALSE(shelf_view_->IsShowingOverflowBubble()); } // Verify the animations of the shelf items are as long as expected. @@ -2148,7 +2159,7 @@ TEST_F(ShelfViewTest, NoContextMenuOnOverflowButton) { ui::test::EventGenerator* generator = GetEventGenerator(); AddButtonsUntilOverflow(); - views::View* overflow_button = test_api_->overflow_button(); + views::View* overflow_button = shelf_view_->GetOverflowButton(); generator->MoveMouseTo(overflow_button->GetBoundsInScreen().CenterPoint()); generator->PressRightButton(); @@ -2437,10 +2448,10 @@ AddAppShortcut(); } test_api_->RunMessageLoopUntilAnimationsDone(); - EXPECT_FALSE(test_api_->IsOverflowButtonVisible()); + EXPECT_FALSE(shelf_view_->GetOverflowButton()->visible()); CheckAllItemsAreInBounds(); // Same for overflow case. - while (!test_api_->IsOverflowButtonVisible()) { + while (!shelf_view_->GetOverflowButton()->visible()) { AddAppShortcut(); } test_api_->RunMessageLoopUntilAnimationsDone(); @@ -2993,7 +3004,7 @@ void SetUp() override { ShelfViewInkDropTest::SetUp(); - overflow_button_ = test_api_->overflow_button(); + overflow_button_ = shelf_view_->GetOverflowButton(); auto overflow_button_ink_drop = std::make_unique<InkDropSpy>(std::make_unique<views::InkDropImpl>( @@ -3003,8 +3014,8 @@ .SetInkDrop(std::move(overflow_button_ink_drop)); AddButtonsUntilOverflow(); - EXPECT_TRUE(test_api_->IsOverflowButtonVisible()); - EXPECT_FALSE(test_api_->IsShowingOverflowBubble()); + EXPECT_TRUE(shelf_view_->GetOverflowButton()->visible()); + EXPECT_FALSE(shelf_view_->IsShowingOverflowBubble()); } protected: @@ -3029,14 +3040,14 @@ // bubble is shown or hidden. TEST_F(OverflowButtonInkDropTest, OnOverflowBubbleShowHide) { test_api_->ShowOverflowBubble(); - ASSERT_TRUE(test_api_->IsShowingOverflowBubble()); + ASSERT_TRUE(shelf_view_->IsShowingOverflowBubble()); EXPECT_EQ(views::InkDropState::ACTIVATED, overflow_button_ink_drop_->GetTargetInkDropState()); EXPECT_THAT(overflow_button_ink_drop_->GetAndResetRequestedStates(), ElementsAre(views::InkDropState::ACTIVATED)); test_api_->HideOverflowBubble(); - EXPECT_FALSE(test_api_->IsShowingOverflowBubble()); + EXPECT_FALSE(shelf_view_->IsShowingOverflowBubble()); EXPECT_EQ(views::InkDropState::HIDDEN, overflow_button_ink_drop_->GetTargetInkDropState()); EXPECT_THAT(overflow_button_ink_drop_->GetAndResetRequestedStates(), @@ -3062,7 +3073,7 @@ EXPECT_THAT(overflow_button_ink_drop_->GetAndResetRequestedStates(), ElementsAre(views::InkDropState::ACTIVATED)); - ASSERT_TRUE(test_api_->IsShowingOverflowBubble()); + ASSERT_TRUE(shelf_view_->IsShowingOverflowBubble()); } // Tests ink drop state transitions for the overflow button when the user @@ -3089,7 +3100,7 @@ EXPECT_THAT(overflow_button_ink_drop_->GetAndResetRequestedStates(), IsEmpty()); - EXPECT_FALSE(test_api_->IsShowingOverflowBubble()); + EXPECT_FALSE(shelf_view_->IsShowingOverflowBubble()); } // Tests ink drop state transitions for the overflow button when the user @@ -3123,7 +3134,7 @@ EXPECT_THAT(overflow_button_ink_drop_->GetAndResetRequestedStates(), ElementsAre(views::InkDropState::ACTIVATED)); - ASSERT_TRUE(test_api_->IsShowingOverflowBubble()); + ASSERT_TRUE(shelf_view_->IsShowingOverflowBubble()); } // Tests ink drop state transitions for the overflow button when the user @@ -3144,7 +3155,7 @@ EXPECT_THAT(overflow_button_ink_drop_->GetAndResetRequestedStates(), IsEmpty()); - EXPECT_FALSE(test_api_->IsShowingOverflowBubble()); + EXPECT_FALSE(shelf_view_->IsShowingOverflowBubble()); } // Tests ink drop state transitions for the overflow button when the user taps @@ -3165,7 +3176,7 @@ EXPECT_THAT(overflow_button_ink_drop_->GetAndResetRequestedStates(), ElementsAre(views::InkDropState::ACTIVATED)); - ASSERT_TRUE(test_api_->IsShowingOverflowBubble()); + ASSERT_TRUE(shelf_view_->IsShowingOverflowBubble()); } // Tests ink drop state transitions for the overflow button when the user taps @@ -3192,7 +3203,7 @@ EXPECT_THAT(overflow_button_ink_drop_->GetAndResetRequestedStates(), IsEmpty()); - EXPECT_FALSE(test_api_->IsShowingOverflowBubble()); + EXPECT_FALSE(shelf_view_->IsShowingOverflowBubble()); } // Tests ink drop state transitions for the overflow button when the user taps @@ -3225,7 +3236,7 @@ EXPECT_THAT(overflow_button_ink_drop_->GetAndResetRequestedStates(), IsEmpty()); - EXPECT_FALSE(test_api_->IsShowingOverflowBubble()); + EXPECT_FALSE(shelf_view_->IsShowingOverflowBubble()); } // Test fixture to run overflow button tests for LTR and RTL directions. @@ -3263,7 +3274,7 @@ OverflowButtonInkDropTest::SetUp(); test_api_->ShowOverflowBubble(); - ASSERT_TRUE(test_api_->IsShowingOverflowBubble()); + ASSERT_TRUE(shelf_view_->IsShowingOverflowBubble()); EXPECT_EQ(views::InkDropState::ACTIVATED, overflow_button_ink_drop_->GetTargetInkDropState()); EXPECT_THAT(overflow_button_ink_drop_->GetAndResetRequestedStates(), @@ -3292,7 +3303,7 @@ EXPECT_THAT(overflow_button_ink_drop_->GetAndResetRequestedStates(), ElementsAre(views::InkDropState::DEACTIVATED)); - EXPECT_FALSE(test_api_->IsShowingOverflowBubble()); + EXPECT_FALSE(shelf_view_->IsShowingOverflowBubble()); } // Tests ink drop state transitions for the overflow button when it is active @@ -3320,7 +3331,7 @@ EXPECT_THAT(overflow_button_ink_drop_->GetAndResetRequestedStates(), IsEmpty()); - ASSERT_TRUE(test_api_->IsShowingOverflowBubble()); + ASSERT_TRUE(shelf_view_->IsShowingOverflowBubble()); } // Tests ink drop state transitions for the overflow button when it is active @@ -3354,7 +3365,7 @@ EXPECT_THAT(overflow_button_ink_drop_->GetAndResetRequestedStates(), ElementsAre(views::InkDropState::DEACTIVATED)); - EXPECT_FALSE(test_api_->IsShowingOverflowBubble()); + EXPECT_FALSE(shelf_view_->IsShowingOverflowBubble()); } // Tests ink drop state transitions for the overflow button when it is active @@ -3375,7 +3386,7 @@ EXPECT_THAT(overflow_button_ink_drop_->GetAndResetRequestedStates(), ElementsAre(views::InkDropState::DEACTIVATED)); - EXPECT_FALSE(test_api_->IsShowingOverflowBubble()); + EXPECT_FALSE(shelf_view_->IsShowingOverflowBubble()); } // Tests ink drop state transitions for the overflow button when it is active @@ -3402,7 +3413,7 @@ EXPECT_THAT(overflow_button_ink_drop_->GetAndResetRequestedStates(), IsEmpty()); - ASSERT_TRUE(test_api_->IsShowingOverflowBubble()); + ASSERT_TRUE(shelf_view_->IsShowingOverflowBubble()); } // Tests ink drop state transitions for the overflow button when it is active @@ -3436,7 +3447,7 @@ EXPECT_THAT(overflow_button_ink_drop_->GetAndResetRequestedStates(), IsEmpty()); - ASSERT_TRUE(test_api_->IsShowingOverflowBubble()); + ASSERT_TRUE(shelf_view_->IsShowingOverflowBubble()); } class ShelfViewFocusTest : public ShelfViewTest { @@ -3483,7 +3494,7 @@ // Tests that the number of buttons is as expected and the shelf's widget // intially has focus. TEST_F(ShelfViewFocusTest, Basic) { - EXPECT_FALSE(test_api_->IsShowingOverflowBubble()); + EXPECT_FALSE(shelf_view_->IsShowingOverflowBubble()); // There are five buttons. The back button and launcher are always there, the // browser shortcut is added in ShelfViewTest and the two test apps added in @@ -3610,8 +3621,8 @@ // Tests that the overflow button is visible and that not all the items are // visible on the main shelf. TEST_F(ShelfViewOverflowFocusTest, Basic) { - EXPECT_TRUE(test_api_->IsOverflowButtonVisible()); - EXPECT_FALSE(test_api_->IsShowingOverflowBubble()); + EXPECT_TRUE(shelf_view_->GetOverflowButton()->visible()); + EXPECT_FALSE(shelf_view_->IsShowingOverflowBubble()); EXPECT_EQ(last_item_on_main_shelf_index_, items_ - 5); EXPECT_TRUE(shelf_view_->shelf_widget()->IsActive()); @@ -3621,7 +3632,7 @@ TEST_F(ShelfViewOverflowFocusTest, OpenOverflow) { OpenOverflow(); ASSERT_TRUE(overflow_shelf_test_api_); - EXPECT_TRUE(test_api_->IsShowingOverflowBubble()); + EXPECT_TRUE(shelf_view_->IsShowingOverflowBubble()); EXPECT_TRUE(test_api_->GetViewAt(1)->HasFocus()); } @@ -3635,13 +3646,13 @@ // Focus the overflow button. DoTab(); - EXPECT_TRUE(test_api_->overflow_button()->HasFocus()); + EXPECT_TRUE(shelf_view_->GetOverflowButton()->HasFocus()); } // Tests that when cycling through the items with shift tab, the items in the // overflow shelf are ignored because it is not visible. TEST_F(ShelfViewOverflowFocusTest, BackwardCycling) { - while (!test_api_->overflow_button()->HasFocus()) + while (!shelf_view_->GetOverflowButton()->HasFocus()) DoTab(); DoShiftTab(); @@ -3659,7 +3670,7 @@ // Focus the overflow button. DoTab(); - EXPECT_TRUE(test_api_->overflow_button()->HasFocus()); + EXPECT_TRUE(shelf_view_->GetOverflowButton()->HasFocus()); // Tests that after pressing tab once more, the overflow bubble widget now is // active, and the first item on the overflow bubble shelf has focus. @@ -3680,13 +3691,13 @@ while (!test_api_->overflow_bubble()->bubble_view()->GetWidget()->IsActive()) DoTab(); EXPECT_FALSE(shelf_view_->shelf_widget()->IsActive()); - EXPECT_FALSE(test_api_->overflow_button()->HasFocus()); + EXPECT_FALSE(shelf_view_->GetOverflowButton()->HasFocus()); // Tests that after pressing shift tab once, the main shelf is active and // the overflow button has focus. DoShiftTab(); EXPECT_TRUE(shelf_view_->shelf_widget()->IsActive()); - EXPECT_TRUE(test_api_->overflow_button()->HasFocus()); + EXPECT_TRUE(shelf_view_->GetOverflowButton()->HasFocus()); // One more shift tab and the last item on the main shelf has focus. DoShiftTab(); @@ -3718,7 +3729,7 @@ // Focus the overflow button DoTab(); - EXPECT_TRUE(test_api_->overflow_button()->HasFocus()); + EXPECT_TRUE(shelf_view_->GetOverflowButton()->HasFocus()); // Tab into the overflow bubble. DoTab(); @@ -3727,7 +3738,7 @@ // Back onto the overflow button itself. DoShiftTab(); - EXPECT_TRUE(test_api_->overflow_button()->HasFocus()); + EXPECT_TRUE(shelf_view_->GetOverflowButton()->HasFocus()); // Now advance until we get to the status area. while (!status_area_->GetWidget()->IsActive())
diff --git a/ash/sticky_keys/sticky_keys_controller.cc b/ash/sticky_keys/sticky_keys_controller.cc index bdab1a1..ada3e41 100644 --- a/ash/sticky_keys/sticky_keys_controller.cc +++ b/ash/sticky_keys/sticky_keys_controller.cc
@@ -5,7 +5,6 @@ #include "ash/sticky_keys/sticky_keys_controller.h" #include "ash/sticky_keys/sticky_keys_overlay.h" -#include "base/debug/stack_trace.h" #include "ui/aura/window.h" #include "ui/aura/window_tracker.h" #include "ui/aura/window_tree_host.h"
diff --git a/ash/wm/desks/close_desk_button.cc b/ash/wm/desks/close_desk_button.cc new file mode 100644 index 0000000..6f701c2 --- /dev/null +++ b/ash/wm/desks/close_desk_button.cc
@@ -0,0 +1,88 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/wm/desks/close_desk_button.h" + +#include <utility> + +#include "ash/resources/vector_icons/vector_icons.h" +#include "ui/gfx/paint_vector_icon.h" +#include "ui/views/animation/flood_fill_ink_drop_ripple.h" +#include "ui/views/animation/ink_drop_impl.h" +#include "ui/views/animation/ink_drop_mask.h" +#include "ui/views/background.h" +#include "ui/views/style/platform_style.h" + +namespace ash { + +namespace { + +constexpr float kInkDropOpacity = 0.2f; + +constexpr float kInkDropHighlightOpacity = 0.1f; + +constexpr int kCornerRadius = 12; + +constexpr SkColor kBackgroundColor = SkColorSetARGB(181, 55, 71, 79); + +} // namespace + +CloseDeskButton::CloseDeskButton(views::ButtonListener* listener) + : ImageButton(listener) { + SetPaintToLayer(); + layer()->SetFillsBoundsOpaquely(false); + + SetImage(views::Button::STATE_NORMAL, + gfx::CreateVectorIcon(kDesksCloseDeskButtonIcon, SK_ColorWHITE)); + SetImageAlignment(views::ImageButton::ALIGN_CENTER, + views::ImageButton::ALIGN_MIDDLE); + SetBackgroundImageAlignment(views::ImageButton::ALIGN_CENTER, + views::ImageButton::ALIGN_MIDDLE); + SetBackground( + CreateBackgroundFromPainter(views::Painter::CreateSolidRoundRectPainter( + kBackgroundColor, kCornerRadius))); + + SetInkDropMode(InkDropMode::ON); + set_has_ink_drop_action_on_click(true); + set_ink_drop_visible_opacity(kInkDropOpacity); + SetFocusPainter(nullptr); +} + +CloseDeskButton::~CloseDeskButton() = default; + +const char* CloseDeskButton::GetClassName() const { + return "CloseDeskButton"; +} + +std::unique_ptr<views::InkDrop> CloseDeskButton::CreateInkDrop() { + auto ink_drop = CreateDefaultFloodFillInkDropImpl(); + ink_drop->SetShowHighlightOnHover(true); + ink_drop->SetShowHighlightOnFocus(!views::PlatformStyle::kPreferFocusRings); + return std::move(ink_drop); +} + +std::unique_ptr<views::InkDropRipple> CloseDeskButton::CreateInkDropRipple() + const { + return std::make_unique<views::FloodFillInkDropRipple>( + size(), GetInkDropCenterBasedOnLastEvent(), GetInkDropBaseColor(), + ink_drop_visible_opacity()); +} + +std::unique_ptr<views::InkDropHighlight> +CloseDeskButton::CreateInkDropHighlight() const { + auto highlight = ImageButton::CreateInkDropHighlight(); + highlight->set_visible_opacity(kInkDropHighlightOpacity); + return highlight; +} + +SkColor CloseDeskButton::GetInkDropBaseColor() const { + return SK_ColorWHITE; +} + +std::unique_ptr<views::InkDropMask> CloseDeskButton::CreateInkDropMask() const { + return std::make_unique<views::RoundRectInkDropMask>(size(), gfx::Insets(), + kCornerRadius); +} + +} // namespace ash
diff --git a/ash/wm/desks/close_desk_button.h b/ash/wm/desks/close_desk_button.h new file mode 100644 index 0000000..03f752a --- /dev/null +++ b/ash/wm/desks/close_desk_button.h
@@ -0,0 +1,38 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ASH_WM_DESKS_CLOSE_DESK_BUTTON_H_ +#define ASH_WM_DESKS_CLOSE_DESK_BUTTON_H_ + +#include <memory> + +#include "ash/ash_export.h" +#include "base/macros.h" +#include "ui/views/controls/button/image_button.h" + +namespace ash { + +// A button view that shows up on hovering over the associated desk mini_view, +// which let users remove the mini_view and its corresponding desk. +class ASH_EXPORT CloseDeskButton : public views::ImageButton { + public: + explicit CloseDeskButton(views::ButtonListener* listener); + ~CloseDeskButton() override; + + // views::ImageButton: + const char* GetClassName() const override; + std::unique_ptr<views::InkDrop> CreateInkDrop() override; + std::unique_ptr<views::InkDropRipple> CreateInkDropRipple() const override; + std::unique_ptr<views::InkDropHighlight> CreateInkDropHighlight() + const override; + SkColor GetInkDropBaseColor() const override; + std::unique_ptr<views::InkDropMask> CreateInkDropMask() const override; + + private: + DISALLOW_COPY_AND_ASSIGN(CloseDeskButton); +}; + +} // namespace ash + +#endif // ASH_WM_DESKS_CLOSE_DESK_BUTTON_H_
diff --git a/ash/wm/desks/desk.cc b/ash/wm/desks/desk.cc new file mode 100644 index 0000000..3199aed --- /dev/null +++ b/ash/wm/desks/desk.cc
@@ -0,0 +1,12 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/wm/desks/desk.h" + +namespace ash { + +Desk::Desk() = default; +Desk::~Desk() = default; + +} // namespace ash
diff --git a/ash/wm/desks/desk.h b/ash/wm/desks/desk.h new file mode 100644 index 0000000..a5b06aa --- /dev/null +++ b/ash/wm/desks/desk.h
@@ -0,0 +1,26 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ASH_WM_DESKS_DESK_H_ +#define ASH_WM_DESKS_DESK_H_ + +#include "ash/ash_export.h" +#include "base/macros.h" + +namespace ash { + +// Represents a virtual desk, tracking the windows that belong to this desk. +// TODO(afakhry): Fill in this class. +class ASH_EXPORT Desk { + public: + Desk(); + ~Desk(); + + private: + DISALLOW_COPY_AND_ASSIGN(Desk); +}; + +} // namespace ash + +#endif // ASH_WM_DESKS_DESK_H_
diff --git a/ash/wm/desks/desk_mini_view.cc b/ash/wm/desks/desk_mini_view.cc new file mode 100644 index 0000000..d75a884 --- /dev/null +++ b/ash/wm/desks/desk_mini_view.cc
@@ -0,0 +1,192 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ash/wm/desks/desk_mini_view.h" + +#include <algorithm> + +#include "ash/wm/desks/close_desk_button.h" +#include "ash/wm/desks/desk.h" +#include "ash/wm/desks/desks_controller.h" +#include "ui/aura/window.h" +#include "ui/views/widget/widget.h" + +namespace ash { + +namespace { + +constexpr int kDeskPreviewHeight = 64; + +constexpr int kLabelPreviewSpacing = 8; + +constexpr int kCloseButtonMargin = 2; + +constexpr gfx::Size kCloseButtonSize{24, 24}; + +// The desk preview bounds are proportional to the bounds of the display on +// which it resides, but always has a fixed height `kDeskPreviewHeight`. +gfx::Rect GetDeskPreviewBounds(aura::Window* root_window) { + const auto root_size = root_window->GetBoundsInRootWindow().size(); + return gfx::Rect(kDeskPreviewHeight * root_size.width() / root_size.height(), + kDeskPreviewHeight); +} + +} // namespace + +// ----------------------------------------------------------------------------- + +// A view that shows the contents of the corresponding desk in its mini_view. +class DeskPreviewView : public views::View { + public: + explicit DeskPreviewView(DeskMiniView* mini_view) : mini_view_(mini_view) { + // For now use a solid color layer. + SetPaintToLayer(ui::LAYER_SOLID_COLOR); + layer()->SetColor(SK_ColorDKGRAY); + + // TODO(afakhry): + // - Ability to mark this preview as active. + // - Actually mirror the contents of the corresponding desk. + } + + ~DeskPreviewView() override = default; + + // ui::EventHandler: + void OnMouseEvent(ui::MouseEvent* event) override { + switch (event->type()) { + case ui::ET_MOUSE_PRESSED: + case ui::ET_MOUSE_DRAGGED: + case ui::ET_MOUSE_RELEASED: + case ui::ET_MOUSE_MOVED: + case ui::ET_MOUSE_ENTERED: + case ui::ET_MOUSE_EXITED: + mini_view_->OnHoverStateMayHaveChanged(); + break; + + default: + break; + } + } + + private: + DeskMiniView* mini_view_; + + DISALLOW_COPY_AND_ASSIGN(DeskPreviewView); +}; + +// ----------------------------------------------------------------------------- +// DeskMiniView + +DeskMiniView::DeskMiniView(const Desk* desk, + const base::string16& title, + views::ButtonListener* listener) + : views::Button(listener), + desk_(desk), + desk_preview_(new DeskPreviewView(this)), + label_(new views::Label(title)), + close_desk_button_(new CloseDeskButton(this)) { + SetPaintToLayer(); + layer()->SetFillsBoundsOpaquely(false); + + label_->SetAutoColorReadabilityEnabled(false); + label_->SetSubpixelRenderingEnabled(false); + label_->set_can_process_events_within_subtree(false); + label_->SetEnabledColor(SK_ColorWHITE); + label_->SetLineHeight(10); + + close_desk_button_->SetVisible(false); + + // TODO(afakhry): Tooltips and accessible names. + + AddChildView(desk_preview_); + AddChildView(label_); + AddChildView(close_desk_button_); + + SetFocusPainter(nullptr); + SetInkDropMode(InkDropMode::OFF); + + SchedulePaint(); +} + +DeskMiniView::~DeskMiniView() = default; + +void DeskMiniView::SetTitle(const base::string16& title) { + label_->SetText(title); +} + +void DeskMiniView::OnHoverStateMayHaveChanged() { + // TODO(afakhry): In tablet mode, discuss showing the close button on long + // press. + close_desk_button_->SetVisible(DesksController::Get()->CanRemoveDesks() && + IsMouseHovered()); +} + +const char* DeskMiniView::GetClassName() const { + return "DeskMiniView"; +} + +void DeskMiniView::Layout() { + auto* root_window = GetWidget()->GetNativeWindow()->GetRootWindow(); + DCHECK(root_window); + + const gfx::Rect preview_bounds = GetDeskPreviewBounds(root_window); + desk_preview_->SetBoundsRect(preview_bounds); + + const gfx::Size label_size = label_->GetPreferredSize(); + const gfx::Rect label_bounds{ + (preview_bounds.width() - label_size.width()) / 2, + preview_bounds.bottom() + kLabelPreviewSpacing, label_size.width(), + label_size.height()}; + label_->SetBoundsRect(label_bounds); + + close_desk_button_->SetBounds( + preview_bounds.right() - kCloseButtonSize.width() - kCloseButtonMargin, + kCloseButtonMargin, kCloseButtonSize.width(), kCloseButtonSize.height()); + + Button::Layout(); + + SchedulePaint(); +} + +gfx::Size DeskMiniView::CalculatePreferredSize() const { + auto* root_window = GetWidget()->GetNativeWindow()->GetRootWindow(); + DCHECK(root_window); + + const gfx::Size label_size = label_->GetPreferredSize(); + const gfx::Rect preview_bounds = GetDeskPreviewBounds(root_window); + + return gfx::Size{ + std::max(preview_bounds.width(), label_size.width()), + preview_bounds.height() + kLabelPreviewSpacing + label_size.height()}; +} + +void DeskMiniView::ButtonPressed(views::Button* sender, + const ui::Event& event) { + if (sender != close_desk_button_) + return; + + // This mini_view can no longer be pressed. + listener_ = nullptr; + + auto* controller = DesksController::Get(); + DCHECK(controller->CanRemoveDesks()); + controller->RemoveDesk(desk_); +} + +void DeskMiniView::OnMouseEvent(ui::MouseEvent* event) { + switch (event->type()) { + case ui::ET_MOUSE_PRESSED: + case ui::ET_MOUSE_DRAGGED: + case ui::ET_MOUSE_RELEASED: + case ui::ET_MOUSE_MOVED: + case ui::ET_MOUSE_ENTERED: + case ui::ET_MOUSE_EXITED: + OnHoverStateMayHaveChanged(); + break; + + default: + break; + } +} + +} // namespace ash
diff --git a/ash/wm/desks/desk_mini_view.h b/ash/wm/desks/desk_mini_view.h new file mode 100644 index 0000000..8fbccbb1 --- /dev/null +++ b/ash/wm/desks/desk_mini_view.h
@@ -0,0 +1,74 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ASH_WM_DESKS_DESK_MINI_VIEW_H_ +#define ASH_WM_DESKS_DESK_MINI_VIEW_H_ + +#include <memory> + +#include "ash/ash_export.h" +#include "base/macros.h" +#include "ui/views/controls/button/button.h" +#include "ui/views/controls/label.h" + +namespace ash { + +class CloseDeskButton; +class Desk; +class DeskPreviewView; + +// A view that acts as a mini representation (a.k.a. desk thumbnail) of a +// virtual desk in the desk bar view when overview mode is active. This view +// shows a preview of the contents of the associated desk, its title, and +// supports desk activation and removal. +class ASH_EXPORT DeskMiniView : public views::Button, + public views::ButtonListener { + public: + DeskMiniView(const Desk* desk, + const base::string16& title, + views::ButtonListener* listener); + ~DeskMiniView() override; + + const Desk* desk() const { return desk_; } + + const CloseDeskButton* close_desk_button() const { + return close_desk_button_; + } + + void SetTitle(const base::string16& title); + + // Updates the visibility state of the close button depending on whether this + // view is mouse hovered. + void OnHoverStateMayHaveChanged(); + + // views::Button: + const char* GetClassName() const override; + void Layout() override; + gfx::Size CalculatePreferredSize() const override; + + // views::ButtonListener: + void ButtonPressed(views::Button* sender, const ui::Event& event) override; + + // ui::EventHandler: + void OnMouseEvent(ui::MouseEvent* event) override; + + private: + // The associated desk. + const Desk* desk_; // Not owned. + + // The view that shows a preview of the desk contents. + DeskPreviewView* desk_preview_; + + // The desk title. + views::Label* label_; + + // The close button that shows on hover. + CloseDeskButton* close_desk_button_; + + DISALLOW_COPY_AND_ASSIGN(DeskMiniView); +}; + +} // namespace ash + +#endif // ASH_WM_DESKS_DESK_MINI_VIEW_H_
diff --git a/ash/wm/desks/desks_bar_view.cc b/ash/wm/desks/desks_bar_view.cc index 88ce533..c2f5524e 100644 --- a/ash/wm/desks/desks_bar_view.cc +++ b/ash/wm/desks/desks_bar_view.cc
@@ -4,26 +4,63 @@ #include "ash/wm/desks/desks_bar_view.h" -#include "ash/wm/desks/desks_controller.h" +#include <algorithm> +#include <utility> + +#include "ash/strings/grit/ash_strings.h" +#include "ash/wm/desks/desk_mini_view.h" #include "ash/wm/desks/new_desk_button.h" +#include "base/stl_util.h" #include "third_party/skia/include/core/SkColor.h" +#include "ui/base/l10n/l10n_util.h" #include "ui/gfx/geometry/insets.h" namespace ash { -DesksBarView::DesksBarView() : new_desk_button_(new NewDeskButton(this)) { - SetPaintToLayer(ui::LAYER_SOLID_COLOR); - layer()->SetFillsBoundsOpaquely(false); - layer()->SetColor(SkColorSetARGB(60, 0, 0, 0)); +namespace { +constexpr int kBarHeight = 104; + +base::string16 GetMiniViewTitle(int mini_view_index) { + DCHECK_GE(mini_view_index, 0); + DCHECK_LT(mini_view_index, 4); + constexpr int kStringIds[] = {IDS_ASH_DESKS_DESK_1_MINI_VIEW_TITLE, + IDS_ASH_DESKS_DESK_2_MINI_VIEW_TITLE, + IDS_ASH_DESKS_DESK_3_MINI_VIEW_TITLE, + IDS_ASH_DESKS_DESK_4_MINI_VIEW_TITLE}; + + return l10n_util::GetStringUTF16(kStringIds[mini_view_index]); +} + +} // namespace + +DesksBarView::DesksBarView() + : backgroud_view_(new views::View), + new_desk_button_(new NewDeskButton(this)) { + SetPaintToLayer(); + layer()->SetFillsBoundsOpaquely(false); + + backgroud_view_->SetPaintToLayer(ui::LAYER_SOLID_COLOR); + backgroud_view_->layer()->SetFillsBoundsOpaquely(false); + backgroud_view_->layer()->SetColor(SkColorSetARGB(60, 0, 0, 0)); + + AddChildView(backgroud_view_); AddChildView(new_desk_button_); - new_desk_button_->SetEnabled(DesksController::Get()->CanCreateDesks()); + UpdateNewDeskButtonState(); + DesksController::Get()->AddObserver(this); +} + +DesksBarView::~DesksBarView() { + DesksController::Get()->RemoveObserver(this); } // static int DesksBarView::GetBarHeight() { - // TODO(afakhry): Bar expands when we add the second desk. - return 48; + return kBarHeight; +} + +void DesksBarView::Init() { + UpdateNewMiniViews(); } const char* DesksBarView::GetClassName() const { @@ -31,6 +68,8 @@ } void DesksBarView::Layout() { + backgroud_view_->SetBoundsRect(bounds()); + constexpr int kButtonRightMargin = 36; constexpr int kIconAndTextHorizontalPadding = 16; constexpr int kIconAndTextVerticalPadding = 8; @@ -45,7 +84,24 @@ new_desk_button_size.width(), new_desk_button_size.height()}; new_desk_button_->SetBoundsRect(button_bounds); - // TODO(afakhry): Layout thumbnails. + if (mini_views_.empty()) + return; + + constexpr int kMiniViewsSpacing = 8; + const gfx::Size mini_view_size = mini_views_[0]->GetPreferredSize(); + const int total_width = + mini_views_.size() * (mini_view_size.width() + kMiniViewsSpacing) - + kMiniViewsSpacing; + gfx::Rect mini_views_bounds = bounds(); + mini_views_bounds.ClampToCenteredSize( + gfx::Size(total_width, mini_view_size.height())); + + int x = mini_views_bounds.x(); + const int y = mini_views_bounds.y(); + for (auto& mini_view : mini_views_) { + mini_view->SetBoundsRect(gfx::Rect(gfx::Point(x, y), mini_view_size)); + x += (mini_view_size.width() + kMiniViewsSpacing); + } } void DesksBarView::ButtonPressed(views::Button* sender, @@ -53,10 +109,79 @@ auto* controller = DesksController::Get(); if (sender == new_desk_button_ && controller->CanCreateDesks()) { controller->NewDesk(); + } else { + // TODO(afakhry): Handle mini_view presses. + } + + UpdateNewDeskButtonState(); +} + +void DesksBarView::OnDeskAdded(const Desk* desk) { + UpdateNewMiniViews(); +} + +void DesksBarView::OnDeskRemoved(const Desk* desk) { + auto iter = + std::find_if(mini_views_.begin(), mini_views_.end(), + [desk](const std::unique_ptr<DeskMiniView>& mini_view) { + return desk == mini_view->desk(); + }); + + DCHECK(iter != mini_views_.end()); + + mini_views_.erase(iter); + Layout(); + UpdateMiniViewsLabels(); + + // TODO(afakhry): Add animations. + + UpdateNewDeskButtonState(); +} + +void DesksBarView::UpdateNewDeskButtonState() { + new_desk_button_->SetEnabled(DesksController::Get()->CanCreateDesks()); +} + +void DesksBarView::UpdateNewMiniViews() { + const auto& desks = DesksController::Get()->desks(); + if (desks.size() < 2) { + // We do not show mini_views when we have a single desk. + DCHECK(mini_views_.empty()); return; } - // TODO(afakhry): Handle thumbnail presses. + // This should not be called when a desk is removed. + DCHECK_LE(mini_views_.size(), desks.size()); + + for (const auto& desk : desks) { + if (!FindMiniViewForDesk(desk.get())) { + mini_views_.emplace_back(std::make_unique<DeskMiniView>( + desk.get(), GetMiniViewTitle(mini_views_.size()), this)); + DeskMiniView* mini_view = mini_views_.back().get(); + mini_view->set_owned_by_client(); + AddChildView(mini_view); + } + } + + Layout(); + + // TODO(afakhry): Add animations. +} + +DeskMiniView* DesksBarView::FindMiniViewForDesk(const Desk* desk) const { + for (auto& mini_view : mini_views_) { + if (mini_view->desk() == desk) + return mini_view.get(); + } + + return nullptr; +} + +void DesksBarView::UpdateMiniViewsLabels() { + // TODO(afakhry): Don't do this for user-modified desk labels. + size_t i = 0; + for (auto& mini_view : mini_views_) + mini_view->SetTitle(GetMiniViewTitle(i++)); } } // namespace ash
diff --git a/ash/wm/desks/desks_bar_view.h b/ash/wm/desks/desks_bar_view.h index 77594a37..f4912c92 100644 --- a/ash/wm/desks/desks_bar_view.h +++ b/ash/wm/desks/desks_bar_view.h
@@ -5,22 +5,45 @@ #ifndef ASH_WM_DESKS_DESKS_BAR_VIEW_H_ #define ASH_WM_DESKS_DESKS_BAR_VIEW_H_ +#include <memory> +#include <vector> + +#include "ash/ash_export.h" +#include "ash/wm/desks/desks_controller.h" #include "base/macros.h" #include "ui/views/controls/button/button.h" namespace ash { +class DeskMiniView; class NewDeskButton; // A bar that resides at the top portion of the overview mode's ShieldView, -// which contains the virtual desks thumbnails, as well as the new desk button. -class DesksBarView : public views::View, public views::ButtonListener { +// which contains the virtual desks mini_views, as well as the new desk button. +class ASH_EXPORT DesksBarView : public views::View, + public views::ButtonListener, + public DesksController::Observer { public: DesksBarView(); - ~DesksBarView() override = default; + ~DesksBarView() override; + // The height of the desk bar view. static int GetBarHeight(); + views::View* backgroud_view() const { return backgroud_view_; } + + NewDeskButton* new_desk_button() const { return new_desk_button_; } + + const std::vector<std::unique_ptr<DeskMiniView>>& mini_views() const { + return mini_views_; + } + + // Initializes and creates mini_views for any pre-existing desks, before the + // bar was created. This should only be called after this view has been added + // to a widget, as it needs to call `GetWidget()` when it's performing a + // layout. + void Init(); + // views::View: const char* GetClassName() const override; void Layout() override; @@ -28,9 +51,37 @@ // views::ButtonListener: void ButtonPressed(views::Button* sender, const ui::Event& event) override; + // DesksController::Observer: + void OnDeskAdded(const Desk* desk) override; + void OnDeskRemoved(const Desk* desk) override; + private: + // This is called on initialization or when a new desk is created to create + // the needed new mini_views. + void UpdateNewMiniViews(); + + // Updates the enabled state of the new desk button when the ability to create + // new desk may have changed. + void UpdateNewDeskButtonState(); + + // Returns the mini_view associated with |desk| or nullptr if no mini_view + // has been created for it yet. + DeskMiniView* FindMiniViewForDesk(const Desk* desk) const; + + // Updates the text labels of the existing mini_views. This is called after a + // mini_view has been removed. + void UpdateMiniViewsLabels(); + + // A view that shows a dark gary transparent background that can be animated + // when the very first mini_views are created. + views::View* backgroud_view_; + NewDeskButton* new_desk_button_; + // The views representing desks mini_views. They're owned by this DeskBarView + // (i.e. `owned_by_client_` is true). + std::vector<std::unique_ptr<DeskMiniView>> mini_views_; + DISALLOW_COPY_AND_ASSIGN(DesksBarView); };
diff --git a/ash/wm/desks/desks_controller.cc b/ash/wm/desks/desks_controller.cc index 4be7a05..78d1bfc2 100644 --- a/ash/wm/desks/desks_controller.cc +++ b/ash/wm/desks/desks_controller.cc
@@ -4,23 +4,73 @@ #include "ash/wm/desks/desks_controller.h" +#include <utility> + #include "ash/shell.h" +#include "ash/wm/desks/desk.h" #include "base/logging.h" namespace ash { +DesksController::DesksController() { + // There's always one default desk. + NewDesk(); +} + +DesksController::~DesksController() = default; + +// static +constexpr size_t DesksController::kMaxNumberOfDesks; + // static DesksController* DesksController::Get() { return Shell::Get()->desks_controller(); } +void DesksController::AddObserver(Observer* observer) { + observers_.AddObserver(observer); +} + +void DesksController::RemoveObserver(Observer* observer) { + observers_.RemoveObserver(observer); +} + bool DesksController::CanCreateDesks() const { - // TODO(afakhry): Maximum of four desks. - return true; + // TODO(afakhry): Disable creating new desks in tablet mode. + return desks_.size() < kMaxNumberOfDesks; +} + +bool DesksController::CanRemoveDesks() const { + return desks_.size() > 1; } void DesksController::NewDesk() { - NOTIMPLEMENTED(); + DCHECK(CanCreateDesks()); + + desks_.emplace_back(std::make_unique<Desk>()); + + for (auto& observer : observers_) + observer.OnDeskAdded(desks_.back().get()); +} + +void DesksController::RemoveDesk(const Desk* desk) { + DCHECK(CanRemoveDesks()); + + auto iter = std::find_if( + desks_.begin(), desks_.end(), + [desk](const std::unique_ptr<Desk>& d) { return d.get() == desk; }); + DCHECK(iter != desks_.end()); + + // TODO(afakhry): + // - Move windows in removed desk (if any) to the currently active desk. + // - If the active desk is the one being removed, activate the desk to its + // left, if no desk to the left, activate one on the right. + + std::unique_ptr<Desk> removed_desk = std::move(*iter); + desks_.erase(iter); + + for (auto& observer : observers_) + observer.OnDeskRemoved(removed_desk.get()); } } // namespace ash
diff --git a/ash/wm/desks/desks_controller.h b/ash/wm/desks/desks_controller.h index 6d69c98..35f14071 100644 --- a/ash/wm/desks/desks_controller.h +++ b/ash/wm/desks/desks_controller.h
@@ -5,27 +5,69 @@ #ifndef ASH_WM_DESKS_DESKS_CONTROLLER_H_ #define ASH_WM_DESKS_DESKS_CONTROLLER_H_ +#include <memory> +#include <vector> + +#include "ash/ash_export.h" #include "base/macros.h" +#include "base/observer_list.h" namespace ash { +class Desk; + // Defines a controller for creating, destroying and managing virtual desks and // their windows. -class DesksController { +class ASH_EXPORT DesksController { public: - DesksController() = default; - ~DesksController() = default; + class Observer { + public: + // Called when |desk| has been created and added to + // `DesksController::desks_`. + virtual void OnDeskAdded(const Desk* desk) = 0; + + // Called when |desk| has been removed from `DesksController::desks_`. + // However |desk| is kept alive temporarily and will be destroyed after all + // observers have been notified with this. + virtual void OnDeskRemoved(const Desk* desk) = 0; + + protected: + virtual ~Observer() = default; + }; + + DesksController(); + ~DesksController(); + + static constexpr size_t kMaxNumberOfDesks = 4; // Convenience method for returning the DesksController instance. The actual // instance is created and owned by Shell. static DesksController* Get(); + const std::vector<std::unique_ptr<Desk>>& desks() const { return desks_; } + + void AddObserver(Observer* observer); + void RemoveObserver(Observer* observer); + // Returns true if we haven't reached the maximum allowed number of desks. bool CanCreateDesks() const; + // Returns true as long as there are two or more desks. It is required that + // there is at least one single desk at any time. + bool CanRemoveDesks() const; + + // Creates a new desk. CanCreateDesks() must be checked before calling this. void NewDesk(); + // Removes and deletes the given |desk|. |desk| must already exist, and + // CanRemoveDesks() must be checked before this. + void RemoveDesk(const Desk* desk); + private: + std::vector<std::unique_ptr<Desk>> desks_; + + base::ObserverList<Observer>::Unchecked observers_; + DISALLOW_COPY_AND_ASSIGN(DesksController); };
diff --git a/ash/wm/desks/desks_unittests.cc b/ash/wm/desks/desks_unittests.cc new file mode 100644 index 0000000..f75b14c --- /dev/null +++ b/ash/wm/desks/desks_unittests.cc
@@ -0,0 +1,178 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <vector> + +#include "ash/public/cpp/ash_features.h" +#include "ash/shell.h" +#include "ash/test/ash_test_base.h" +#include "ash/wm/desks/close_desk_button.h" +#include "ash/wm/desks/desk_mini_view.h" +#include "ash/wm/desks/desks_bar_view.h" +#include "ash/wm/desks/desks_controller.h" +#include "ash/wm/desks/new_desk_button.h" +#include "ash/wm/overview/overview_controller.h" +#include "ash/wm/overview/overview_grid.h" +#include "ash/wm/overview/overview_session.h" +#include "base/stl_util.h" +#include "base/test/scoped_feature_list.h" +#include "ui/events/test/event_generator.h" + +namespace ash { + +namespace { + +// Defines an observer to test DesksController notifications. +class TestObserver : public DesksController::Observer { + public: + TestObserver() = default; + ~TestObserver() override = default; + + const std::vector<const Desk*>& desks() const { return desks_; } + + // DesksController::Observer: + void OnDeskAdded(const Desk* desk) override { desks_.emplace_back(desk); } + void OnDeskRemoved(const Desk* desk) override { base::Erase(desks_, desk); } + + private: + std::vector<const Desk*> desks_; + + DISALLOW_COPY_AND_ASSIGN(TestObserver); +}; + +class DesksTest : public AshTestBase { + public: + DesksTest() = default; + ~DesksTest() override = default; + + // AshTestBase: + void SetUp() override { + scoped_feature_list_.InitAndEnableFeature(features::kVirtualDesks); + + AshTestBase::SetUp(); + } + + private: + base::test::ScopedFeatureList scoped_feature_list_; + + DISALLOW_COPY_AND_ASSIGN(DesksTest); +}; + +TEST_F(DesksTest, DesksCreationAndRemoval) { + TestObserver observer; + auto* controller = DesksController::Get(); + controller->AddObserver(&observer); + + // There's always a default pre-existing desk that cannot be removed. + EXPECT_EQ(1u, controller->desks().size()); + EXPECT_FALSE(controller->CanRemoveDesks()); + EXPECT_TRUE(controller->CanCreateDesks()); + + // Add desks until no longer possible. + while (controller->CanCreateDesks()) + controller->NewDesk(); + + // Expect we've reached the max number of desks, and we've been notified only + // with the newly created desks. + EXPECT_EQ(DesksController::kMaxNumberOfDesks, controller->desks().size()); + EXPECT_EQ(DesksController::kMaxNumberOfDesks - 1, observer.desks().size()); + EXPECT_TRUE(controller->CanRemoveDesks()); + + // Remove all desks until no longer possible, and expect that there's always + // one default desk remaining. + while (controller->CanRemoveDesks()) + controller->RemoveDesk(observer.desks().back()); + + EXPECT_EQ(1u, controller->desks().size()); + EXPECT_FALSE(controller->CanRemoveDesks()); + EXPECT_TRUE(controller->CanCreateDesks()); + EXPECT_TRUE(observer.desks().empty()); + + controller->RemoveObserver(&observer); +} + +TEST_F(DesksTest, DesksBarViewDeskCreation) { + TestObserver observer; + auto* controller = DesksController::Get(); + + auto* overview_controller = Shell::Get()->overview_controller(); + overview_controller->ToggleOverview(); + EXPECT_TRUE(overview_controller->IsSelecting()); + + const auto* overview_grid = + overview_controller->overview_session()->GetGridWithRootWindow( + Shell::GetPrimaryRootWindow()); + + // TODO(afakhry): Update expected initial grid's y offset when there are no + // desk mini_views once animations are added. + EXPECT_EQ(DesksBarView::GetBarHeight(), overview_grid->GetGridYOffset()); + + const auto* desks_bar_view = overview_grid->GetDesksBarViewForTesting(); + + // Since we have a single default desk, there should be no mini_views, and the + // new desk button is enabled. + DCHECK(desks_bar_view); + EXPECT_TRUE(desks_bar_view->mini_views().empty()); + EXPECT_TRUE(desks_bar_view->new_desk_button()->enabled()); + + // Click many times on the new desk button and expect only the max number of + // desks will be created, and the button is no longer enabled. + const gfx::Point button_center = + desks_bar_view->new_desk_button()->GetBoundsInScreen().CenterPoint(); + + auto* event_generator = GetEventGenerator(); + event_generator->MoveMouseTo(button_center); + for (size_t i = 0; i < DesksController::kMaxNumberOfDesks + 2; ++i) + event_generator->ClickLeftButton(); + + EXPECT_EQ(DesksBarView::GetBarHeight(), overview_grid->GetGridYOffset()); + EXPECT_EQ(DesksController::kMaxNumberOfDesks, controller->desks().size()); + EXPECT_EQ(controller->desks().size(), desks_bar_view->mini_views().size()); + EXPECT_FALSE(controller->CanCreateDesks()); + EXPECT_TRUE(controller->CanRemoveDesks()); + EXPECT_FALSE(desks_bar_view->new_desk_button()->enabled()); + + // Hover over one of the mini_views, and expect that the close button becomes + // visible. + const auto* mini_view = desks_bar_view->mini_views().back().get(); + EXPECT_FALSE(mini_view->close_desk_button()->visible()); + const gfx::Point mini_view_center = + mini_view->GetBoundsInScreen().CenterPoint(); + event_generator->MoveMouseTo(mini_view_center); + EXPECT_TRUE(mini_view->close_desk_button()->visible()); + + // Use the close button to close the desk. + event_generator->MoveMouseTo( + mini_view->close_desk_button()->GetBoundsInScreen().CenterPoint()); + event_generator->ClickLeftButton(); + + // The new desk button is now enabled again. + EXPECT_EQ(DesksController::kMaxNumberOfDesks - 1, controller->desks().size()); + EXPECT_EQ(controller->desks().size(), desks_bar_view->mini_views().size()); + EXPECT_TRUE(controller->CanCreateDesks()); + EXPECT_TRUE(desks_bar_view->new_desk_button()->enabled()); + + // Exit overview mode and re-enter. Since we have more than one pre-existing + // desks, their mini_views should be created upon construction of the desks + // bar. + overview_controller->ToggleOverview(); + EXPECT_FALSE(overview_controller->IsSelecting()); + overview_controller->ToggleOverview(); + EXPECT_TRUE(overview_controller->IsSelecting()); + + // Get the new grid and the new desk_bar_view. + overview_grid = + overview_controller->overview_session()->GetGridWithRootWindow( + Shell::GetPrimaryRootWindow()); + EXPECT_EQ(DesksBarView::GetBarHeight(), overview_grid->GetGridYOffset()); + desks_bar_view = overview_grid->GetDesksBarViewForTesting(); + + DCHECK(desks_bar_view); + EXPECT_EQ(controller->desks().size(), desks_bar_view->mini_views().size()); + EXPECT_TRUE(desks_bar_view->new_desk_button()->enabled()); +} + +} // namespace + +} // namespace ash
diff --git a/ash/wm/desks/new_desk_button.cc b/ash/wm/desks/new_desk_button.cc index 9c72659..5876a92 100644 --- a/ash/wm/desks/new_desk_button.cc +++ b/ash/wm/desks/new_desk_button.cc
@@ -41,9 +41,9 @@ layer()->SetFillsBoundsOpaquely(false); SetHorizontalAlignment(gfx::ALIGN_CENTER); SetImage(views::Button::STATE_NORMAL, - gfx::CreateVectorIcon(kNewDeskButtonIcon, SK_ColorWHITE)); + gfx::CreateVectorIcon(kDesksNewDeskButtonIcon, SK_ColorWHITE)); SetImage(views::Button::STATE_DISABLED, - gfx::CreateVectorIcon(kNewDeskButtonIcon, SK_ColorGRAY)); + gfx::CreateVectorIcon(kDesksNewDeskButtonIcon, SK_ColorGRAY)); SetTextColor(views::Button::STATE_NORMAL, SK_ColorWHITE); SetTextColor(views::Button::STATE_HOVERED, SK_ColorWHITE); SetTextColor(views::Button::STATE_PRESSED, SK_ColorWHITE);
diff --git a/ash/wm/desks/new_desk_button.h b/ash/wm/desks/new_desk_button.h index 696ca40..4696e09 100644 --- a/ash/wm/desks/new_desk_button.h +++ b/ash/wm/desks/new_desk_button.h
@@ -7,6 +7,7 @@ #include <memory> +#include "ash/ash_export.h" #include "base/macros.h" #include "ui/views/controls/button/label_button.h" @@ -14,7 +15,7 @@ // A button view that shows up in the top-right corner of the screen when // overview mode is on, which is used to create a new virtual desk. -class NewDeskButton : public views::LabelButton { +class ASH_EXPORT NewDeskButton : public views::LabelButton { public: NewDeskButton(views::ButtonListener* listener); ~NewDeskButton() override = default;
diff --git a/ash/wm/overview/overview_grid.cc b/ash/wm/overview/overview_grid.cc index ba84a94..4da9284 100644 --- a/ash/wm/overview/overview_grid.cc +++ b/ash/wm/overview/overview_grid.cc
@@ -205,15 +205,24 @@ label_container_->SetVisible(false); AddChildView(label_container_); - - if (features::IsVirtualDesksEnabled()) { - desks_bar_view_ = new DesksBarView; - AddChildView(desks_bar_view_); - } } ~ShieldView() override = default; + const DesksBarView* desks_bar_view() const { return desks_bar_view_; } + + // Call this only after this view has been added to a widget. This is needed + // because the desks mini views need to access the widget to get the + // root window in order to know how to layout themselves. + void MaybeInitVirtualDesksBar() { + if (!features::IsVirtualDesksEnabled()) + return; + + desks_bar_view_ = new DesksBarView; + AddChildView(desks_bar_view_); + desks_bar_view_->Init(); + } + void SetLabelVisibility(bool visible) { label_container_->SetVisible(visible); } @@ -1229,6 +1238,17 @@ return (iter != window_list_.end()) ? (*iter)->GetWindow() : nullptr; } +const DesksBarView* OverviewGrid::GetDesksBarViewForTesting() const { + return shield_view_->desks_bar_view(); +} + +int OverviewGrid::GetGridYOffset() const { + DCHECK(features::IsVirtualDesksEnabled()); + + // TODO(afakhry): Update this when animation is added. + return DesksBarView::GetBarHeight(); +} + void OverviewGrid::InitShieldWidget(bool animate) { // TODO(varkha): The code assumes that SHELF_BACKGROUND_MAXIMIZED is // synonymous with a black shelf background. Update this code if that @@ -1252,6 +1272,7 @@ // Create |shield_view_| and animate its background and label if needed. shield_view_ = new ShieldView(); shield_widget_->SetContentsView(shield_view_); + shield_view_->MaybeInitVirtualDesksBar(); shield_view_->SetGridBounds(bounds_); if (animate) { @@ -1361,8 +1382,11 @@ OverviewItem* ignored_item) { gfx::Rect total_bounds = bounds_; - if (features::IsVirtualDesksEnabled()) - total_bounds.Inset(0, DesksBarView::GetBarHeight(), 0, 0); + if (features::IsVirtualDesksEnabled()) { + total_bounds.set_height(total_bounds.height() - + DesksBarView::GetBarHeight()); + total_bounds.Offset(0, GetGridYOffset()); + } // Windows occupy vertically centered area with additional vertical insets. int horizontal_inset =
diff --git a/ash/wm/overview/overview_grid.h b/ash/wm/overview/overview_grid.h index 0ef0f32f..59172ac 100644 --- a/ash/wm/overview/overview_grid.h +++ b/ash/wm/overview/overview_grid.h
@@ -29,6 +29,8 @@ } namespace ash { + +class DesksBarView; class OverviewItem; // Represents a grid of windows in the Overview Mode in a particular root @@ -213,6 +215,11 @@ // Returns the window of the overview item that contains |location_in_screen|. aura::Window* GetTargetWindowOnLocation(const gfx::Point& location_in_screen); + // The vertical offset by which the overview window grid is pushed down to + // account for the desks thumbnails. Initially when we don't have any + // thumbnails, this value is zero. + int GetGridYOffset() const; + // Returns true if the grid has no more windows. bool empty() const { return window_list_.empty(); } @@ -245,6 +252,8 @@ void set_suspend_reposition(bool value) { suspend_reposition_ = value; } + const DesksBarView* GetDesksBarViewForTesting() const; + private: class ShieldView; class TargetWindowObserver;
diff --git a/base/BUILD.gn b/base/BUILD.gn index dfe6c8ca..4e1c41c 100644 --- a/base/BUILD.gn +++ b/base/BUILD.gn
@@ -3177,6 +3177,7 @@ "test/android/javatests/src/org/chromium/base/test/BaseChromiumRunnerCommon.java", "test/android/javatests/src/org/chromium/base/test/BaseTestResult.java", "test/android/javatests/src/org/chromium/base/test/LifetimeAssertRule.java", + "test/android/javatests/src/org/chromium/base/test/DestroyActivitiesRule.java", "test/android/javatests/src/org/chromium/base/test/ScreenshotOnFailureStatement.java", "test/android/javatests/src/org/chromium/base/test/SetUpTestRule.java", "test/android/javatests/src/org/chromium/base/test/SetUpStatement.java",
diff --git a/base/android/java/src/org/chromium/base/ApplicationStatus.java b/base/android/java/src/org/chromium/base/ApplicationStatus.java index 775c316a..d83db2f6 100644 --- a/base/android/java/src/org/chromium/base/ApplicationStatus.java +++ b/base/android/java/src/org/chromium/base/ApplicationStatus.java
@@ -216,7 +216,7 @@ } } - private static boolean isInitialized() { + public static boolean isInitialized() { synchronized (sActivityInfo) { return sCurrentApplicationState != ApplicationState.UNKNOWN; }
diff --git a/base/android/linker/linker_jni.cc b/base/android/linker/linker_jni.cc index f29b98b..d1aeab2 100644 --- a/base/android/linker/linker_jni.cc +++ b/base/android/linker/linker_jni.cc
@@ -258,8 +258,8 @@ // Ensure libraries located in the same directory as the linker // can be loaded before system ones. - crazy_context_add_search_path_for_address( - s_crazy_context, reinterpret_cast<void*>(&GetCrazyContext)); + crazy_add_search_path_for_address( + reinterpret_cast<void*>(&GetCrazyContext)); } return s_crazy_context; @@ -365,8 +365,7 @@ snprintf(search_path, sizeof(search_path), "%s!lib/" CURRENT_ABI "/", apk_path.c_str()); - crazy_context_t* context = GetCrazyContext(); - crazy_context_add_search_path(context, search_path); + crazy_add_search_path(search_path); return true; } @@ -524,9 +523,9 @@ &linker_class)) return false; - // Save JavaVM* handle into context. - crazy_context_t* context = GetCrazyContext(); - crazy_context_set_java_vm(context, vm, JNI_VERSION_1_4); + // Save JavaVM* handle into linker, so that it can call JNI_OnLoad() + // automatically when loading libraries containing JNI entry points. + crazy_set_java_vm(vm, JNI_VERSION_1_4); return true; }
diff --git a/base/debug/stack_trace_posix.cc b/base/debug/stack_trace_posix.cc index 1f015ee..d4b8b3a 100644 --- a/base/debug/stack_trace_posix.cc +++ b/base/debug/stack_trace_posix.cc
@@ -577,10 +577,10 @@ // it cannot be called before the singleton is created. SandboxSymbolizeHelper* instance = GetInstance(); - // The assumption here is that iterating over - // std::vector<MappedMemoryRegion> using a const_iterator does not allocate - // dynamic memory, hence it is async-signal-safe. - for (const MappedMemoryRegion& region : instance->regions_) { + // Cannot use STL iterators here, since debug iterators use locks. + // NOLINTNEXTLINE(modernize-loop-convert) + for (size_t i = 0; i < instance->regions_.size(); ++i) { + const MappedMemoryRegion& region = instance->regions_[i]; if (region.start <= pc && pc < region.end) { start_address = region.start; base_address = region.base;
diff --git a/base/process/launch_posix.cc b/base/process/launch_posix.cc index 71f8f72..fa2c0e9 100644 --- a/base/process/launch_posix.cc +++ b/base/process/launch_posix.cc
@@ -431,7 +431,10 @@ #endif // defined(OS_CHROMEOS) // Cannot use STL iterators here, since debug iterators use locks. - for (const auto& value : options.fds_to_remap) { + // NOLINTNEXTLINE(modernize-loop-convert) + for (size_t i = 0; i < options.fds_to_remap.size(); ++i) { + const FileHandleMappingVector::value_type& value = + options.fds_to_remap[i]; fd_shuffle1.push_back(InjectionArc(value.first, value.second, false)); fd_shuffle2.push_back(InjectionArc(value.first, value.second, false)); }
diff --git a/base/sampling_heap_profiler/module_cache.cc b/base/sampling_heap_profiler/module_cache.cc index 2fb9369..b5524a3 100644 --- a/base/sampling_heap_profiler/module_cache.cc +++ b/base/sampling_heap_profiler/module_cache.cc
@@ -8,33 +8,6 @@ namespace base { -ModuleCache::Module::Module(uintptr_t base_address, - const std::string& id, - const FilePath& debug_basename, - size_t size) - : base_address_(base_address), - id_(id), - debug_basename_(debug_basename), - size_(size) {} - -ModuleCache::Module::~Module() = default; - -uintptr_t ModuleCache::Module::GetBaseAddress() const { - return base_address_; -} - -std::string ModuleCache::Module::GetId() const { - return id_; -} - -FilePath ModuleCache::Module::GetDebugBasename() const { - return debug_basename_; -} - -size_t ModuleCache::Module::GetSize() const { - return size_; -} - ModuleCache::ModuleCache() = default; ModuleCache::~ModuleCache() = default;
diff --git a/base/sampling_heap_profiler/module_cache.h b/base/sampling_heap_profiler/module_cache.h index 8755b8e5..2b5189b 100644 --- a/base/sampling_heap_profiler/module_cache.h +++ b/base/sampling_heap_profiler/module_cache.h
@@ -26,17 +26,14 @@ // associated state. class BASE_EXPORT Module { public: - Module(uintptr_t base_address, - const std::string& id, - const FilePath& filename, - size_t size); - ~Module(); + Module() = default; + virtual ~Module() = default; Module(const Module&) = delete; Module& operator=(const Module&) = delete; // Gets the base address of the module. - uintptr_t GetBaseAddress() const; + virtual uintptr_t GetBaseAddress() const = 0; // Gets the opaque binary string that uniquely identifies a particular // program version with high probability. This is parsed from headers of the @@ -45,20 +42,14 @@ // Contents of the .note.gnu.build-id field. // On Windows: // GUID + AGE in the debug image headers of a module. - std::string GetId() const; + virtual std::string GetId() const = 0; // Gets the debug basename of the module. This is the basename of the PDB // file on Windows and the basename of the binary on other platforms. - FilePath GetDebugBasename() const; + virtual FilePath GetDebugBasename() const = 0; // Gets the size of the module. - size_t GetSize() const; - - private: - uintptr_t base_address_; - std::string id_; - FilePath debug_basename_; - size_t size_; + virtual size_t GetSize() const = 0; }; ModuleCache();
diff --git a/base/sampling_heap_profiler/module_cache_mac.cc b/base/sampling_heap_profiler/module_cache_mac.cc index 287a860..0a9b7a2 100644 --- a/base/sampling_heap_profiler/module_cache_mac.cc +++ b/base/sampling_heap_profiler/module_cache_mac.cc
@@ -63,6 +63,33 @@ } // namespace +class MacModule : public ModuleCache::Module { + public: + MacModule(uintptr_t base_address, + const std::string& id, + const FilePath& debug_basename, + size_t size) + : base_address_(base_address), + id_(id), + debug_basename_(debug_basename), + size_(size) {} + + MacModule(const MacModule&) = delete; + MacModule& operator=(const MacModule&) = delete; + + // ModuleCache::Module + uintptr_t GetBaseAddress() const override { return base_address_; } + std::string GetId() const override { return id_; } + FilePath GetDebugBasename() const override { return debug_basename_; } + size_t GetSize() const override { return size_; } + + private: + uintptr_t base_address_; + std::string id_; + FilePath debug_basename_; + size_t size_; +}; + // static std::unique_ptr<ModuleCache::Module> ModuleCache::CreateModuleForAddress( uintptr_t address) { @@ -70,7 +97,7 @@ if (!dladdr(reinterpret_cast<const void*>(address), &inf)) return nullptr; auto base_module_address = reinterpret_cast<uintptr_t>(inf.dli_fbase); - return std::make_unique<Module>( + return std::make_unique<MacModule>( base_module_address, GetUniqueId(inf.dli_fbase), FilePath(inf.dli_fname).BaseName(), GetModuleTextSize(inf.dli_fbase)); }
diff --git a/base/sampling_heap_profiler/module_cache_win.cc b/base/sampling_heap_profiler/module_cache_win.cc index 954cef0..30d4d15 100644 --- a/base/sampling_heap_profiler/module_cache_win.cc +++ b/base/sampling_heap_profiler/module_cache_win.cc
@@ -65,6 +65,33 @@ } // namespace +class WindowsModule : public ModuleCache::Module { + public: + WindowsModule(uintptr_t base_address, + const std::string& id, + const FilePath& debug_basename, + size_t size) + : base_address_(base_address), + id_(id), + debug_basename_(debug_basename), + size_(size) {} + + WindowsModule(const WindowsModule&) = delete; + WindowsModule& operator=(const WindowsModule&) = delete; + + // ModuleCache::Module + uintptr_t GetBaseAddress() const override { return base_address_; } + std::string GetId() const override { return id_; } + FilePath GetDebugBasename() const override { return debug_basename_; } + size_t GetSize() const override { return size_; } + + private: + uintptr_t base_address_; + std::string id_; + FilePath debug_basename_; + size_t size_; +}; + // static std::unique_ptr<ModuleCache::Module> ModuleCache::CreateModuleForAddress( uintptr_t address) { @@ -114,7 +141,7 @@ return nullptr; } - return std::make_unique<Module>( + return std::make_unique<WindowsModule>( reinterpret_cast<uintptr_t>(module_info.lpBaseOfDll), build_id, pdb_name, module_info.SizeOfImage); }
diff --git a/base/system/sys_info_win.cc b/base/system/sys_info_win.cc index 54984d4..87650d8 100644 --- a/base/system/sys_info_win.cc +++ b/base/system/sys_info_win.cc
@@ -131,8 +131,7 @@ // static std::string SysInfo::OperatingSystemArchitecture() { - win::OSInfo::WindowsArchitecture arch = - win::OSInfo::GetInstance()->architecture(); + win::OSInfo::WindowsArchitecture arch = win::OSInfo::GetArchitecture(); switch (arch) { case win::OSInfo::X86_ARCHITECTURE: return "x86";
diff --git a/base/test/android/javatests/src/org/chromium/base/test/BaseJUnit4ClassRunner.java b/base/test/android/javatests/src/org/chromium/base/test/BaseJUnit4ClassRunner.java index 7c203f8..161f2cc 100644 --- a/base/test/android/javatests/src/org/chromium/base/test/BaseJUnit4ClassRunner.java +++ b/base/test/android/javatests/src/org/chromium/base/test/BaseJUnit4ClassRunner.java
@@ -174,7 +174,7 @@ */ @CallSuper protected List<TestRule> getDefaultTestRules() { - return Collections.singletonList(new LifetimeAssertRule()); + return Arrays.asList(new DestroyActivitiesRule(), new LifetimeAssertRule()); } /**
diff --git a/base/test/android/javatests/src/org/chromium/base/test/DestroyActivitiesRule.java b/base/test/android/javatests/src/org/chromium/base/test/DestroyActivitiesRule.java new file mode 100644 index 0000000..ffbc213 --- /dev/null +++ b/base/test/android/javatests/src/org/chromium/base/test/DestroyActivitiesRule.java
@@ -0,0 +1,81 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.base.test; + +import android.app.Activity; + +import org.junit.rules.ExternalResource; + +import org.chromium.base.ActivityState; +import org.chromium.base.ApplicationStatus; +import org.chromium.base.Log; +import org.chromium.base.ThreadUtils; +import org.chromium.base.test.util.CallbackHelper; + +import java.util.concurrent.TimeoutException; + +/** + * This is to ensure all calls to onDestroy() are performed before starting the next test. + * We could probably remove this when crbug.com/932130 is fixed. + */ +public class DestroyActivitiesRule extends ExternalResource { + private static final String TAG = "DestroyActivities"; + @Override + public void after() { + if (!ApplicationStatus.isInitialized()) { + return; + } + CallbackHelper allDestroyedCalledback = new CallbackHelper(); + ApplicationStatus.ActivityStateListener activityStateListener = + new ApplicationStatus.ActivityStateListener() { + @Override + public void onActivityStateChange(Activity activity, int newState) { + switch (newState) { + case ActivityState.DESTROYED: + if (ApplicationStatus.isEveryActivityDestroyed()) { + allDestroyedCalledback.notifyCalled(); + ApplicationStatus.unregisterActivityStateListener(this); + } + break; + case ActivityState.CREATED: + if (!activity.isFinishing()) { + // This is required to ensure we finish any activities created + // after doing the bulk finish operation below. + activity.finish(); + } + break; + } + } + }; + + ThreadUtils.runOnUiThread(() -> { + if (ApplicationStatus.isEveryActivityDestroyed()) { + allDestroyedCalledback.notifyCalled(); + } else { + ApplicationStatus.registerStateListenerForAllActivities(activityStateListener); + } + for (Activity a : ApplicationStatus.getRunningActivities()) { + if (!a.isFinishing()) { + a.finish(); + } + } + }); + try { + allDestroyedCalledback.waitForCallback(); + } catch (InterruptedException | TimeoutException e) { + // There appears to be a framework bug on K and L where onStop and onDestroy are not + // called for a handful of tests. We ignore these exceptions. + Log.w(TAG, "Activity failed to be destroyed after a test"); + + ThreadUtils.runOnUiThreadBlocking(() -> { + for (Activity a : ApplicationStatus.getRunningActivities()) { + ApplicationStatus.onStateChangeForTesting(a, ActivityState.DESTROYED); + } + // Make sure subsequent tests don't have these notifications firing. + ApplicationStatus.unregisterActivityStateListener(activityStateListener); + }); + } + } +}
diff --git a/base/threading/scoped_blocking_call.cc b/base/threading/scoped_blocking_call.cc index 8034c6c..f5fcad0 100644 --- a/base/threading/scoped_blocking_call.cc +++ b/base/threading/scoped_blocking_call.cc
@@ -65,9 +65,6 @@ } // namespace internal -ScopedBlockingCall::ScopedBlockingCall(BlockingType blocking_type) - : ScopedBlockingCall(FROM_HERE, blocking_type) {} - ScopedBlockingCall::ScopedBlockingCall(const Location& from_here, BlockingType blocking_type) : UncheckedScopedBlockingCall(blocking_type) {
diff --git a/base/threading/scoped_blocking_call.h b/base/threading/scoped_blocking_call.h index 022a773f..4ca728d 100644 --- a/base/threading/scoped_blocking_call.h +++ b/base/threading/scoped_blocking_call.h
@@ -67,13 +67,15 @@ // Good: // Data data; // { -// ScopedBlockingCall scoped_blocking_call(BlockingType::WILL_BLOCK); +// ScopedBlockingCall scoped_blocking_call( +// FROM_HERE, BlockingType::WILL_BLOCK); // data = GetDataFromNetwork(); // } // CPUIntensiveProcessing(data); // // Bad: -// ScopedBlockingCall scoped_blocking_call(BlockingType::WILL_BLOCK); +// ScopedBlockingCall scoped_blocking_call(FROM_HERE, +// BlockingType::WILL_BLOCK); // Data data = GetDataFromNetwork(); // CPUIntensiveProcessing(data); // CPU usage within a ScopedBlockingCall. // @@ -81,7 +83,8 @@ // Data a; // Data b; // { -// ScopedBlockingCall scoped_blocking_call(BlockingType::MAY_BLOCK); +// ScopedBlockingCall scoped_blocking_call( +// FROM_HERE, BlockingType::MAY_BLOCK); // a = GetDataFromMemoryCacheOrNetwork(); // b = GetDataFromMemoryCacheOrNetwork(); // } @@ -89,7 +92,8 @@ // CPUIntensiveProcessing(b); // // Bad: -// ScopedBlockingCall scoped_blocking_call(BlockingType::MAY_BLOCK); +// ScopedBlockingCall scoped_blocking_call( +// FROM_HERE, BlockingType::MAY_BLOCK); // Data a = GetDataFromMemoryCacheOrNetwork(); // Data b = GetDataFromMemoryCacheOrNetwork(); // CPUIntensiveProcessing(a); // CPU usage within a ScopedBlockingCall. @@ -101,7 +105,8 @@ // // Bad: // base::WaitableEvent waitable_event(...); -// ScopedBlockingCall scoped_blocking_call(BlockingType::WILL_BLOCK); +// ScopedBlockingCall scoped_blocking_call( +// FROM_HERE, BlockingType::WILL_BLOCK); // waitable_event.Wait(); // Wait() instantiates its own ScopedBlockingCall. // // When a ScopedBlockingCall is instantiated from a TaskScheduler parallel or @@ -110,7 +115,6 @@ class BASE_EXPORT ScopedBlockingCall : public internal::UncheckedScopedBlockingCall { public: - explicit ScopedBlockingCall(BlockingType blocking_type); ScopedBlockingCall(const Location& from_here, BlockingType blocking_type); ~ScopedBlockingCall(); };
diff --git a/base/trace_event/builtin_categories.h b/base/trace_event/builtin_categories.h index 8f4f894f..ac68abb4 100644 --- a/base/trace_event/builtin_categories.h +++ b/base/trace_event/builtin_categories.h
@@ -67,8 +67,7 @@ X("explore_sites") \ X("FileSystem") \ X("file_system_provider") \ - X("font_loader") \ - X("font_service") \ + X("fonts") \ X("GAMEPAD") \ X("gpu") \ X("gpu.capture") \
diff --git a/base/win/windows_version.cc b/base/win/windows_version.cc index 79d9446..8f2b2da 100644 --- a/base/win/windows_version.cc +++ b/base/win/windows_version.cc
@@ -56,6 +56,12 @@ return static_cast<int>(ubr); } +const _SYSTEM_INFO& GetSystemInfoStorage() { + static _SYSTEM_INFO system_info = {}; + ::GetNativeSystemInfo(&system_info); + return system_info; +} + } // namespace // static @@ -66,9 +72,6 @@ _OSVERSIONINFOEXW version_info = {sizeof(version_info)}; ::GetVersionEx(reinterpret_cast<_OSVERSIONINFOW*>(&version_info)); - _SYSTEM_INFO system_info = {}; - ::GetNativeSystemInfo(&system_info); - DWORD os_type = 0; if (version_info.dwMajorVersion == 6 || version_info.dwMajorVersion == 10) { // Only present on Vista+. @@ -79,7 +82,7 @@ 0, 0, &os_type); } - return new OSInfo(version_info, system_info, os_type); + return new OSInfo(version_info, GetSystemInfoStorage(), os_type); }(); return &info; @@ -90,11 +93,26 @@ return *GetInstanceStorage(); } +// static +OSInfo::WindowsArchitecture OSInfo::GetArchitecture() { + switch (GetSystemInfoStorage().wProcessorArchitecture) { + case PROCESSOR_ARCHITECTURE_INTEL: + return X86_ARCHITECTURE; + case PROCESSOR_ARCHITECTURE_AMD64: + return X64_ARCHITECTURE; + case PROCESSOR_ARCHITECTURE_IA64: + return IA64_ARCHITECTURE; + case PROCESSOR_ARCHITECTURE_ARM64: + return ARM64_ARCHITECTURE; + default: + return OTHER_ARCHITECTURE; + } +} + OSInfo::OSInfo(const _OSVERSIONINFOEXW& version_info, const _SYSTEM_INFO& system_info, int os_type) : version_(VERSION_PRE_XP), - architecture_(OTHER_ARCHITECTURE), wow64_status_(GetWOW64StatusForProcess(GetCurrentProcess())) { version_number_.major = version_info.dwMajorVersion; version_number_.minor = version_info.dwMinorVersion; @@ -106,14 +124,6 @@ service_pack_.minor = version_info.wServicePackMinor; service_pack_str_ = WideToUTF8(version_info.szCSDVersion); - switch (system_info.wProcessorArchitecture) { - case PROCESSOR_ARCHITECTURE_INTEL: architecture_ = X86_ARCHITECTURE; break; - case PROCESSOR_ARCHITECTURE_AMD64: architecture_ = X64_ARCHITECTURE; break; - case PROCESSOR_ARCHITECTURE_IA64: architecture_ = IA64_ARCHITECTURE; break; - case PROCESSOR_ARCHITECTURE_ARM64: - architecture_ = ARM64_ARCHITECTURE; - break; - } processors_ = system_info.dwNumberOfProcessors; allocation_granularity_ = system_info.dwAllocationGranularity;
diff --git a/base/win/windows_version.h b/base/win/windows_version.h index 82cfcf6..fef7c9e 100644 --- a/base/win/windows_version.h +++ b/base/win/windows_version.h
@@ -110,6 +110,14 @@ static OSInfo* GetInstance(); + // Separate from the rest of OSInfo so it can be used during early process + // initialization. + static WindowsArchitecture GetArchitecture(); + + // Like wow64_status(), but for the supplied handle instead of the current + // process. This doesn't touch member state, so you can bypass the singleton. + static WOW64Status GetWOW64StatusForProcess(HANDLE process_handle); + Version version() const { return version_; } Version Kernel32Version() const; base::Version Kernel32BaseVersion() const; @@ -118,16 +126,13 @@ VersionType version_type() const { return version_type_; } ServicePack service_pack() const { return service_pack_; } std::string service_pack_str() const { return service_pack_str_; } - WindowsArchitecture architecture() const { return architecture_; } + // TODO(thestig): Switch callers to GetArchitecture(). + WindowsArchitecture architecture() const { return GetArchitecture(); } int processors() const { return processors_; } size_t allocation_granularity() const { return allocation_granularity_; } WOW64Status wow64_status() const { return wow64_status_; } std::string processor_model_name(); - // Like wow64_status(), but for the supplied handle instead of the current - // process. This doesn't touch member state, so you can bypass the singleton. - static WOW64Status GetWOW64StatusForProcess(HANDLE process_handle); - private: friend class base::test::ScopedOSInfoOverride; FRIEND_TEST_ALL_PREFIXES(OSInfo, MajorMinorBuildToVersion); @@ -150,7 +155,6 @@ // installed on the system. If no Service Pack has been installed, the string // is empty. std::string service_pack_str_; - WindowsArchitecture architecture_; int processors_; size_t allocation_granularity_; WOW64Status wow64_status_;
diff --git a/build/check_gn_headers.py b/build/check_gn_headers.py index f6ae8f5..2de11b83 100755 --- a/build/check_gn_headers.py +++ b/build/check_gn_headers.py
@@ -297,6 +297,10 @@ if f in missing: print count[f], f + if args.json: + # Assume running on the bots. Temporarily return 0 before + # https://crbug.com/937847 is fixed. + return 0 return 1
diff --git a/build/win/BUILD.gn b/build/win/BUILD.gn index d2e911e..febe884 100644 --- a/build/win/BUILD.gn +++ b/build/win/BUILD.gn
@@ -32,49 +32,54 @@ "$root_out_dir/cdb/winext/uext.dll", "$root_out_dir/cdb/winxp/exts.dll", "$root_out_dir/cdb/winxp/ntsdexts.dll", - "$root_out_dir/cdb/api-ms-win-core-console-l1-1-0.dll", - "$root_out_dir/cdb/api-ms-win-core-datetime-l1-1-0.dll", - "$root_out_dir/cdb/api-ms-win-core-debug-l1-1-0.dll", - "$root_out_dir/cdb/api-ms-win-core-errorhandling-l1-1-0.dll", - "$root_out_dir/cdb/api-ms-win-core-file-l1-1-0.dll", - "$root_out_dir/cdb/api-ms-win-core-file-l1-2-0.dll", - "$root_out_dir/cdb/api-ms-win-core-file-l2-1-0.dll", - "$root_out_dir/cdb/api-ms-win-core-handle-l1-1-0.dll", - "$root_out_dir/cdb/api-ms-win-core-heap-l1-1-0.dll", - "$root_out_dir/cdb/api-ms-win-core-interlocked-l1-1-0.dll", - "$root_out_dir/cdb/api-ms-win-core-libraryloader-l1-1-0.dll", - "$root_out_dir/cdb/api-ms-win-core-localization-l1-2-0.dll", - "$root_out_dir/cdb/api-ms-win-core-memory-l1-1-0.dll", - "$root_out_dir/cdb/api-ms-win-core-namedpipe-l1-1-0.dll", - "$root_out_dir/cdb/api-ms-win-core-processenvironment-l1-1-0.dll", - "$root_out_dir/cdb/api-ms-win-core-processthreads-l1-1-0.dll", - "$root_out_dir/cdb/api-ms-win-core-processthreads-l1-1-1.dll", - "$root_out_dir/cdb/api-ms-win-core-profile-l1-1-0.dll", - "$root_out_dir/cdb/api-ms-win-core-rtlsupport-l1-1-0.dll", - "$root_out_dir/cdb/api-ms-win-core-string-l1-1-0.dll", - "$root_out_dir/cdb/api-ms-win-core-synch-l1-1-0.dll", - "$root_out_dir/cdb/api-ms-win-core-synch-l1-2-0.dll", - "$root_out_dir/cdb/api-ms-win-core-sysinfo-l1-1-0.dll", - "$root_out_dir/cdb/api-ms-win-core-timezone-l1-1-0.dll", - "$root_out_dir/cdb/api-ms-win-core-util-l1-1-0.dll", - "$root_out_dir/cdb/api-ms-win-crt-conio-l1-1-0.dll", - "$root_out_dir/cdb/api-ms-win-crt-convert-l1-1-0.dll", - "$root_out_dir/cdb/api-ms-win-crt-environment-l1-1-0.dll", - "$root_out_dir/cdb/api-ms-win-crt-filesystem-l1-1-0.dll", - "$root_out_dir/cdb/api-ms-win-crt-heap-l1-1-0.dll", - "$root_out_dir/cdb/api-ms-win-crt-locale-l1-1-0.dll", - "$root_out_dir/cdb/api-ms-win-crt-math-l1-1-0.dll", - "$root_out_dir/cdb/api-ms-win-crt-multibyte-l1-1-0.dll", - "$root_out_dir/cdb/api-ms-win-crt-private-l1-1-0.dll", - "$root_out_dir/cdb/api-ms-win-crt-process-l1-1-0.dll", - "$root_out_dir/cdb/api-ms-win-crt-runtime-l1-1-0.dll", - "$root_out_dir/cdb/api-ms-win-crt-stdio-l1-1-0.dll", - "$root_out_dir/cdb/api-ms-win-crt-string-l1-1-0.dll", - "$root_out_dir/cdb/api-ms-win-crt-time-l1-1-0.dll", - "$root_out_dir/cdb/api-ms-win-crt-utility-l1-1-0.dll", - "$root_out_dir/cdb/api-ms-win-eventing-provider-l1-1-0.dll", - "$root_out_dir/cdb/ucrtbase.dll", ] + if (current_cpu != "arm64") { + # The UCRT files are not redistributable for ARM64 Win32. + outputs += [ + "$root_out_dir/cdb/api-ms-win-core-console-l1-1-0.dll", + "$root_out_dir/cdb/api-ms-win-core-datetime-l1-1-0.dll", + "$root_out_dir/cdb/api-ms-win-core-debug-l1-1-0.dll", + "$root_out_dir/cdb/api-ms-win-core-errorhandling-l1-1-0.dll", + "$root_out_dir/cdb/api-ms-win-core-file-l1-1-0.dll", + "$root_out_dir/cdb/api-ms-win-core-file-l1-2-0.dll", + "$root_out_dir/cdb/api-ms-win-core-file-l2-1-0.dll", + "$root_out_dir/cdb/api-ms-win-core-handle-l1-1-0.dll", + "$root_out_dir/cdb/api-ms-win-core-heap-l1-1-0.dll", + "$root_out_dir/cdb/api-ms-win-core-interlocked-l1-1-0.dll", + "$root_out_dir/cdb/api-ms-win-core-libraryloader-l1-1-0.dll", + "$root_out_dir/cdb/api-ms-win-core-localization-l1-2-0.dll", + "$root_out_dir/cdb/api-ms-win-core-memory-l1-1-0.dll", + "$root_out_dir/cdb/api-ms-win-core-namedpipe-l1-1-0.dll", + "$root_out_dir/cdb/api-ms-win-core-processenvironment-l1-1-0.dll", + "$root_out_dir/cdb/api-ms-win-core-processthreads-l1-1-0.dll", + "$root_out_dir/cdb/api-ms-win-core-processthreads-l1-1-1.dll", + "$root_out_dir/cdb/api-ms-win-core-profile-l1-1-0.dll", + "$root_out_dir/cdb/api-ms-win-core-rtlsupport-l1-1-0.dll", + "$root_out_dir/cdb/api-ms-win-core-string-l1-1-0.dll", + "$root_out_dir/cdb/api-ms-win-core-synch-l1-1-0.dll", + "$root_out_dir/cdb/api-ms-win-core-synch-l1-2-0.dll", + "$root_out_dir/cdb/api-ms-win-core-sysinfo-l1-1-0.dll", + "$root_out_dir/cdb/api-ms-win-core-timezone-l1-1-0.dll", + "$root_out_dir/cdb/api-ms-win-core-util-l1-1-0.dll", + "$root_out_dir/cdb/api-ms-win-crt-conio-l1-1-0.dll", + "$root_out_dir/cdb/api-ms-win-crt-convert-l1-1-0.dll", + "$root_out_dir/cdb/api-ms-win-crt-environment-l1-1-0.dll", + "$root_out_dir/cdb/api-ms-win-crt-filesystem-l1-1-0.dll", + "$root_out_dir/cdb/api-ms-win-crt-heap-l1-1-0.dll", + "$root_out_dir/cdb/api-ms-win-crt-locale-l1-1-0.dll", + "$root_out_dir/cdb/api-ms-win-crt-math-l1-1-0.dll", + "$root_out_dir/cdb/api-ms-win-crt-multibyte-l1-1-0.dll", + "$root_out_dir/cdb/api-ms-win-crt-private-l1-1-0.dll", + "$root_out_dir/cdb/api-ms-win-crt-process-l1-1-0.dll", + "$root_out_dir/cdb/api-ms-win-crt-runtime-l1-1-0.dll", + "$root_out_dir/cdb/api-ms-win-crt-stdio-l1-1-0.dll", + "$root_out_dir/cdb/api-ms-win-crt-string-l1-1-0.dll", + "$root_out_dir/cdb/api-ms-win-crt-time-l1-1-0.dll", + "$root_out_dir/cdb/api-ms-win-crt-utility-l1-1-0.dll", + "$root_out_dir/cdb/api-ms-win-eventing-provider-l1-1-0.dll", + "$root_out_dir/cdb/ucrtbase.dll", + ] + } args = [ rebase_path("$root_out_dir/cdb", root_out_dir), current_cpu,
diff --git a/cc/raster/raster_buffer_provider.cc b/cc/raster/raster_buffer_provider.cc index 9916886..0e7d1c71 100644 --- a/cc/raster/raster_buffer_provider.cc +++ b/cc/raster/raster_buffer_provider.cc
@@ -118,8 +118,12 @@ "RasterBufferProvider::PlaybackToMemory::ConvertRGBA4444"); SkImageInfo dst_info = info.makeColorType( ResourceFormatToClosestSkColorType(gpu_compositing, format)); - bool rv = surface->readPixels(dst_info, memory, stride, 0, 0); - DCHECK(rv); + auto dst_canvas = SkCanvas::MakeRasterDirect(dst_info, memory, stride); + DCHECK(dst_canvas); + SkPaint paint; + paint.setDither(true); + paint.setBlendMode(SkBlendMode::kSrc); + surface->draw(dst_canvas.get(), 0, 0, &paint); return; } case viz::ETC1:
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn index 07dfe7c..4a71c93 100644 --- a/chrome/android/BUILD.gn +++ b/chrome/android/BUILD.gn
@@ -9,6 +9,7 @@ import("//build/util/process_version.gni") import("//chrome/android/chrome_common_shared_library.gni") import("//chrome/android/chrome_public_apk_tmpl.gni") +import("//chrome/android/features/vr/public_vr_java_sources.gni") import("//chrome/android/feed/feed_java_sources.gni") import("//chrome/android/monochrome_android_manifest_jinja_variables.gni") import("//chrome/chrome_paks.gni") @@ -51,7 +52,7 @@ # Exclude it from JNI registration if VR is not enabled. chrome_jni_sources_blacklist = [] if (!enable_vr) { - chrome_jni_sources_blacklist += [ "//chrome/android/java/src/org/chromium/chrome/browser/vr/VrModuleProvider.java" ] + chrome_jni_sources_blacklist += [ "//chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrModuleProvider.java" ] } chrome_jni_registration_header = "$root_build_dir/gen/chrome/browser/android/chrome_jni_registration.h" @@ -124,12 +125,14 @@ } if (enable_vr) { + # TODO(crbug.com/935982): Currently, adding multiple resource folders to a + # resource target may clobber some resources. Once that is fixed we should add + # the VR resurces to chrome_app_java_resources. android_resources("chrome_vr_java_resources") { resource_dirs = [ "//chrome/android/java/res_vr" ] deps = [ ":chrome_app_java_resources", ] - custom_package = "org.chromium.chrome.vr.pub" } } @@ -412,6 +415,8 @@ java_files += feed_java_sources srcjar_deps += feed_srcjar_deps + java_files += public_vr_java_sources + if (enable_vr) { deps += [ ":chrome_vr_java_resources", @@ -818,7 +823,7 @@ "//base:base_java_test_support", "//chrome/android:app_hooks_java", "//chrome/android:chrome_java", - "//chrome/browser/android/vr:java", + "//chrome/android/features/vr:java", "//chrome/test/android:chrome_java_test_support", "//components/policy/android:policy_java", "//content/public/android:content_java", @@ -1759,7 +1764,7 @@ ] if (enable_vr) { # Contains VrFirstRunActivity, which is referenced by AndroidManifest.xml. - deps += [ "//chrome/browser/android/vr:java" ] + deps += [ "//chrome/android/features/vr:java" ] } additional_apks = [ "//net/android:net_test_support_apk" ] @@ -2055,10 +2060,10 @@ generate_jni("jni_headers") { sources = [ - "features/media_router/java/org/chromium/chrome/browser/media/router/ChromeMediaRouter.java", - "features/media_router/java/org/chromium/chrome/browser/media/router/ChromeMediaRouterDialogController.java", - "features/media_router/java/org/chromium/chrome/browser/media/router/FlingingControllerBridge.java", - "features/media_router/java/org/chromium/chrome/browser/media/router/MediaStatusBridge.java", + "features/media_router/java/src/org/chromium/chrome/browser/media/router/ChromeMediaRouter.java", + "features/media_router/java/src/org/chromium/chrome/browser/media/router/ChromeMediaRouterDialogController.java", + "features/media_router/java/src/org/chromium/chrome/browser/media/router/FlingingControllerBridge.java", + "features/media_router/java/src/org/chromium/chrome/browser/media/router/MediaStatusBridge.java", "java/src/org/chromium/chrome/browser/AfterStartupTaskUtils.java", "java/src/org/chromium/chrome/browser/AppHooks.java", "java/src/org/chromium/chrome/browser/ApplicationLifetime.java",
diff --git a/chrome/android/chrome_public_apk_tmpl.gni b/chrome/android/chrome_public_apk_tmpl.gni index 175b3b08..7d9af53 100644 --- a/chrome/android/chrome_public_apk_tmpl.gni +++ b/chrome/android/chrome_public_apk_tmpl.gni
@@ -238,7 +238,7 @@ deps += [ "//chrome/android:chrome_all_java" ] if (enable_vr && (_target_type == "android_apk" || !modularize_vr)) { - deps += [ "//chrome/browser/android/vr:java" ] + deps += [ "//chrome/android/features/vr:java" ] } if (!defined(version_code)) {
diff --git a/chrome/android/features/media_router/BUILD.gn b/chrome/android/features/media_router/BUILD.gn index d606c2f..66d317f 100644 --- a/chrome/android/features/media_router/BUILD.gn +++ b/chrome/android/features/media_router/BUILD.gn
@@ -8,7 +8,7 @@ android_library("java") { deps = [ - ":resources", + ":java_resources", "$google_play_services_package:google_play_services_base_java", "$google_play_services_package:google_play_services_basement_java", "$google_play_services_package:google_play_services_cast_framework_java", @@ -22,46 +22,46 @@ "//third_party/android_media:android_media_java", ] java_files = [ - "java/org/chromium/chrome/browser/media/router/BaseMediaRouteDialogManager.java", - "java/org/chromium/chrome/browser/media/router/CastRequestIdGenerator.java", - "java/org/chromium/chrome/browser/media/router/CastSessionUtil.java", - "java/org/chromium/chrome/browser/media/router/ChromeMediaRouter.java", - "java/org/chromium/chrome/browser/media/router/ChromeMediaRouterDialogController.java", - "java/org/chromium/chrome/browser/media/router/ClientRecord.java", - "java/org/chromium/chrome/browser/media/router/DiscoveryCallback.java", - "java/org/chromium/chrome/browser/media/router/DiscoveryDelegate.java", - "java/org/chromium/chrome/browser/media/router/FlingingController.java", - "java/org/chromium/chrome/browser/media/router/FlingingControllerBridge.java", - "java/org/chromium/chrome/browser/media/router/MediaController.java", - "java/org/chromium/chrome/browser/media/router/MediaRoute.java", - "java/org/chromium/chrome/browser/media/router/MediaRouteChooserDialogManager.java", - "java/org/chromium/chrome/browser/media/router/MediaRouteControllerDialogManager.java", - "java/org/chromium/chrome/browser/media/router/MediaRouteDialogDelegate.java", - "java/org/chromium/chrome/browser/media/router/MediaRouteDialogManager.java", - "java/org/chromium/chrome/browser/media/router/MediaRouteManager.java", - "java/org/chromium/chrome/browser/media/router/MediaRouteProvider.java", - "java/org/chromium/chrome/browser/media/router/MediaSink.java", - "java/org/chromium/chrome/browser/media/router/MediaSource.java", - "java/org/chromium/chrome/browser/media/router/MediaStatusBridge.java", - "java/org/chromium/chrome/browser/media/router/MediaStatusObserver.java", - "java/org/chromium/chrome/browser/media/router/caf/BaseNotificationController.java", - "java/org/chromium/chrome/browser/media/router/caf/BaseSessionController.java", - "java/org/chromium/chrome/browser/media/router/caf/CafBaseMediaRouteProvider.java", - "java/org/chromium/chrome/browser/media/router/caf/CafMediaRouteProvider.java", - "java/org/chromium/chrome/browser/media/router/caf/CafMessageHandler.java", - "java/org/chromium/chrome/browser/media/router/caf/CafNotificationController.java", - "java/org/chromium/chrome/browser/media/router/caf/CastMediaSource.java", - "java/org/chromium/chrome/browser/media/router/caf/CastOptionsProvider.java", - "java/org/chromium/chrome/browser/media/router/caf/CastSessionController.java", - "java/org/chromium/chrome/browser/media/router/caf/CastUtils.java", - "java/org/chromium/chrome/browser/media/router/caf/CreateRouteRequestInfo.java", - "java/org/chromium/chrome/browser/media/router/caf/remoting/CafExpandedControllerActivity.java", - "java/org/chromium/chrome/browser/media/router/caf/remoting/CafRemotingMediaRouteProvider.java", - "java/org/chromium/chrome/browser/media/router/caf/remoting/FlingingControllerAdapter.java", - "java/org/chromium/chrome/browser/media/router/caf/remoting/RemotingMediaSource.java", - "java/org/chromium/chrome/browser/media/router/caf/remoting/RemotingNotificationController.java", - "java/org/chromium/chrome/browser/media/router/caf/remoting/RemotingSessionController.java", - "java/org/chromium/chrome/browser/media/router/caf/remoting/StreamPositionExtrapolator.java", + "java/src/org/chromium/chrome/browser/media/router/BaseMediaRouteDialogManager.java", + "java/src/org/chromium/chrome/browser/media/router/CastRequestIdGenerator.java", + "java/src/org/chromium/chrome/browser/media/router/CastSessionUtil.java", + "java/src/org/chromium/chrome/browser/media/router/ChromeMediaRouter.java", + "java/src/org/chromium/chrome/browser/media/router/ChromeMediaRouterDialogController.java", + "java/src/org/chromium/chrome/browser/media/router/ClientRecord.java", + "java/src/org/chromium/chrome/browser/media/router/DiscoveryCallback.java", + "java/src/org/chromium/chrome/browser/media/router/DiscoveryDelegate.java", + "java/src/org/chromium/chrome/browser/media/router/FlingingController.java", + "java/src/org/chromium/chrome/browser/media/router/FlingingControllerBridge.java", + "java/src/org/chromium/chrome/browser/media/router/MediaController.java", + "java/src/org/chromium/chrome/browser/media/router/MediaRoute.java", + "java/src/org/chromium/chrome/browser/media/router/MediaRouteChooserDialogManager.java", + "java/src/org/chromium/chrome/browser/media/router/MediaRouteControllerDialogManager.java", + "java/src/org/chromium/chrome/browser/media/router/MediaRouteDialogDelegate.java", + "java/src/org/chromium/chrome/browser/media/router/MediaRouteDialogManager.java", + "java/src/org/chromium/chrome/browser/media/router/MediaRouteManager.java", + "java/src/org/chromium/chrome/browser/media/router/MediaRouteProvider.java", + "java/src/org/chromium/chrome/browser/media/router/MediaSink.java", + "java/src/org/chromium/chrome/browser/media/router/MediaSource.java", + "java/src/org/chromium/chrome/browser/media/router/MediaStatusBridge.java", + "java/src/org/chromium/chrome/browser/media/router/MediaStatusObserver.java", + "java/src/org/chromium/chrome/browser/media/router/caf/BaseNotificationController.java", + "java/src/org/chromium/chrome/browser/media/router/caf/BaseSessionController.java", + "java/src/org/chromium/chrome/browser/media/router/caf/CafBaseMediaRouteProvider.java", + "java/src/org/chromium/chrome/browser/media/router/caf/CafMediaRouteProvider.java", + "java/src/org/chromium/chrome/browser/media/router/caf/CafMessageHandler.java", + "java/src/org/chromium/chrome/browser/media/router/caf/CafNotificationController.java", + "java/src/org/chromium/chrome/browser/media/router/caf/CastMediaSource.java", + "java/src/org/chromium/chrome/browser/media/router/caf/CastOptionsProvider.java", + "java/src/org/chromium/chrome/browser/media/router/caf/CastSessionController.java", + "java/src/org/chromium/chrome/browser/media/router/caf/CastUtils.java", + "java/src/org/chromium/chrome/browser/media/router/caf/CreateRouteRequestInfo.java", + "java/src/org/chromium/chrome/browser/media/router/caf/remoting/CafExpandedControllerActivity.java", + "java/src/org/chromium/chrome/browser/media/router/caf/remoting/CafRemotingMediaRouteProvider.java", + "java/src/org/chromium/chrome/browser/media/router/caf/remoting/FlingingControllerAdapter.java", + "java/src/org/chromium/chrome/browser/media/router/caf/remoting/RemotingMediaSource.java", + "java/src/org/chromium/chrome/browser/media/router/caf/remoting/RemotingNotificationController.java", + "java/src/org/chromium/chrome/browser/media/router/caf/remoting/RemotingSessionController.java", + "java/src/org/chromium/chrome/browser/media/router/caf/remoting/StreamPositionExtrapolator.java", ] } @@ -69,8 +69,8 @@ testonly = true java_files = [ - "javatests/org/chromium/chrome/browser/media/router/MediaRouterIntegrationTest.java", - "javatests/org/chromium/chrome/browser/media/router/MockMediaRouteProvider.java", + "javatests/src/org/chromium/chrome/browser/media/router/MediaRouterIntegrationTest.java", + "javatests/src/org/chromium/chrome/browser/media/router/MockMediaRouteProvider.java", ] deps = [ @@ -90,21 +90,21 @@ junit_binary("media_router_junit_tests") { java_files = [ - "junit/org/chromium/chrome/browser/media/router/ChromeMediaRouterRouteTest.java", - "junit/org/chromium/chrome/browser/media/router/ChromeMediaRouterSinkObservationTest.java", - "junit/org/chromium/chrome/browser/media/router/ChromeMediaRouterTestBase.java", - "junit/org/chromium/chrome/browser/media/router/DiscoveryCallbackTest.java", - "junit/org/chromium/chrome/browser/media/router/JSONTestUtils.java", - "junit/org/chromium/chrome/browser/media/router/TestUtils.java", - "junit/org/chromium/chrome/browser/media/router/caf/BaseSessionControllerTest.java", - "junit/org/chromium/chrome/browser/media/router/caf/CafBaseMediaRouteProviderTest.java", - "junit/org/chromium/chrome/browser/media/router/caf/CafMediaRouteProviderTest.java", - "junit/org/chromium/chrome/browser/media/router/caf/CafMessageHandlerTest.java", - "junit/org/chromium/chrome/browser/media/router/caf/CastSessionControllerTest.java", - "junit/org/chromium/chrome/browser/media/router/caf/MediaRouterTestHelper.java", - "junit/org/chromium/chrome/browser/media/router/caf/ShadowCastContext.java", - "junit/org/chromium/chrome/browser/media/router/caf/ShadowCastMediaSource.java", - "junit/org/chromium/chrome/browser/media/router/caf/ShadowMediaRouter.java", + "junit/src/org/chromium/chrome/browser/media/router/ChromeMediaRouterRouteTest.java", + "junit/src/org/chromium/chrome/browser/media/router/ChromeMediaRouterSinkObservationTest.java", + "junit/src/org/chromium/chrome/browser/media/router/ChromeMediaRouterTestBase.java", + "junit/src/org/chromium/chrome/browser/media/router/DiscoveryCallbackTest.java", + "junit/src/org/chromium/chrome/browser/media/router/JSONTestUtils.java", + "junit/src/org/chromium/chrome/browser/media/router/TestUtils.java", + "junit/src/org/chromium/chrome/browser/media/router/caf/BaseSessionControllerTest.java", + "junit/src/org/chromium/chrome/browser/media/router/caf/CafBaseMediaRouteProviderTest.java", + "junit/src/org/chromium/chrome/browser/media/router/caf/CafMediaRouteProviderTest.java", + "junit/src/org/chromium/chrome/browser/media/router/caf/CafMessageHandlerTest.java", + "junit/src/org/chromium/chrome/browser/media/router/caf/CastSessionControllerTest.java", + "junit/src/org/chromium/chrome/browser/media/router/caf/MediaRouterTestHelper.java", + "junit/src/org/chromium/chrome/browser/media/router/caf/ShadowCastContext.java", + "junit/src/org/chromium/chrome/browser/media/router/caf/ShadowCastMediaSource.java", + "junit/src/org/chromium/chrome/browser/media/router/caf/ShadowMediaRouter.java", ] deps = [ @@ -115,20 +115,19 @@ ] } -# TODO(wnwen): Rename these to be more generic once https://crbug.com/935576 is fixed. -android_resources("resources") { - resource_dirs = [ "res" ] +android_resources("java_resources") { + resource_dirs = [ "java/res" ] deps = [ - ":strings_grd", + ":java_strings_grd", "//chrome/android:chrome_app_java_resources", "//third_party/android_media:android_media_resources", ] custom_package = "org.chromium.chrome.media.router" } -java_strings_grd("strings_grd") { +java_strings_grd("java_strings_grd") { defines = chrome_grit_defines - grd_file = "strings/android_chrome_media_router_strings.grd" + grd_file = "java/strings/android_chrome_media_router_strings.grd" outputs = [ "values-am/android_chrome_media_router_strings.xml", "values-ar/android_chrome_media_router_strings.xml",
diff --git a/chrome/android/features/media_router/res/drawable-hdpi/cast_playing_square.png b/chrome/android/features/media_router/java/res/drawable-hdpi/cast_playing_square.png similarity index 100% rename from chrome/android/features/media_router/res/drawable-hdpi/cast_playing_square.png rename to chrome/android/features/media_router/java/res/drawable-hdpi/cast_playing_square.png Binary files differ
diff --git a/chrome/android/features/media_router/res/drawable-hdpi/ic_cast_dark_off.png b/chrome/android/features/media_router/java/res/drawable-hdpi/ic_cast_dark_off.png similarity index 100% rename from chrome/android/features/media_router/res/drawable-hdpi/ic_cast_dark_off.png rename to chrome/android/features/media_router/java/res/drawable-hdpi/ic_cast_dark_off.png Binary files differ
diff --git a/chrome/android/features/media_router/res/drawable-hdpi/ic_cast_dark_on.png b/chrome/android/features/media_router/java/res/drawable-hdpi/ic_cast_dark_on.png similarity index 100% rename from chrome/android/features/media_router/res/drawable-hdpi/ic_cast_dark_on.png rename to chrome/android/features/media_router/java/res/drawable-hdpi/ic_cast_dark_on.png Binary files differ
diff --git a/chrome/android/features/media_router/res/drawable-hdpi/ic_notification_media_route.png b/chrome/android/features/media_router/java/res/drawable-hdpi/ic_notification_media_route.png similarity index 100% rename from chrome/android/features/media_router/res/drawable-hdpi/ic_notification_media_route.png rename to chrome/android/features/media_router/java/res/drawable-hdpi/ic_notification_media_route.png Binary files differ
diff --git a/chrome/android/features/media_router/res/drawable-mdpi/cast_playing_square.png b/chrome/android/features/media_router/java/res/drawable-mdpi/cast_playing_square.png similarity index 100% rename from chrome/android/features/media_router/res/drawable-mdpi/cast_playing_square.png rename to chrome/android/features/media_router/java/res/drawable-mdpi/cast_playing_square.png Binary files differ
diff --git a/chrome/android/features/media_router/res/drawable-mdpi/ic_cast_dark_off.png b/chrome/android/features/media_router/java/res/drawable-mdpi/ic_cast_dark_off.png similarity index 100% rename from chrome/android/features/media_router/res/drawable-mdpi/ic_cast_dark_off.png rename to chrome/android/features/media_router/java/res/drawable-mdpi/ic_cast_dark_off.png Binary files differ
diff --git a/chrome/android/features/media_router/res/drawable-mdpi/ic_cast_dark_on.png b/chrome/android/features/media_router/java/res/drawable-mdpi/ic_cast_dark_on.png similarity index 100% rename from chrome/android/features/media_router/res/drawable-mdpi/ic_cast_dark_on.png rename to chrome/android/features/media_router/java/res/drawable-mdpi/ic_cast_dark_on.png Binary files differ
diff --git a/chrome/android/features/media_router/res/drawable-mdpi/ic_notification_media_route.png b/chrome/android/features/media_router/java/res/drawable-mdpi/ic_notification_media_route.png similarity index 100% rename from chrome/android/features/media_router/res/drawable-mdpi/ic_notification_media_route.png rename to chrome/android/features/media_router/java/res/drawable-mdpi/ic_notification_media_route.png Binary files differ
diff --git a/chrome/android/features/media_router/res/drawable-xhdpi/cast_playing_square.png b/chrome/android/features/media_router/java/res/drawable-xhdpi/cast_playing_square.png similarity index 100% rename from chrome/android/features/media_router/res/drawable-xhdpi/cast_playing_square.png rename to chrome/android/features/media_router/java/res/drawable-xhdpi/cast_playing_square.png Binary files differ
diff --git a/chrome/android/features/media_router/res/drawable-xhdpi/ic_cast_dark_off.png b/chrome/android/features/media_router/java/res/drawable-xhdpi/ic_cast_dark_off.png similarity index 100% rename from chrome/android/features/media_router/res/drawable-xhdpi/ic_cast_dark_off.png rename to chrome/android/features/media_router/java/res/drawable-xhdpi/ic_cast_dark_off.png Binary files differ
diff --git a/chrome/android/features/media_router/res/drawable-xhdpi/ic_cast_dark_on.png b/chrome/android/features/media_router/java/res/drawable-xhdpi/ic_cast_dark_on.png similarity index 100% rename from chrome/android/features/media_router/res/drawable-xhdpi/ic_cast_dark_on.png rename to chrome/android/features/media_router/java/res/drawable-xhdpi/ic_cast_dark_on.png Binary files differ
diff --git a/chrome/android/features/media_router/res/drawable-xhdpi/ic_notification_media_route.png b/chrome/android/features/media_router/java/res/drawable-xhdpi/ic_notification_media_route.png similarity index 100% rename from chrome/android/features/media_router/res/drawable-xhdpi/ic_notification_media_route.png rename to chrome/android/features/media_router/java/res/drawable-xhdpi/ic_notification_media_route.png Binary files differ
diff --git a/chrome/android/features/media_router/res/drawable-xxhdpi/cast_playing_square.png b/chrome/android/features/media_router/java/res/drawable-xxhdpi/cast_playing_square.png similarity index 100% rename from chrome/android/features/media_router/res/drawable-xxhdpi/cast_playing_square.png rename to chrome/android/features/media_router/java/res/drawable-xxhdpi/cast_playing_square.png Binary files differ
diff --git a/chrome/android/features/media_router/res/drawable-xxhdpi/ic_cast_dark_off.png b/chrome/android/features/media_router/java/res/drawable-xxhdpi/ic_cast_dark_off.png similarity index 100% rename from chrome/android/features/media_router/res/drawable-xxhdpi/ic_cast_dark_off.png rename to chrome/android/features/media_router/java/res/drawable-xxhdpi/ic_cast_dark_off.png Binary files differ
diff --git a/chrome/android/features/media_router/res/drawable-xxhdpi/ic_cast_dark_on.png b/chrome/android/features/media_router/java/res/drawable-xxhdpi/ic_cast_dark_on.png similarity index 100% rename from chrome/android/features/media_router/res/drawable-xxhdpi/ic_cast_dark_on.png rename to chrome/android/features/media_router/java/res/drawable-xxhdpi/ic_cast_dark_on.png Binary files differ
diff --git a/chrome/android/features/media_router/res/drawable-xxhdpi/ic_notification_media_route.png b/chrome/android/features/media_router/java/res/drawable-xxhdpi/ic_notification_media_route.png similarity index 100% rename from chrome/android/features/media_router/res/drawable-xxhdpi/ic_notification_media_route.png rename to chrome/android/features/media_router/java/res/drawable-xxhdpi/ic_notification_media_route.png Binary files differ
diff --git a/chrome/android/features/media_router/res/drawable-xxxhdpi/cast_playing_square.png b/chrome/android/features/media_router/java/res/drawable-xxxhdpi/cast_playing_square.png similarity index 100% rename from chrome/android/features/media_router/res/drawable-xxxhdpi/cast_playing_square.png rename to chrome/android/features/media_router/java/res/drawable-xxxhdpi/cast_playing_square.png Binary files differ
diff --git a/chrome/android/features/media_router/res/drawable-xxxhdpi/ic_notification_media_route.png b/chrome/android/features/media_router/java/res/drawable-xxxhdpi/ic_notification_media_route.png similarity index 100% rename from chrome/android/features/media_router/res/drawable-xxxhdpi/ic_notification_media_route.png rename to chrome/android/features/media_router/java/res/drawable-xxxhdpi/ic_notification_media_route.png Binary files differ
diff --git a/chrome/android/features/media_router/res/drawable/ic_cast_dark_chrome.xml b/chrome/android/features/media_router/java/res/drawable/ic_cast_dark_chrome.xml similarity index 100% rename from chrome/android/features/media_router/res/drawable/ic_cast_dark_chrome.xml rename to chrome/android/features/media_router/java/res/drawable/ic_cast_dark_chrome.xml
diff --git a/chrome/android/features/media_router/res/layout/caf_controller_media_route_button.xml b/chrome/android/features/media_router/java/res/layout/caf_controller_media_route_button.xml similarity index 100% rename from chrome/android/features/media_router/res/layout/caf_controller_media_route_button.xml rename to chrome/android/features/media_router/java/res/layout/caf_controller_media_route_button.xml
diff --git a/chrome/android/features/media_router/res/layout/expanded_cast_controller.xml b/chrome/android/features/media_router/java/res/layout/expanded_cast_controller.xml similarity index 100% rename from chrome/android/features/media_router/res/layout/expanded_cast_controller.xml rename to chrome/android/features/media_router/java/res/layout/expanded_cast_controller.xml
diff --git a/chrome/android/features/media_router/res/values-v17/styles.xml b/chrome/android/features/media_router/java/res/values-v17/styles.xml similarity index 100% rename from chrome/android/features/media_router/res/values-v17/styles.xml rename to chrome/android/features/media_router/java/res/values-v17/styles.xml
diff --git a/chrome/android/features/media_router/java/org/chromium/chrome/browser/media/router/BaseMediaRouteDialogManager.java b/chrome/android/features/media_router/java/src/org/chromium/chrome/browser/media/router/BaseMediaRouteDialogManager.java similarity index 100% rename from chrome/android/features/media_router/java/org/chromium/chrome/browser/media/router/BaseMediaRouteDialogManager.java rename to chrome/android/features/media_router/java/src/org/chromium/chrome/browser/media/router/BaseMediaRouteDialogManager.java
diff --git a/chrome/android/features/media_router/java/org/chromium/chrome/browser/media/router/CastRequestIdGenerator.java b/chrome/android/features/media_router/java/src/org/chromium/chrome/browser/media/router/CastRequestIdGenerator.java similarity index 100% rename from chrome/android/features/media_router/java/org/chromium/chrome/browser/media/router/CastRequestIdGenerator.java rename to chrome/android/features/media_router/java/src/org/chromium/chrome/browser/media/router/CastRequestIdGenerator.java
diff --git a/chrome/android/features/media_router/java/org/chromium/chrome/browser/media/router/CastSessionUtil.java b/chrome/android/features/media_router/java/src/org/chromium/chrome/browser/media/router/CastSessionUtil.java similarity index 100% rename from chrome/android/features/media_router/java/org/chromium/chrome/browser/media/router/CastSessionUtil.java rename to chrome/android/features/media_router/java/src/org/chromium/chrome/browser/media/router/CastSessionUtil.java
diff --git a/chrome/android/features/media_router/java/org/chromium/chrome/browser/media/router/ChromeMediaRouter.java b/chrome/android/features/media_router/java/src/org/chromium/chrome/browser/media/router/ChromeMediaRouter.java similarity index 100% rename from chrome/android/features/media_router/java/org/chromium/chrome/browser/media/router/ChromeMediaRouter.java rename to chrome/android/features/media_router/java/src/org/chromium/chrome/browser/media/router/ChromeMediaRouter.java
diff --git a/chrome/android/features/media_router/java/org/chromium/chrome/browser/media/router/ChromeMediaRouterDialogController.java b/chrome/android/features/media_router/java/src/org/chromium/chrome/browser/media/router/ChromeMediaRouterDialogController.java similarity index 100% rename from chrome/android/features/media_router/java/org/chromium/chrome/browser/media/router/ChromeMediaRouterDialogController.java rename to chrome/android/features/media_router/java/src/org/chromium/chrome/browser/media/router/ChromeMediaRouterDialogController.java
diff --git a/chrome/android/features/media_router/java/org/chromium/chrome/browser/media/router/ClientRecord.java b/chrome/android/features/media_router/java/src/org/chromium/chrome/browser/media/router/ClientRecord.java similarity index 100% rename from chrome/android/features/media_router/java/org/chromium/chrome/browser/media/router/ClientRecord.java rename to chrome/android/features/media_router/java/src/org/chromium/chrome/browser/media/router/ClientRecord.java
diff --git a/chrome/android/features/media_router/java/org/chromium/chrome/browser/media/router/DiscoveryCallback.java b/chrome/android/features/media_router/java/src/org/chromium/chrome/browser/media/router/DiscoveryCallback.java similarity index 100% rename from chrome/android/features/media_router/java/org/chromium/chrome/browser/media/router/DiscoveryCallback.java rename to chrome/android/features/media_router/java/src/org/chromium/chrome/browser/media/router/DiscoveryCallback.java
diff --git a/chrome/android/features/media_router/java/org/chromium/chrome/browser/media/router/DiscoveryDelegate.java b/chrome/android/features/media_router/java/src/org/chromium/chrome/browser/media/router/DiscoveryDelegate.java similarity index 100% rename from chrome/android/features/media_router/java/org/chromium/chrome/browser/media/router/DiscoveryDelegate.java rename to chrome/android/features/media_router/java/src/org/chromium/chrome/browser/media/router/DiscoveryDelegate.java
diff --git a/chrome/android/features/media_router/java/org/chromium/chrome/browser/media/router/FlingingController.java b/chrome/android/features/media_router/java/src/org/chromium/chrome/browser/media/router/FlingingController.java similarity index 100% rename from chrome/android/features/media_router/java/org/chromium/chrome/browser/media/router/FlingingController.java rename to chrome/android/features/media_router/java/src/org/chromium/chrome/browser/media/router/FlingingController.java
diff --git a/chrome/android/features/media_router/java/org/chromium/chrome/browser/media/router/FlingingControllerBridge.java b/chrome/android/features/media_router/java/src/org/chromium/chrome/browser/media/router/FlingingControllerBridge.java similarity index 100% rename from chrome/android/features/media_router/java/org/chromium/chrome/browser/media/router/FlingingControllerBridge.java rename to chrome/android/features/media_router/java/src/org/chromium/chrome/browser/media/router/FlingingControllerBridge.java
diff --git a/chrome/android/features/media_router/java/org/chromium/chrome/browser/media/router/MediaController.java b/chrome/android/features/media_router/java/src/org/chromium/chrome/browser/media/router/MediaController.java similarity index 100% rename from chrome/android/features/media_router/java/org/chromium/chrome/browser/media/router/MediaController.java rename to chrome/android/features/media_router/java/src/org/chromium/chrome/browser/media/router/MediaController.java
diff --git a/chrome/android/features/media_router/java/org/chromium/chrome/browser/media/router/MediaRoute.java b/chrome/android/features/media_router/java/src/org/chromium/chrome/browser/media/router/MediaRoute.java similarity index 100% rename from chrome/android/features/media_router/java/org/chromium/chrome/browser/media/router/MediaRoute.java rename to chrome/android/features/media_router/java/src/org/chromium/chrome/browser/media/router/MediaRoute.java
diff --git a/chrome/android/features/media_router/java/org/chromium/chrome/browser/media/router/MediaRouteChooserDialogManager.java b/chrome/android/features/media_router/java/src/org/chromium/chrome/browser/media/router/MediaRouteChooserDialogManager.java similarity index 100% rename from chrome/android/features/media_router/java/org/chromium/chrome/browser/media/router/MediaRouteChooserDialogManager.java rename to chrome/android/features/media_router/java/src/org/chromium/chrome/browser/media/router/MediaRouteChooserDialogManager.java
diff --git a/chrome/android/features/media_router/java/org/chromium/chrome/browser/media/router/MediaRouteControllerDialogManager.java b/chrome/android/features/media_router/java/src/org/chromium/chrome/browser/media/router/MediaRouteControllerDialogManager.java similarity index 100% rename from chrome/android/features/media_router/java/org/chromium/chrome/browser/media/router/MediaRouteControllerDialogManager.java rename to chrome/android/features/media_router/java/src/org/chromium/chrome/browser/media/router/MediaRouteControllerDialogManager.java
diff --git a/chrome/android/features/media_router/java/org/chromium/chrome/browser/media/router/MediaRouteDialogDelegate.java b/chrome/android/features/media_router/java/src/org/chromium/chrome/browser/media/router/MediaRouteDialogDelegate.java similarity index 100% rename from chrome/android/features/media_router/java/org/chromium/chrome/browser/media/router/MediaRouteDialogDelegate.java rename to chrome/android/features/media_router/java/src/org/chromium/chrome/browser/media/router/MediaRouteDialogDelegate.java
diff --git a/chrome/android/features/media_router/java/org/chromium/chrome/browser/media/router/MediaRouteDialogManager.java b/chrome/android/features/media_router/java/src/org/chromium/chrome/browser/media/router/MediaRouteDialogManager.java similarity index 100% rename from chrome/android/features/media_router/java/org/chromium/chrome/browser/media/router/MediaRouteDialogManager.java rename to chrome/android/features/media_router/java/src/org/chromium/chrome/browser/media/router/MediaRouteDialogManager.java
diff --git a/chrome/android/features/media_router/java/org/chromium/chrome/browser/media/router/MediaRouteManager.java b/chrome/android/features/media_router/java/src/org/chromium/chrome/browser/media/router/MediaRouteManager.java similarity index 100% rename from chrome/android/features/media_router/java/org/chromium/chrome/browser/media/router/MediaRouteManager.java rename to chrome/android/features/media_router/java/src/org/chromium/chrome/browser/media/router/MediaRouteManager.java
diff --git a/chrome/android/features/media_router/java/org/chromium/chrome/browser/media/router/MediaRouteProvider.java b/chrome/android/features/media_router/java/src/org/chromium/chrome/browser/media/router/MediaRouteProvider.java similarity index 100% rename from chrome/android/features/media_router/java/org/chromium/chrome/browser/media/router/MediaRouteProvider.java rename to chrome/android/features/media_router/java/src/org/chromium/chrome/browser/media/router/MediaRouteProvider.java
diff --git a/chrome/android/features/media_router/java/org/chromium/chrome/browser/media/router/MediaSink.java b/chrome/android/features/media_router/java/src/org/chromium/chrome/browser/media/router/MediaSink.java similarity index 100% rename from chrome/android/features/media_router/java/org/chromium/chrome/browser/media/router/MediaSink.java rename to chrome/android/features/media_router/java/src/org/chromium/chrome/browser/media/router/MediaSink.java
diff --git a/chrome/android/features/media_router/java/org/chromium/chrome/browser/media/router/MediaSource.java b/chrome/android/features/media_router/java/src/org/chromium/chrome/browser/media/router/MediaSource.java similarity index 100% rename from chrome/android/features/media_router/java/org/chromium/chrome/browser/media/router/MediaSource.java rename to chrome/android/features/media_router/java/src/org/chromium/chrome/browser/media/router/MediaSource.java
diff --git a/chrome/android/features/media_router/java/org/chromium/chrome/browser/media/router/MediaStatusBridge.java b/chrome/android/features/media_router/java/src/org/chromium/chrome/browser/media/router/MediaStatusBridge.java similarity index 100% rename from chrome/android/features/media_router/java/org/chromium/chrome/browser/media/router/MediaStatusBridge.java rename to chrome/android/features/media_router/java/src/org/chromium/chrome/browser/media/router/MediaStatusBridge.java
diff --git a/chrome/android/features/media_router/java/org/chromium/chrome/browser/media/router/MediaStatusObserver.java b/chrome/android/features/media_router/java/src/org/chromium/chrome/browser/media/router/MediaStatusObserver.java similarity index 100% rename from chrome/android/features/media_router/java/org/chromium/chrome/browser/media/router/MediaStatusObserver.java rename to chrome/android/features/media_router/java/src/org/chromium/chrome/browser/media/router/MediaStatusObserver.java
diff --git a/chrome/android/features/media_router/java/org/chromium/chrome/browser/media/router/caf/BaseNotificationController.java b/chrome/android/features/media_router/java/src/org/chromium/chrome/browser/media/router/caf/BaseNotificationController.java similarity index 100% rename from chrome/android/features/media_router/java/org/chromium/chrome/browser/media/router/caf/BaseNotificationController.java rename to chrome/android/features/media_router/java/src/org/chromium/chrome/browser/media/router/caf/BaseNotificationController.java
diff --git a/chrome/android/features/media_router/java/org/chromium/chrome/browser/media/router/caf/BaseSessionController.java b/chrome/android/features/media_router/java/src/org/chromium/chrome/browser/media/router/caf/BaseSessionController.java similarity index 100% rename from chrome/android/features/media_router/java/org/chromium/chrome/browser/media/router/caf/BaseSessionController.java rename to chrome/android/features/media_router/java/src/org/chromium/chrome/browser/media/router/caf/BaseSessionController.java
diff --git a/chrome/android/features/media_router/java/org/chromium/chrome/browser/media/router/caf/CafBaseMediaRouteProvider.java b/chrome/android/features/media_router/java/src/org/chromium/chrome/browser/media/router/caf/CafBaseMediaRouteProvider.java similarity index 100% rename from chrome/android/features/media_router/java/org/chromium/chrome/browser/media/router/caf/CafBaseMediaRouteProvider.java rename to chrome/android/features/media_router/java/src/org/chromium/chrome/browser/media/router/caf/CafBaseMediaRouteProvider.java
diff --git a/chrome/android/features/media_router/java/org/chromium/chrome/browser/media/router/caf/CafMediaRouteProvider.java b/chrome/android/features/media_router/java/src/org/chromium/chrome/browser/media/router/caf/CafMediaRouteProvider.java similarity index 100% rename from chrome/android/features/media_router/java/org/chromium/chrome/browser/media/router/caf/CafMediaRouteProvider.java rename to chrome/android/features/media_router/java/src/org/chromium/chrome/browser/media/router/caf/CafMediaRouteProvider.java
diff --git a/chrome/android/features/media_router/java/org/chromium/chrome/browser/media/router/caf/CafMessageHandler.java b/chrome/android/features/media_router/java/src/org/chromium/chrome/browser/media/router/caf/CafMessageHandler.java similarity index 100% rename from chrome/android/features/media_router/java/org/chromium/chrome/browser/media/router/caf/CafMessageHandler.java rename to chrome/android/features/media_router/java/src/org/chromium/chrome/browser/media/router/caf/CafMessageHandler.java
diff --git a/chrome/android/features/media_router/java/org/chromium/chrome/browser/media/router/caf/CafNotificationController.java b/chrome/android/features/media_router/java/src/org/chromium/chrome/browser/media/router/caf/CafNotificationController.java similarity index 100% rename from chrome/android/features/media_router/java/org/chromium/chrome/browser/media/router/caf/CafNotificationController.java rename to chrome/android/features/media_router/java/src/org/chromium/chrome/browser/media/router/caf/CafNotificationController.java
diff --git a/chrome/android/features/media_router/java/org/chromium/chrome/browser/media/router/caf/CastMediaSource.java b/chrome/android/features/media_router/java/src/org/chromium/chrome/browser/media/router/caf/CastMediaSource.java similarity index 100% rename from chrome/android/features/media_router/java/org/chromium/chrome/browser/media/router/caf/CastMediaSource.java rename to chrome/android/features/media_router/java/src/org/chromium/chrome/browser/media/router/caf/CastMediaSource.java
diff --git a/chrome/android/features/media_router/java/org/chromium/chrome/browser/media/router/caf/CastOptionsProvider.java b/chrome/android/features/media_router/java/src/org/chromium/chrome/browser/media/router/caf/CastOptionsProvider.java similarity index 100% rename from chrome/android/features/media_router/java/org/chromium/chrome/browser/media/router/caf/CastOptionsProvider.java rename to chrome/android/features/media_router/java/src/org/chromium/chrome/browser/media/router/caf/CastOptionsProvider.java
diff --git a/chrome/android/features/media_router/java/org/chromium/chrome/browser/media/router/caf/CastSessionController.java b/chrome/android/features/media_router/java/src/org/chromium/chrome/browser/media/router/caf/CastSessionController.java similarity index 100% rename from chrome/android/features/media_router/java/org/chromium/chrome/browser/media/router/caf/CastSessionController.java rename to chrome/android/features/media_router/java/src/org/chromium/chrome/browser/media/router/caf/CastSessionController.java
diff --git a/chrome/android/features/media_router/java/org/chromium/chrome/browser/media/router/caf/CastUtils.java b/chrome/android/features/media_router/java/src/org/chromium/chrome/browser/media/router/caf/CastUtils.java similarity index 100% rename from chrome/android/features/media_router/java/org/chromium/chrome/browser/media/router/caf/CastUtils.java rename to chrome/android/features/media_router/java/src/org/chromium/chrome/browser/media/router/caf/CastUtils.java
diff --git a/chrome/android/features/media_router/java/org/chromium/chrome/browser/media/router/caf/CreateRouteRequestInfo.java b/chrome/android/features/media_router/java/src/org/chromium/chrome/browser/media/router/caf/CreateRouteRequestInfo.java similarity index 100% rename from chrome/android/features/media_router/java/org/chromium/chrome/browser/media/router/caf/CreateRouteRequestInfo.java rename to chrome/android/features/media_router/java/src/org/chromium/chrome/browser/media/router/caf/CreateRouteRequestInfo.java
diff --git a/chrome/android/features/media_router/java/org/chromium/chrome/browser/media/router/caf/remoting/CafExpandedControllerActivity.java b/chrome/android/features/media_router/java/src/org/chromium/chrome/browser/media/router/caf/remoting/CafExpandedControllerActivity.java similarity index 100% rename from chrome/android/features/media_router/java/org/chromium/chrome/browser/media/router/caf/remoting/CafExpandedControllerActivity.java rename to chrome/android/features/media_router/java/src/org/chromium/chrome/browser/media/router/caf/remoting/CafExpandedControllerActivity.java
diff --git a/chrome/android/features/media_router/java/org/chromium/chrome/browser/media/router/caf/remoting/CafRemotingMediaRouteProvider.java b/chrome/android/features/media_router/java/src/org/chromium/chrome/browser/media/router/caf/remoting/CafRemotingMediaRouteProvider.java similarity index 100% rename from chrome/android/features/media_router/java/org/chromium/chrome/browser/media/router/caf/remoting/CafRemotingMediaRouteProvider.java rename to chrome/android/features/media_router/java/src/org/chromium/chrome/browser/media/router/caf/remoting/CafRemotingMediaRouteProvider.java
diff --git a/chrome/android/features/media_router/java/org/chromium/chrome/browser/media/router/caf/remoting/FlingingControllerAdapter.java b/chrome/android/features/media_router/java/src/org/chromium/chrome/browser/media/router/caf/remoting/FlingingControllerAdapter.java similarity index 100% rename from chrome/android/features/media_router/java/org/chromium/chrome/browser/media/router/caf/remoting/FlingingControllerAdapter.java rename to chrome/android/features/media_router/java/src/org/chromium/chrome/browser/media/router/caf/remoting/FlingingControllerAdapter.java
diff --git a/chrome/android/features/media_router/java/org/chromium/chrome/browser/media/router/caf/remoting/RemotingMediaSource.java b/chrome/android/features/media_router/java/src/org/chromium/chrome/browser/media/router/caf/remoting/RemotingMediaSource.java similarity index 100% rename from chrome/android/features/media_router/java/org/chromium/chrome/browser/media/router/caf/remoting/RemotingMediaSource.java rename to chrome/android/features/media_router/java/src/org/chromium/chrome/browser/media/router/caf/remoting/RemotingMediaSource.java
diff --git a/chrome/android/features/media_router/java/org/chromium/chrome/browser/media/router/caf/remoting/RemotingNotificationController.java b/chrome/android/features/media_router/java/src/org/chromium/chrome/browser/media/router/caf/remoting/RemotingNotificationController.java similarity index 100% rename from chrome/android/features/media_router/java/org/chromium/chrome/browser/media/router/caf/remoting/RemotingNotificationController.java rename to chrome/android/features/media_router/java/src/org/chromium/chrome/browser/media/router/caf/remoting/RemotingNotificationController.java
diff --git a/chrome/android/features/media_router/java/org/chromium/chrome/browser/media/router/caf/remoting/RemotingSessionController.java b/chrome/android/features/media_router/java/src/org/chromium/chrome/browser/media/router/caf/remoting/RemotingSessionController.java similarity index 100% rename from chrome/android/features/media_router/java/org/chromium/chrome/browser/media/router/caf/remoting/RemotingSessionController.java rename to chrome/android/features/media_router/java/src/org/chromium/chrome/browser/media/router/caf/remoting/RemotingSessionController.java
diff --git a/chrome/android/features/media_router/java/org/chromium/chrome/browser/media/router/caf/remoting/StreamPositionExtrapolator.java b/chrome/android/features/media_router/java/src/org/chromium/chrome/browser/media/router/caf/remoting/StreamPositionExtrapolator.java similarity index 100% rename from chrome/android/features/media_router/java/org/chromium/chrome/browser/media/router/caf/remoting/StreamPositionExtrapolator.java rename to chrome/android/features/media_router/java/src/org/chromium/chrome/browser/media/router/caf/remoting/StreamPositionExtrapolator.java
diff --git a/chrome/android/features/media_router/strings/android_chrome_media_router_strings.grd b/chrome/android/features/media_router/java/strings/android_chrome_media_router_strings.grd similarity index 100% rename from chrome/android/features/media_router/strings/android_chrome_media_router_strings.grd rename to chrome/android/features/media_router/java/strings/android_chrome_media_router_strings.grd
diff --git a/chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_am.xtb b/chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_am.xtb similarity index 100% rename from chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_am.xtb rename to chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_am.xtb
diff --git a/chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_ar.xtb b/chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_ar.xtb similarity index 100% rename from chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_ar.xtb rename to chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_ar.xtb
diff --git a/chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_bg.xtb b/chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_bg.xtb similarity index 100% rename from chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_bg.xtb rename to chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_bg.xtb
diff --git a/chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_bn.xtb b/chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_bn.xtb similarity index 100% rename from chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_bn.xtb rename to chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_bn.xtb
diff --git a/chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_ca.xtb b/chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_ca.xtb similarity index 100% rename from chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_ca.xtb rename to chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_ca.xtb
diff --git a/chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_cs.xtb b/chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_cs.xtb similarity index 100% rename from chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_cs.xtb rename to chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_cs.xtb
diff --git a/chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_da.xtb b/chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_da.xtb similarity index 100% rename from chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_da.xtb rename to chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_da.xtb
diff --git a/chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_de.xtb b/chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_de.xtb similarity index 100% rename from chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_de.xtb rename to chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_de.xtb
diff --git a/chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_el.xtb b/chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_el.xtb similarity index 100% rename from chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_el.xtb rename to chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_el.xtb
diff --git a/chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_en-GB.xtb b/chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_en-GB.xtb similarity index 100% rename from chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_en-GB.xtb rename to chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_en-GB.xtb
diff --git a/chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_es-419.xtb b/chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_es-419.xtb similarity index 100% rename from chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_es-419.xtb rename to chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_es-419.xtb
diff --git a/chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_es.xtb b/chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_es.xtb similarity index 100% rename from chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_es.xtb rename to chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_es.xtb
diff --git a/chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_et.xtb b/chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_et.xtb similarity index 100% rename from chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_et.xtb rename to chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_et.xtb
diff --git a/chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_fa.xtb b/chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_fa.xtb similarity index 100% rename from chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_fa.xtb rename to chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_fa.xtb
diff --git a/chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_fi.xtb b/chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_fi.xtb similarity index 100% rename from chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_fi.xtb rename to chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_fi.xtb
diff --git a/chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_fil.xtb b/chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_fil.xtb similarity index 100% rename from chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_fil.xtb rename to chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_fil.xtb
diff --git a/chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_fr.xtb b/chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_fr.xtb similarity index 100% rename from chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_fr.xtb rename to chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_fr.xtb
diff --git a/chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_gu.xtb b/chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_gu.xtb similarity index 100% rename from chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_gu.xtb rename to chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_gu.xtb
diff --git a/chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_hi.xtb b/chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_hi.xtb similarity index 100% rename from chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_hi.xtb rename to chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_hi.xtb
diff --git a/chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_hr.xtb b/chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_hr.xtb similarity index 100% rename from chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_hr.xtb rename to chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_hr.xtb
diff --git a/chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_hu.xtb b/chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_hu.xtb similarity index 100% rename from chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_hu.xtb rename to chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_hu.xtb
diff --git a/chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_id.xtb b/chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_id.xtb similarity index 100% rename from chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_id.xtb rename to chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_id.xtb
diff --git a/chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_it.xtb b/chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_it.xtb similarity index 100% rename from chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_it.xtb rename to chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_it.xtb
diff --git a/chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_iw.xtb b/chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_iw.xtb similarity index 100% rename from chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_iw.xtb rename to chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_iw.xtb
diff --git a/chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_ja.xtb b/chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_ja.xtb similarity index 100% rename from chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_ja.xtb rename to chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_ja.xtb
diff --git a/chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_kn.xtb b/chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_kn.xtb similarity index 100% rename from chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_kn.xtb rename to chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_kn.xtb
diff --git a/chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_ko.xtb b/chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_ko.xtb similarity index 100% rename from chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_ko.xtb rename to chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_ko.xtb
diff --git a/chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_lt.xtb b/chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_lt.xtb similarity index 100% rename from chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_lt.xtb rename to chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_lt.xtb
diff --git a/chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_lv.xtb b/chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_lv.xtb similarity index 100% rename from chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_lv.xtb rename to chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_lv.xtb
diff --git a/chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_ml.xtb b/chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_ml.xtb similarity index 100% rename from chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_ml.xtb rename to chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_ml.xtb
diff --git a/chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_mr.xtb b/chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_mr.xtb similarity index 100% rename from chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_mr.xtb rename to chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_mr.xtb
diff --git a/chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_ms.xtb b/chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_ms.xtb similarity index 100% rename from chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_ms.xtb rename to chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_ms.xtb
diff --git a/chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_nl.xtb b/chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_nl.xtb similarity index 100% rename from chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_nl.xtb rename to chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_nl.xtb
diff --git a/chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_no.xtb b/chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_no.xtb similarity index 100% rename from chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_no.xtb rename to chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_no.xtb
diff --git a/chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_pl.xtb b/chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_pl.xtb similarity index 100% rename from chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_pl.xtb rename to chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_pl.xtb
diff --git a/chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_pt-BR.xtb b/chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_pt-BR.xtb similarity index 100% rename from chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_pt-BR.xtb rename to chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_pt-BR.xtb
diff --git a/chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_pt-PT.xtb b/chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_pt-PT.xtb similarity index 100% rename from chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_pt-PT.xtb rename to chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_pt-PT.xtb
diff --git a/chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_ro.xtb b/chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_ro.xtb similarity index 100% rename from chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_ro.xtb rename to chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_ro.xtb
diff --git a/chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_ru.xtb b/chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_ru.xtb similarity index 100% rename from chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_ru.xtb rename to chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_ru.xtb
diff --git a/chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_sk.xtb b/chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_sk.xtb similarity index 100% rename from chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_sk.xtb rename to chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_sk.xtb
diff --git a/chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_sl.xtb b/chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_sl.xtb similarity index 100% rename from chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_sl.xtb rename to chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_sl.xtb
diff --git a/chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_sr.xtb b/chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_sr.xtb similarity index 100% rename from chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_sr.xtb rename to chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_sr.xtb
diff --git a/chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_sv.xtb b/chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_sv.xtb similarity index 100% rename from chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_sv.xtb rename to chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_sv.xtb
diff --git a/chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_sw.xtb b/chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_sw.xtb similarity index 100% rename from chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_sw.xtb rename to chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_sw.xtb
diff --git a/chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_ta.xtb b/chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_ta.xtb similarity index 100% rename from chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_ta.xtb rename to chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_ta.xtb
diff --git a/chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_te.xtb b/chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_te.xtb similarity index 100% rename from chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_te.xtb rename to chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_te.xtb
diff --git a/chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_th.xtb b/chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_th.xtb similarity index 100% rename from chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_th.xtb rename to chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_th.xtb
diff --git a/chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_tr.xtb b/chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_tr.xtb similarity index 100% rename from chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_tr.xtb rename to chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_tr.xtb
diff --git a/chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_uk.xtb b/chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_uk.xtb similarity index 100% rename from chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_uk.xtb rename to chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_uk.xtb
diff --git a/chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_vi.xtb b/chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_vi.xtb similarity index 100% rename from chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_vi.xtb rename to chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_vi.xtb
diff --git a/chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_zh-CN.xtb b/chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_zh-CN.xtb similarity index 100% rename from chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_zh-CN.xtb rename to chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_zh-CN.xtb
diff --git a/chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_zh-TW.xtb b/chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_zh-TW.xtb similarity index 100% rename from chrome/android/features/media_router/strings/translations/android_chrome_media_router_strings_zh-TW.xtb rename to chrome/android/features/media_router/java/strings/translations/android_chrome_media_router_strings_zh-TW.xtb
diff --git a/chrome/android/features/media_router/javatests/org/chromium/chrome/browser/media/router/MediaRouterIntegrationTest.java b/chrome/android/features/media_router/javatests/src/org/chromium/chrome/browser/media/router/MediaRouterIntegrationTest.java similarity index 100% rename from chrome/android/features/media_router/javatests/org/chromium/chrome/browser/media/router/MediaRouterIntegrationTest.java rename to chrome/android/features/media_router/javatests/src/org/chromium/chrome/browser/media/router/MediaRouterIntegrationTest.java
diff --git a/chrome/android/features/media_router/javatests/org/chromium/chrome/browser/media/router/MockMediaRouteProvider.java b/chrome/android/features/media_router/javatests/src/org/chromium/chrome/browser/media/router/MockMediaRouteProvider.java similarity index 100% rename from chrome/android/features/media_router/javatests/org/chromium/chrome/browser/media/router/MockMediaRouteProvider.java rename to chrome/android/features/media_router/javatests/src/org/chromium/chrome/browser/media/router/MockMediaRouteProvider.java
diff --git a/chrome/android/features/media_router/junit/org/chromium/chrome/browser/media/router/ChromeMediaRouterRouteTest.java b/chrome/android/features/media_router/junit/src/org/chromium/chrome/browser/media/router/ChromeMediaRouterRouteTest.java similarity index 100% rename from chrome/android/features/media_router/junit/org/chromium/chrome/browser/media/router/ChromeMediaRouterRouteTest.java rename to chrome/android/features/media_router/junit/src/org/chromium/chrome/browser/media/router/ChromeMediaRouterRouteTest.java
diff --git a/chrome/android/features/media_router/junit/org/chromium/chrome/browser/media/router/ChromeMediaRouterSinkObservationTest.java b/chrome/android/features/media_router/junit/src/org/chromium/chrome/browser/media/router/ChromeMediaRouterSinkObservationTest.java similarity index 100% rename from chrome/android/features/media_router/junit/org/chromium/chrome/browser/media/router/ChromeMediaRouterSinkObservationTest.java rename to chrome/android/features/media_router/junit/src/org/chromium/chrome/browser/media/router/ChromeMediaRouterSinkObservationTest.java
diff --git a/chrome/android/features/media_router/junit/org/chromium/chrome/browser/media/router/ChromeMediaRouterTestBase.java b/chrome/android/features/media_router/junit/src/org/chromium/chrome/browser/media/router/ChromeMediaRouterTestBase.java similarity index 100% rename from chrome/android/features/media_router/junit/org/chromium/chrome/browser/media/router/ChromeMediaRouterTestBase.java rename to chrome/android/features/media_router/junit/src/org/chromium/chrome/browser/media/router/ChromeMediaRouterTestBase.java
diff --git a/chrome/android/features/media_router/junit/org/chromium/chrome/browser/media/router/DiscoveryCallbackTest.java b/chrome/android/features/media_router/junit/src/org/chromium/chrome/browser/media/router/DiscoveryCallbackTest.java similarity index 100% rename from chrome/android/features/media_router/junit/org/chromium/chrome/browser/media/router/DiscoveryCallbackTest.java rename to chrome/android/features/media_router/junit/src/org/chromium/chrome/browser/media/router/DiscoveryCallbackTest.java
diff --git a/chrome/android/features/media_router/junit/org/chromium/chrome/browser/media/router/JSONTestUtils.java b/chrome/android/features/media_router/junit/src/org/chromium/chrome/browser/media/router/JSONTestUtils.java similarity index 100% rename from chrome/android/features/media_router/junit/org/chromium/chrome/browser/media/router/JSONTestUtils.java rename to chrome/android/features/media_router/junit/src/org/chromium/chrome/browser/media/router/JSONTestUtils.java
diff --git a/chrome/android/features/media_router/junit/org/chromium/chrome/browser/media/router/OWNERS b/chrome/android/features/media_router/junit/src/org/chromium/chrome/browser/media/router/OWNERS similarity index 100% rename from chrome/android/features/media_router/junit/org/chromium/chrome/browser/media/router/OWNERS rename to chrome/android/features/media_router/junit/src/org/chromium/chrome/browser/media/router/OWNERS
diff --git a/chrome/android/features/media_router/junit/org/chromium/chrome/browser/media/router/TestUtils.java b/chrome/android/features/media_router/junit/src/org/chromium/chrome/browser/media/router/TestUtils.java similarity index 100% rename from chrome/android/features/media_router/junit/org/chromium/chrome/browser/media/router/TestUtils.java rename to chrome/android/features/media_router/junit/src/org/chromium/chrome/browser/media/router/TestUtils.java
diff --git a/chrome/android/features/media_router/junit/org/chromium/chrome/browser/media/router/caf/BaseSessionControllerTest.java b/chrome/android/features/media_router/junit/src/org/chromium/chrome/browser/media/router/caf/BaseSessionControllerTest.java similarity index 100% rename from chrome/android/features/media_router/junit/org/chromium/chrome/browser/media/router/caf/BaseSessionControllerTest.java rename to chrome/android/features/media_router/junit/src/org/chromium/chrome/browser/media/router/caf/BaseSessionControllerTest.java
diff --git a/chrome/android/features/media_router/junit/org/chromium/chrome/browser/media/router/caf/CafBaseMediaRouteProviderTest.java b/chrome/android/features/media_router/junit/src/org/chromium/chrome/browser/media/router/caf/CafBaseMediaRouteProviderTest.java similarity index 100% rename from chrome/android/features/media_router/junit/org/chromium/chrome/browser/media/router/caf/CafBaseMediaRouteProviderTest.java rename to chrome/android/features/media_router/junit/src/org/chromium/chrome/browser/media/router/caf/CafBaseMediaRouteProviderTest.java
diff --git a/chrome/android/features/media_router/junit/org/chromium/chrome/browser/media/router/caf/CafMediaRouteProviderTest.java b/chrome/android/features/media_router/junit/src/org/chromium/chrome/browser/media/router/caf/CafMediaRouteProviderTest.java similarity index 100% rename from chrome/android/features/media_router/junit/org/chromium/chrome/browser/media/router/caf/CafMediaRouteProviderTest.java rename to chrome/android/features/media_router/junit/src/org/chromium/chrome/browser/media/router/caf/CafMediaRouteProviderTest.java
diff --git a/chrome/android/features/media_router/junit/org/chromium/chrome/browser/media/router/caf/CafMessageHandlerTest.java b/chrome/android/features/media_router/junit/src/org/chromium/chrome/browser/media/router/caf/CafMessageHandlerTest.java similarity index 100% rename from chrome/android/features/media_router/junit/org/chromium/chrome/browser/media/router/caf/CafMessageHandlerTest.java rename to chrome/android/features/media_router/junit/src/org/chromium/chrome/browser/media/router/caf/CafMessageHandlerTest.java
diff --git a/chrome/android/features/media_router/junit/org/chromium/chrome/browser/media/router/caf/CastSessionControllerTest.java b/chrome/android/features/media_router/junit/src/org/chromium/chrome/browser/media/router/caf/CastSessionControllerTest.java similarity index 100% rename from chrome/android/features/media_router/junit/org/chromium/chrome/browser/media/router/caf/CastSessionControllerTest.java rename to chrome/android/features/media_router/junit/src/org/chromium/chrome/browser/media/router/caf/CastSessionControllerTest.java
diff --git a/chrome/android/features/media_router/junit/org/chromium/chrome/browser/media/router/caf/MediaRouterTestHelper.java b/chrome/android/features/media_router/junit/src/org/chromium/chrome/browser/media/router/caf/MediaRouterTestHelper.java similarity index 100% rename from chrome/android/features/media_router/junit/org/chromium/chrome/browser/media/router/caf/MediaRouterTestHelper.java rename to chrome/android/features/media_router/junit/src/org/chromium/chrome/browser/media/router/caf/MediaRouterTestHelper.java
diff --git a/chrome/android/features/media_router/junit/org/chromium/chrome/browser/media/router/caf/ShadowCastContext.java b/chrome/android/features/media_router/junit/src/org/chromium/chrome/browser/media/router/caf/ShadowCastContext.java similarity index 100% rename from chrome/android/features/media_router/junit/org/chromium/chrome/browser/media/router/caf/ShadowCastContext.java rename to chrome/android/features/media_router/junit/src/org/chromium/chrome/browser/media/router/caf/ShadowCastContext.java
diff --git a/chrome/android/features/media_router/junit/org/chromium/chrome/browser/media/router/caf/ShadowCastMediaSource.java b/chrome/android/features/media_router/junit/src/org/chromium/chrome/browser/media/router/caf/ShadowCastMediaSource.java similarity index 100% rename from chrome/android/features/media_router/junit/org/chromium/chrome/browser/media/router/caf/ShadowCastMediaSource.java rename to chrome/android/features/media_router/junit/src/org/chromium/chrome/browser/media/router/caf/ShadowCastMediaSource.java
diff --git a/chrome/android/features/media_router/junit/org/chromium/chrome/browser/media/router/caf/ShadowMediaRouter.java b/chrome/android/features/media_router/junit/src/org/chromium/chrome/browser/media/router/caf/ShadowMediaRouter.java similarity index 100% rename from chrome/android/features/media_router/junit/org/chromium/chrome/browser/media/router/caf/ShadowMediaRouter.java rename to chrome/android/features/media_router/junit/src/org/chromium/chrome/browser/media/router/caf/ShadowMediaRouter.java
diff --git a/chrome/android/features/vr/BUILD.gn b/chrome/android/features/vr/BUILD.gn new file mode 100644 index 0000000..917275c --- /dev/null +++ b/chrome/android/features/vr/BUILD.gn
@@ -0,0 +1,141 @@ +# Copyright 2019 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//build/config/android/rules.gni") +import("//chrome/common/features.gni") +import("//device/vr/buildflags/buildflags.gni") + +assert(enable_vr) + +java_strings_grd("java_strings_grd") { + defines = chrome_grit_defines + grd_file = "java/strings/android_chrome_vr_strings.grd" + outputs = [ + "values-am/android_chrome_vr_strings.xml", + "values-ar/android_chrome_vr_strings.xml", + "values-bg/android_chrome_vr_strings.xml", + "values-ca/android_chrome_vr_strings.xml", + "values-cs/android_chrome_vr_strings.xml", + "values-da/android_chrome_vr_strings.xml", + "values-de/android_chrome_vr_strings.xml", + "values-el/android_chrome_vr_strings.xml", + "values/android_chrome_vr_strings.xml", + "values-en-rGB/android_chrome_vr_strings.xml", + "values-es/android_chrome_vr_strings.xml", + "values-es-rUS/android_chrome_vr_strings.xml", + "values-fa/android_chrome_vr_strings.xml", + "values-fi/android_chrome_vr_strings.xml", + "values-tl/android_chrome_vr_strings.xml", + "values-fr/android_chrome_vr_strings.xml", + "values-hi/android_chrome_vr_strings.xml", + "values-hr/android_chrome_vr_strings.xml", + "values-hu/android_chrome_vr_strings.xml", + "values-in/android_chrome_vr_strings.xml", + "values-it/android_chrome_vr_strings.xml", + "values-iw/android_chrome_vr_strings.xml", + "values-ja/android_chrome_vr_strings.xml", + "values-ko/android_chrome_vr_strings.xml", + "values-lt/android_chrome_vr_strings.xml", + "values-lv/android_chrome_vr_strings.xml", + "values-nl/android_chrome_vr_strings.xml", + "values-nb/android_chrome_vr_strings.xml", + "values-pl/android_chrome_vr_strings.xml", + "values-pt-rBR/android_chrome_vr_strings.xml", + "values-pt-rPT/android_chrome_vr_strings.xml", + "values-ro/android_chrome_vr_strings.xml", + "values-ru/android_chrome_vr_strings.xml", + "values-sk/android_chrome_vr_strings.xml", + "values-sl/android_chrome_vr_strings.xml", + "values-sr/android_chrome_vr_strings.xml", + "values-sv/android_chrome_vr_strings.xml", + "values-sw/android_chrome_vr_strings.xml", + "values-th/android_chrome_vr_strings.xml", + "values-tr/android_chrome_vr_strings.xml", + "values-uk/android_chrome_vr_strings.xml", + "values-vi/android_chrome_vr_strings.xml", + "values-zh-rCN/android_chrome_vr_strings.xml", + "values-zh-rTW/android_chrome_vr_strings.xml", + ] +} + +android_resources("java_resources") { + resource_dirs = [ "java/res" ] + + deps = [ + ":java_strings_grd", + ] + + custom_package = "org.chromium.chrome.vr" +} + +android_library("java") { + java_files = [ + "java/src/org/chromium/chrome/browser/vr/AndroidUiGestureTarget.java", + "java/src/org/chromium/chrome/browser/vr/AndroidVSyncHelper.java", + "java/src/org/chromium/chrome/browser/vr/EmptySniffingVrViewContainer.java", + "java/src/org/chromium/chrome/browser/vr/keyboard/BuildConstants.java", + "java/src/org/chromium/chrome/browser/vr/keyboard/GvrKeyboardLoaderClient.java", + "java/src/org/chromium/chrome/browser/vr/keyboard/TextEditAction.java", + "java/src/org/chromium/chrome/browser/vr/keyboard/VrInputMethodManagerWrapper.java", + "java/src/org/chromium/chrome/browser/vr/NoopCanvas.java", + "java/src/org/chromium/chrome/browser/vr/OnDispatchTouchEventCallback.java", + "java/src/org/chromium/chrome/browser/vr/VrAlertDialog.java", + "java/src/org/chromium/chrome/browser/vr/VrCancelAnimationActivity.java", + "java/src/org/chromium/chrome/browser/vr/VrCompositorSurfaceManager.java", + "java/src/org/chromium/chrome/browser/vr/VrCoreInfo.java", + "java/src/org/chromium/chrome/browser/vr/VrCoreVersionChecker.java", + "java/src/org/chromium/chrome/browser/vr/VrDaydreamApi.java", + "java/src/org/chromium/chrome/browser/vr/VrDelegateImpl.java", + "java/src/org/chromium/chrome/browser/vr/VrIntentDelegateImpl.java", + "java/src/org/chromium/chrome/browser/vr/VrDelegateProviderImpl.java", + "java/src/org/chromium/chrome/browser/vr/VrDialog.java", + "java/src/org/chromium/chrome/browser/vr/VrDialogManager.java", + "java/src/org/chromium/chrome/browser/vr/VrFeedbackStatus.java", + "java/src/org/chromium/chrome/browser/vr/VrFirstRunActivity.java", + "java/src/org/chromium/chrome/browser/vr/VrInputConnection.java", + "java/src/org/chromium/chrome/browser/vr/VrModalPresenter.java", + "java/src/org/chromium/chrome/browser/vr/VrPopupWindow.java", + "java/src/org/chromium/chrome/browser/vr/VrShell.java", + "java/src/org/chromium/chrome/browser/vr/VrShellDelegate.java", + "java/src/org/chromium/chrome/browser/vr/VrToast.java", + "java/src/org/chromium/chrome/browser/vr/VrToastManager.java", + "java/src/org/chromium/chrome/browser/vr/VrUiWidgetFactory.java", + "java/src/org/chromium/chrome/browser/vr/VrViewContainer.java", + "java/src/org/chromium/chrome/browser/vr/VrWindowAndroid.java", + ] + + classpath_deps = [ + "//base:base_java", + "//chrome/android:chrome_java", + "//components/policy/android:policy_java", + "//content/public/android:content_java", + "//third_party/android_deps:android_arch_lifecycle_common_java", + "//third_party/android_deps:android_arch_lifecycle_runtime_java", + "//third_party/android_deps:android_support_annotations_java", + "//third_party/android_deps:android_support_v7_appcompat_java", + "//third_party/gvr-android-keyboard:kb_java", + "//ui/android:ui_full_java", + "//ui/android:ui_utils_java", + ] + + deps = [ + ":java_resources", + "//third_party/gvr-android-sdk:gvr_common_java", + ] +} + +generate_jni("jni_headers") { + sources = [ + "java/src/org/chromium/chrome/browser/vr/AndroidUiGestureTarget.java", + "java/src/org/chromium/chrome/browser/vr/AndroidVSyncHelper.java", + "java/src/org/chromium/chrome/browser/vr/VrCoreInfo.java", + "java/src/org/chromium/chrome/browser/vr/VrInputConnection.java", + "java/src/org/chromium/chrome/browser/vr/VrModuleProvider.java", + "java/src/org/chromium/chrome/browser/vr/VrShell.java", + "java/src/org/chromium/chrome/browser/vr/VrShellDelegate.java", + "java/src/org/chromium/chrome/browser/vr/keyboard/GvrKeyboardLoaderClient.java", + "java/src/org/chromium/chrome/browser/vr/keyboard/TextEditAction.java", + ] + jni_package = "vr" +}
diff --git a/chrome/android/features/vr/DEPS b/chrome/android/features/vr/DEPS new file mode 100644 index 0000000..96de8413 --- /dev/null +++ b/chrome/android/features/vr/DEPS
@@ -0,0 +1,4 @@ +include_rules = [ + "+components/module_installer", + "+content/public/android/java/src/org/chromium/content_public", +]
diff --git a/chrome/android/features/vr/AndroidManifest.xml b/chrome/android/features/vr/java/AndroidManifest.xml similarity index 100% rename from chrome/android/features/vr/AndroidManifest.xml rename to chrome/android/features/vr/java/AndroidManifest.xml
diff --git a/chrome/android/java/res_vr/drawable-hdpi/vr_services.png b/chrome/android/features/vr/java/res/drawable-hdpi/vr_services.png similarity index 100% rename from chrome/android/java/res_vr/drawable-hdpi/vr_services.png rename to chrome/android/features/vr/java/res/drawable-hdpi/vr_services.png Binary files differ
diff --git a/chrome/android/java/res_vr/drawable-mdpi/vr_services.png b/chrome/android/features/vr/java/res/drawable-mdpi/vr_services.png similarity index 100% rename from chrome/android/java/res_vr/drawable-mdpi/vr_services.png rename to chrome/android/features/vr/java/res/drawable-mdpi/vr_services.png Binary files differ
diff --git a/chrome/android/java/res_vr/drawable-xhdpi/vr_services.png b/chrome/android/features/vr/java/res/drawable-xhdpi/vr_services.png similarity index 100% rename from chrome/android/java/res_vr/drawable-xhdpi/vr_services.png rename to chrome/android/features/vr/java/res/drawable-xhdpi/vr_services.png Binary files differ
diff --git a/chrome/android/java/res_vr/drawable-xxhdpi/vr_services.png b/chrome/android/features/vr/java/res/drawable-xxhdpi/vr_services.png similarity index 100% rename from chrome/android/java/res_vr/drawable-xxhdpi/vr_services.png rename to chrome/android/features/vr/java/res/drawable-xxhdpi/vr_services.png Binary files differ
diff --git a/chrome/android/java/res_vr/drawable-xxxhdpi/vr_services.png b/chrome/android/features/vr/java/res/drawable-xxxhdpi/vr_services.png similarity index 100% rename from chrome/android/java/res_vr/drawable-xxxhdpi/vr_services.png rename to chrome/android/features/vr/java/res/drawable-xxxhdpi/vr_services.png Binary files differ
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr/AndroidUiGestureTarget.java b/chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/AndroidUiGestureTarget.java similarity index 100% rename from chrome/android/java/src/org/chromium/chrome/browser/vr/AndroidUiGestureTarget.java rename to chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/AndroidUiGestureTarget.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr/AndroidVSyncHelper.java b/chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/AndroidVSyncHelper.java similarity index 100% rename from chrome/android/java/src/org/chromium/chrome/browser/vr/AndroidVSyncHelper.java rename to chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/AndroidVSyncHelper.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr/EmptySniffingVrViewContainer.java b/chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/EmptySniffingVrViewContainer.java similarity index 100% rename from chrome/android/java/src/org/chromium/chrome/browser/vr/EmptySniffingVrViewContainer.java rename to chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/EmptySniffingVrViewContainer.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr/NoopCanvas.java b/chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/NoopCanvas.java similarity index 100% rename from chrome/android/java/src/org/chromium/chrome/browser/vr/NoopCanvas.java rename to chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/NoopCanvas.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr/OnDispatchTouchEventCallback.java b/chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/OnDispatchTouchEventCallback.java similarity index 100% rename from chrome/android/java/src/org/chromium/chrome/browser/vr/OnDispatchTouchEventCallback.java rename to chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/OnDispatchTouchEventCallback.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr/OnExitVrRequestListener.java b/chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/OnExitVrRequestListener.java similarity index 100% rename from chrome/android/java/src/org/chromium/chrome/browser/vr/OnExitVrRequestListener.java rename to chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/OnExitVrRequestListener.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr/VrAlertDialog.java b/chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrAlertDialog.java similarity index 97% rename from chrome/android/java/src/org/chromium/chrome/browser/vr/VrAlertDialog.java rename to chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrAlertDialog.java index 03de5a8..520feb7 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/vr/VrAlertDialog.java +++ b/chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrAlertDialog.java
@@ -84,7 +84,7 @@ @Override public void setButton( int whichButton, CharSequence text, DialogInterface.OnClickListener listener) { - assert(whichButton == DialogInterface.BUTTON_POSITIVE + assert (whichButton == DialogInterface.BUTTON_POSITIVE || whichButton == DialogInterface.BUTTON_NEGATIVE); if (whichButton == DialogInterface.BUTTON_POSITIVE) { mButtonPositive = new DialogButton( @@ -118,7 +118,7 @@ @Override public void onDismiss(PropertyModel model, int dismissalCause) {} }; - assert(mView == null || mMessage == null); + assert (mView == null || mMessage == null); String message = mMessage != null ? mMessage.toString() : null; String positiveButtonText = mButtonPositive != null ? mButtonPositive.getText() : null;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr/VrCancelAnimationActivity.java b/chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrCancelAnimationActivity.java similarity index 100% rename from chrome/android/java/src/org/chromium/chrome/browser/vr/VrCancelAnimationActivity.java rename to chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrCancelAnimationActivity.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr/VrCompositorSurfaceManager.java b/chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrCompositorSurfaceManager.java similarity index 100% rename from chrome/android/java/src/org/chromium/chrome/browser/vr/VrCompositorSurfaceManager.java rename to chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrCompositorSurfaceManager.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr/VrCoreInfo.java b/chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrCoreInfo.java similarity index 94% rename from chrome/android/java/src/org/chromium/chrome/browser/vr/VrCoreInfo.java rename to chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrCoreInfo.java index 70e503c..437af23 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/vr/VrCoreInfo.java +++ b/chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrCoreInfo.java
@@ -36,7 +36,7 @@ public long makeNativeVrCoreInfo() { return (gvrVersion == null) ? nativeInit(0, 0, 0, compatibility) : nativeInit(gvrVersion.majorVersion, gvrVersion.minorVersion, - gvrVersion.patchVersion, compatibility); + gvrVersion.patchVersion, compatibility); } private native long nativeInit(
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr/VrCoreVersionChecker.java b/chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrCoreVersionChecker.java similarity index 100% rename from chrome/android/java/src/org/chromium/chrome/browser/vr/VrCoreVersionChecker.java rename to chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrCoreVersionChecker.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr/VrDaydreamApi.java b/chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrDaydreamApi.java similarity index 100% rename from chrome/android/java/src/org/chromium/chrome/browser/vr/VrDaydreamApi.java rename to chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrDaydreamApi.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr/VrDelegate.java b/chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrDelegate.java similarity index 100% rename from chrome/android/java/src/org/chromium/chrome/browser/vr/VrDelegate.java rename to chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrDelegate.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr/VrDelegateFallback.java b/chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrDelegateFallback.java similarity index 100% rename from chrome/android/java/src/org/chromium/chrome/browser/vr/VrDelegateFallback.java rename to chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrDelegateFallback.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr/VrDelegateImpl.java b/chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrDelegateImpl.java similarity index 100% rename from chrome/android/java/src/org/chromium/chrome/browser/vr/VrDelegateImpl.java rename to chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrDelegateImpl.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr/VrDelegateProvider.java b/chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrDelegateProvider.java similarity index 100% rename from chrome/android/java/src/org/chromium/chrome/browser/vr/VrDelegateProvider.java rename to chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrDelegateProvider.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr/VrDelegateProviderFallback.java b/chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrDelegateProviderFallback.java similarity index 100% rename from chrome/android/java/src/org/chromium/chrome/browser/vr/VrDelegateProviderFallback.java rename to chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrDelegateProviderFallback.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr/VrDelegateProviderImpl.java b/chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrDelegateProviderImpl.java similarity index 100% rename from chrome/android/java/src/org/chromium/chrome/browser/vr/VrDelegateProviderImpl.java rename to chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrDelegateProviderImpl.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr/VrDialog.java b/chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrDialog.java similarity index 100% rename from chrome/android/java/src/org/chromium/chrome/browser/vr/VrDialog.java rename to chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrDialog.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr/VrDialogManager.java b/chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrDialogManager.java similarity index 100% rename from chrome/android/java/src/org/chromium/chrome/browser/vr/VrDialogManager.java rename to chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrDialogManager.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr/VrFallbackUtils.java b/chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrFallbackUtils.java similarity index 100% rename from chrome/android/java/src/org/chromium/chrome/browser/vr/VrFallbackUtils.java rename to chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrFallbackUtils.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr/VrFeedbackStatus.java b/chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrFeedbackStatus.java similarity index 100% rename from chrome/android/java/src/org/chromium/chrome/browser/vr/VrFeedbackStatus.java rename to chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrFeedbackStatus.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr/VrFirstRunActivity.java b/chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrFirstRunActivity.java similarity index 100% rename from chrome/android/java/src/org/chromium/chrome/browser/vr/VrFirstRunActivity.java rename to chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrFirstRunActivity.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr/VrInputConnection.java b/chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrInputConnection.java similarity index 100% rename from chrome/android/java/src/org/chromium/chrome/browser/vr/VrInputConnection.java rename to chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrInputConnection.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr/VrIntentDelegate.java b/chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrIntentDelegate.java similarity index 100% rename from chrome/android/java/src/org/chromium/chrome/browser/vr/VrIntentDelegate.java rename to chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrIntentDelegate.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr/VrIntentDelegateFallback.java b/chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrIntentDelegateFallback.java similarity index 100% rename from chrome/android/java/src/org/chromium/chrome/browser/vr/VrIntentDelegateFallback.java rename to chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrIntentDelegateFallback.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr/VrIntentDelegateImpl.java b/chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrIntentDelegateImpl.java similarity index 100% rename from chrome/android/java/src/org/chromium/chrome/browser/vr/VrIntentDelegateImpl.java rename to chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrIntentDelegateImpl.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr/VrModalPresenter.java b/chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrModalPresenter.java similarity index 100% rename from chrome/android/java/src/org/chromium/chrome/browser/vr/VrModalPresenter.java rename to chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrModalPresenter.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr/VrModeObserver.java b/chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrModeObserver.java similarity index 100% rename from chrome/android/java/src/org/chromium/chrome/browser/vr/VrModeObserver.java rename to chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrModeObserver.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr/VrModuleProvider.java b/chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrModuleProvider.java similarity index 100% rename from chrome/android/java/src/org/chromium/chrome/browser/vr/VrModuleProvider.java rename to chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrModuleProvider.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr/VrPopupWindow.java b/chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrPopupWindow.java similarity index 100% rename from chrome/android/java/src/org/chromium/chrome/browser/vr/VrPopupWindow.java rename to chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrPopupWindow.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr/VrShell.java b/chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrShell.java similarity index 100% rename from chrome/android/java/src/org/chromium/chrome/browser/vr/VrShell.java rename to chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrShell.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr/VrShellDelegate.java b/chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrShellDelegate.java similarity index 99% rename from chrome/android/java/src/org/chromium/chrome/browser/vr/VrShellDelegate.java rename to chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrShellDelegate.java index f9d46208..eb8985c 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/vr/VrShellDelegate.java +++ b/chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrShellDelegate.java
@@ -424,8 +424,7 @@ registerDaydreamIntent(activity); } } - } - .executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } catch (RejectedExecutionException ex) { // This isn't critical work, so it's okay to fail silently. If the user does try to // enter VR the asset component may not be available, and headset insertion will go to @@ -828,7 +827,7 @@ SimpleConfirmInfoBarBuilder.create(tab, listener, InfoBarIdentifier.VR_FEEDBACK_INFOBAR_ANDROID, - org.chromium.chrome.vr.pub.R.drawable.vr_services, + org.chromium.chrome.vr.R.drawable.vr_services, ContextUtils.getApplicationContext().getString( org.chromium.chrome.vr.R.string.vr_shell_feedback_infobar_description), ContextUtils.getApplicationContext().getString( @@ -1022,8 +1021,8 @@ }; SimpleConfirmInfoBarBuilder.create(tab, listener, InfoBarIdentifier.VR_SERVICES_UPGRADE_ANDROID, - org.chromium.chrome.vr.pub.R.drawable.vr_services, infobarText, buttonText, null, - null, true); + org.chromium.chrome.vr.R.drawable.vr_services, infobarText, buttonText, null, null, + true); } @VisibleForTesting @@ -1461,7 +1460,7 @@ maybeUpdateVrSupportLevel(); // Shouldn't handle VR Intents pre-Daydream. - assert(getVrSupportLevel() == VrSupportLevel.VR_DAYDREAM || !mStartedFromVrIntent); + assert (getVrSupportLevel() == VrSupportLevel.VR_DAYDREAM || !mStartedFromVrIntent); StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites(); try { @@ -1495,7 +1494,7 @@ // If we were resumed at the wrong density, we need to trigger activity recreation. if (!mInVr && mExpectedDensityChange != 0 && (mActivity.getResources().getConfiguration().densityDpi - != mExpectedDensityChange)) { + != mExpectedDensityChange)) { mActivity.recreate(); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr/VrToast.java b/chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrToast.java similarity index 100% rename from chrome/android/java/src/org/chromium/chrome/browser/vr/VrToast.java rename to chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrToast.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr/VrToastManager.java b/chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrToastManager.java similarity index 100% rename from chrome/android/java/src/org/chromium/chrome/browser/vr/VrToastManager.java rename to chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrToastManager.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr/VrUiWidgetFactory.java b/chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrUiWidgetFactory.java similarity index 100% rename from chrome/android/java/src/org/chromium/chrome/browser/vr/VrUiWidgetFactory.java rename to chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrUiWidgetFactory.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr/VrViewContainer.java b/chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrViewContainer.java similarity index 100% rename from chrome/android/java/src/org/chromium/chrome/browser/vr/VrViewContainer.java rename to chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrViewContainer.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr/VrWindowAndroid.java b/chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrWindowAndroid.java similarity index 100% rename from chrome/android/java/src/org/chromium/chrome/browser/vr/VrWindowAndroid.java rename to chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrWindowAndroid.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr/keyboard/BuildConstants.java b/chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/keyboard/BuildConstants.java similarity index 100% rename from chrome/android/java/src/org/chromium/chrome/browser/vr/keyboard/BuildConstants.java rename to chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/keyboard/BuildConstants.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr/keyboard/GvrKeyboardLoaderClient.java b/chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/keyboard/GvrKeyboardLoaderClient.java similarity index 100% rename from chrome/android/java/src/org/chromium/chrome/browser/vr/keyboard/GvrKeyboardLoaderClient.java rename to chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/keyboard/GvrKeyboardLoaderClient.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr/keyboard/TextEditAction.java b/chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/keyboard/TextEditAction.java similarity index 100% rename from chrome/android/java/src/org/chromium/chrome/browser/vr/keyboard/TextEditAction.java rename to chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/keyboard/TextEditAction.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr/keyboard/VrInputMethodManagerWrapper.java b/chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/keyboard/VrInputMethodManagerWrapper.java similarity index 100% rename from chrome/android/java/src/org/chromium/chrome/browser/vr/keyboard/VrInputMethodManagerWrapper.java rename to chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/keyboard/VrInputMethodManagerWrapper.java
diff --git a/chrome/android/features/vr/java/strings/android_chrome_vr_strings.grd b/chrome/android/features/vr/java/strings/android_chrome_vr_strings.grd new file mode 100644 index 0000000..2ebbb4f5 --- /dev/null +++ b/chrome/android/features/vr/java/strings/android_chrome_vr_strings.grd
@@ -0,0 +1,130 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- android_chrome_strings.grd contains strings for VR DFM of Chrome for Android. --> +<grit current_release="1" latest_public_release="0" output_all_resource_defines="false"> + <outputs> + <output filename="values-am/android_chrome_vr_strings.xml" lang="am" type="android" /> + <output filename="values-ar/android_chrome_vr_strings.xml" lang="ar" type="android" /> + <output filename="values-bg/android_chrome_vr_strings.xml" lang="bg" type="android" /> + <output filename="values-ca/android_chrome_vr_strings.xml" lang="ca" type="android" /> + <output filename="values-cs/android_chrome_vr_strings.xml" lang="cs" type="android" /> + <output filename="values-da/android_chrome_vr_strings.xml" lang="da" type="android" /> + <output filename="values-de/android_chrome_vr_strings.xml" lang="de" type="android" /> + <output filename="values-el/android_chrome_vr_strings.xml" lang="el" type="android" /> + <output filename="values/android_chrome_vr_strings.xml" lang="en" type="android" /> + <output filename="values-en-rGB/android_chrome_vr_strings.xml" lang="en-GB" type="android" /> + <output filename="values-es/android_chrome_vr_strings.xml" lang="es" type="android" /> + <output filename="values-es-rUS/android_chrome_vr_strings.xml" lang="es-419" type="android" /> + <output filename="values-fa/android_chrome_vr_strings.xml" lang="fa" type="android" /> + <output filename="values-fi/android_chrome_vr_strings.xml" lang="fi" type="android" /> + <output filename="values-tl/android_chrome_vr_strings.xml" lang="fil" type="android" /> + <output filename="values-fr/android_chrome_vr_strings.xml" lang="fr" type="android" /> + <output filename="values-hi/android_chrome_vr_strings.xml" lang="hi" type="android" /> + <output filename="values-hr/android_chrome_vr_strings.xml" lang="hr" type="android" /> + <output filename="values-hu/android_chrome_vr_strings.xml" lang="hu" type="android" /> + <output filename="values-in/android_chrome_vr_strings.xml" lang="id" type="android" /> + <output filename="values-it/android_chrome_vr_strings.xml" lang="it" type="android" /> + <output filename="values-iw/android_chrome_vr_strings.xml" lang="iw" type="android" /> + <output filename="values-ja/android_chrome_vr_strings.xml" lang="ja" type="android" /> + <output filename="values-ko/android_chrome_vr_strings.xml" lang="ko" type="android" /> + <output filename="values-lt/android_chrome_vr_strings.xml" lang="lt" type="android" /> + <output filename="values-lv/android_chrome_vr_strings.xml" lang="lv" type="android" /> + <output filename="values-nl/android_chrome_vr_strings.xml" lang="nl" type="android" /> + <output filename="values-nb/android_chrome_vr_strings.xml" lang="no" type="android" /> + <output filename="values-pl/android_chrome_vr_strings.xml" lang="pl" type="android" /> + <output filename="values-pt-rBR/android_chrome_vr_strings.xml" lang="pt-BR" type="android" /> + <output filename="values-pt-rPT/android_chrome_vr_strings.xml" lang="pt-PT" type="android" /> + <output filename="values-ro/android_chrome_vr_strings.xml" lang="ro" type="android" /> + <output filename="values-ru/android_chrome_vr_strings.xml" lang="ru" type="android" /> + <output filename="values-sk/android_chrome_vr_strings.xml" lang="sk" type="android" /> + <output filename="values-sl/android_chrome_vr_strings.xml" lang="sl" type="android" /> + <output filename="values-sr/android_chrome_vr_strings.xml" lang="sr" type="android" /> + <output filename="values-sv/android_chrome_vr_strings.xml" lang="sv" type="android" /> + <output filename="values-sw/android_chrome_vr_strings.xml" lang="sw" type="android" /> + <output filename="values-th/android_chrome_vr_strings.xml" lang="th" type="android" /> + <output filename="values-tr/android_chrome_vr_strings.xml" lang="tr" type="android" /> + <output filename="values-uk/android_chrome_vr_strings.xml" lang="uk" type="android" /> + <output filename="values-vi/android_chrome_vr_strings.xml" lang="vi" type="android" /> + <output filename="values-zh-rCN/android_chrome_vr_strings.xml" lang="zh-CN" type="android" /> + <output filename="values-zh-rTW/android_chrome_vr_strings.xml" lang="zh-TW" type="android" /> + </outputs> + <translations> + <file lang="am" path="translations/android_chrome_vr_strings_am.xtb" /> + <file lang="ar" path="translations/android_chrome_vr_strings_ar.xtb" /> + <file lang="bg" path="translations/android_chrome_vr_strings_bg.xtb" /> + <file lang="bn" path="translations/android_chrome_vr_strings_bn.xtb" /> + <file lang="ca" path="translations/android_chrome_vr_strings_ca.xtb" /> + <file lang="cs" path="translations/android_chrome_vr_strings_cs.xtb" /> + <file lang="da" path="translations/android_chrome_vr_strings_da.xtb" /> + <file lang="de" path="translations/android_chrome_vr_strings_de.xtb" /> + <file lang="el" path="translations/android_chrome_vr_strings_el.xtb" /> + <file lang="en-GB" path="translations/android_chrome_vr_strings_en-GB.xtb" /> + <file lang="es" path="translations/android_chrome_vr_strings_es.xtb" /> + <file lang="es-419" path="translations/android_chrome_vr_strings_es-419.xtb" /> + <file lang="et" path="translations/android_chrome_vr_strings_et.xtb" /> + <file lang="fa" path="translations/android_chrome_vr_strings_fa.xtb" /> + <file lang="fi" path="translations/android_chrome_vr_strings_fi.xtb" /> + <file lang="fil" path="translations/android_chrome_vr_strings_fil.xtb" /> + <file lang="fr" path="translations/android_chrome_vr_strings_fr.xtb" /> + <file lang="gu" path="translations/android_chrome_vr_strings_gu.xtb" /> + <file lang="hi" path="translations/android_chrome_vr_strings_hi.xtb" /> + <file lang="hr" path="translations/android_chrome_vr_strings_hr.xtb" /> + <file lang="hu" path="translations/android_chrome_vr_strings_hu.xtb" /> + <file lang="id" path="translations/android_chrome_vr_strings_id.xtb" /> + <file lang="it" path="translations/android_chrome_vr_strings_it.xtb" /> + <file lang="iw" path="translations/android_chrome_vr_strings_iw.xtb" /> + <file lang="ja" path="translations/android_chrome_vr_strings_ja.xtb" /> + <file lang="ko" path="translations/android_chrome_vr_strings_ko.xtb" /> + <file lang="kn" path="translations/android_chrome_vr_strings_kn.xtb" /> + <file lang="lt" path="translations/android_chrome_vr_strings_lt.xtb" /> + <file lang="lv" path="translations/android_chrome_vr_strings_lv.xtb" /> + <file lang="ml" path="translations/android_chrome_vr_strings_ml.xtb" /> + <file lang="mr" path="translations/android_chrome_vr_strings_mr.xtb" /> + <file lang="ms" path="translations/android_chrome_vr_strings_ms.xtb" /> + <file lang="nl" path="translations/android_chrome_vr_strings_nl.xtb" /> + <file lang="no" path="translations/android_chrome_vr_strings_no.xtb" /> + <file lang="pl" path="translations/android_chrome_vr_strings_pl.xtb" /> + <file lang="pt-BR" path="translations/android_chrome_vr_strings_pt-BR.xtb" /> + <file lang="pt-PT" path="translations/android_chrome_vr_strings_pt-PT.xtb" /> + <file lang="ro" path="translations/android_chrome_vr_strings_ro.xtb" /> + <file lang="ru" path="translations/android_chrome_vr_strings_ru.xtb" /> + <file lang="sk" path="translations/android_chrome_vr_strings_sk.xtb" /> + <file lang="sl" path="translations/android_chrome_vr_strings_sl.xtb" /> + <file lang="sr" path="translations/android_chrome_vr_strings_sr.xtb" /> + <file lang="sv" path="translations/android_chrome_vr_strings_sv.xtb" /> + <file lang="sw" path="translations/android_chrome_vr_strings_sw.xtb" /> + <file lang="ta" path="translations/android_chrome_vr_strings_ta.xtb" /> + <file lang="te" path="translations/android_chrome_vr_strings_te.xtb" /> + <file lang="th" path="translations/android_chrome_vr_strings_th.xtb" /> + <file lang="tr" path="translations/android_chrome_vr_strings_tr.xtb" /> + <file lang="uk" path="translations/android_chrome_vr_strings_uk.xtb" /> + <file lang="vi" path="translations/android_chrome_vr_strings_vi.xtb" /> + <file lang="zh-CN" path="translations/android_chrome_vr_strings_zh-CN.xtb" /> + <file lang="zh-TW" path="translations/android_chrome_vr_strings_zh-TW.xtb" /> + </translations> + <release allow_pseudo="false" seq="1"> + <messages fallback_to_english="true"> + <!-- Chrome VR feedback infobar --> + <message name="IDS_VR_SHELL_FEEDBACK_INFOBAR_DESCRIPTION" desc="Description for infobar prompting the user for feedback on their VR browsing experience."> + Help improve the VR experience in Chrome + </message> + <message name="IDS_VR_SHELL_FEEDBACK_INFOBAR_FEEDBACK_BUTTON" desc="Brief button text asking the user to provide feedback in the VR feedback infobar."> + Provide feedback + </message> + + <!-- VR services check infobar --> + <message name="IDS_VR_SERVICES_CHECK_INFOBAR_INSTALL_TEXT" desc="Text to be displayed in the VR Services check infobar. When a WebVR page is loaded if the VR services that are needed to display WebVR don't exist an infobar will be shown to the user prompting them to install VR services."> + To view virtual reality content, install Google VR Services + </message> + <message name="IDS_VR_SERVICES_CHECK_INFOBAR_UPDATE_TEXT" desc="Text to be displayed in the VR Services check infobar. When a WebVR page is loaded if the VR services that are needed to display WebVR are out of date an infobar will be shown to the user prompting them to update VR services."> + To view virtual reality content, update Google VR Services + </message> + <message name="IDS_VR_SERVICES_CHECK_INFOBAR_INSTALL_BUTTON" desc="Text to be displayed in the VR Services check infobar confirm button for installing."> + Install + </message> + <message name="IDS_VR_SERVICES_CHECK_INFOBAR_UPDATE_BUTTON" desc="Text to be displayed in the VR Services check infobar confirm button for updating."> + Update + </message> + </messages> + </release> +</grit> +
diff --git a/chrome/android/java/strings/vr_translations/android_chrome_vr_strings_am.xtb b/chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_am.xtb similarity index 100% rename from chrome/android/java/strings/vr_translations/android_chrome_vr_strings_am.xtb rename to chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_am.xtb
diff --git a/chrome/android/java/strings/vr_translations/android_chrome_vr_strings_ar.xtb b/chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_ar.xtb similarity index 100% rename from chrome/android/java/strings/vr_translations/android_chrome_vr_strings_ar.xtb rename to chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_ar.xtb
diff --git a/chrome/android/java/strings/vr_translations/android_chrome_vr_strings_bg.xtb b/chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_bg.xtb similarity index 100% rename from chrome/android/java/strings/vr_translations/android_chrome_vr_strings_bg.xtb rename to chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_bg.xtb
diff --git a/chrome/android/java/strings/vr_translations/android_chrome_vr_strings_bn.xtb b/chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_bn.xtb similarity index 100% rename from chrome/android/java/strings/vr_translations/android_chrome_vr_strings_bn.xtb rename to chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_bn.xtb
diff --git a/chrome/android/java/strings/vr_translations/android_chrome_vr_strings_ca.xtb b/chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_ca.xtb similarity index 100% rename from chrome/android/java/strings/vr_translations/android_chrome_vr_strings_ca.xtb rename to chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_ca.xtb
diff --git a/chrome/android/java/strings/vr_translations/android_chrome_vr_strings_cs.xtb b/chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_cs.xtb similarity index 100% rename from chrome/android/java/strings/vr_translations/android_chrome_vr_strings_cs.xtb rename to chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_cs.xtb
diff --git a/chrome/android/java/strings/vr_translations/android_chrome_vr_strings_da.xtb b/chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_da.xtb similarity index 100% rename from chrome/android/java/strings/vr_translations/android_chrome_vr_strings_da.xtb rename to chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_da.xtb
diff --git a/chrome/android/java/strings/vr_translations/android_chrome_vr_strings_de.xtb b/chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_de.xtb similarity index 100% rename from chrome/android/java/strings/vr_translations/android_chrome_vr_strings_de.xtb rename to chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_de.xtb
diff --git a/chrome/android/java/strings/vr_translations/android_chrome_vr_strings_el.xtb b/chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_el.xtb similarity index 100% rename from chrome/android/java/strings/vr_translations/android_chrome_vr_strings_el.xtb rename to chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_el.xtb
diff --git a/chrome/android/java/strings/vr_translations/android_chrome_vr_strings_en-GB.xtb b/chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_en-GB.xtb similarity index 100% rename from chrome/android/java/strings/vr_translations/android_chrome_vr_strings_en-GB.xtb rename to chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_en-GB.xtb
diff --git a/chrome/android/java/strings/vr_translations/android_chrome_vr_strings_es-419.xtb b/chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_es-419.xtb similarity index 100% rename from chrome/android/java/strings/vr_translations/android_chrome_vr_strings_es-419.xtb rename to chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_es-419.xtb
diff --git a/chrome/android/java/strings/vr_translations/android_chrome_vr_strings_es.xtb b/chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_es.xtb similarity index 100% rename from chrome/android/java/strings/vr_translations/android_chrome_vr_strings_es.xtb rename to chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_es.xtb
diff --git a/chrome/android/java/strings/vr_translations/android_chrome_vr_strings_et.xtb b/chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_et.xtb similarity index 100% rename from chrome/android/java/strings/vr_translations/android_chrome_vr_strings_et.xtb rename to chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_et.xtb
diff --git a/chrome/android/java/strings/vr_translations/android_chrome_vr_strings_fa.xtb b/chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_fa.xtb similarity index 100% rename from chrome/android/java/strings/vr_translations/android_chrome_vr_strings_fa.xtb rename to chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_fa.xtb
diff --git a/chrome/android/java/strings/vr_translations/android_chrome_vr_strings_fi.xtb b/chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_fi.xtb similarity index 100% rename from chrome/android/java/strings/vr_translations/android_chrome_vr_strings_fi.xtb rename to chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_fi.xtb
diff --git a/chrome/android/java/strings/vr_translations/android_chrome_vr_strings_fil.xtb b/chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_fil.xtb similarity index 100% rename from chrome/android/java/strings/vr_translations/android_chrome_vr_strings_fil.xtb rename to chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_fil.xtb
diff --git a/chrome/android/java/strings/vr_translations/android_chrome_vr_strings_fr.xtb b/chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_fr.xtb similarity index 100% rename from chrome/android/java/strings/vr_translations/android_chrome_vr_strings_fr.xtb rename to chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_fr.xtb
diff --git a/chrome/android/java/strings/vr_translations/android_chrome_vr_strings_gu.xtb b/chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_gu.xtb similarity index 100% rename from chrome/android/java/strings/vr_translations/android_chrome_vr_strings_gu.xtb rename to chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_gu.xtb
diff --git a/chrome/android/java/strings/vr_translations/android_chrome_vr_strings_hi.xtb b/chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_hi.xtb similarity index 100% rename from chrome/android/java/strings/vr_translations/android_chrome_vr_strings_hi.xtb rename to chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_hi.xtb
diff --git a/chrome/android/java/strings/vr_translations/android_chrome_vr_strings_hr.xtb b/chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_hr.xtb similarity index 100% rename from chrome/android/java/strings/vr_translations/android_chrome_vr_strings_hr.xtb rename to chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_hr.xtb
diff --git a/chrome/android/java/strings/vr_translations/android_chrome_vr_strings_hu.xtb b/chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_hu.xtb similarity index 100% rename from chrome/android/java/strings/vr_translations/android_chrome_vr_strings_hu.xtb rename to chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_hu.xtb
diff --git a/chrome/android/java/strings/vr_translations/android_chrome_vr_strings_id.xtb b/chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_id.xtb similarity index 100% rename from chrome/android/java/strings/vr_translations/android_chrome_vr_strings_id.xtb rename to chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_id.xtb
diff --git a/chrome/android/java/strings/vr_translations/android_chrome_vr_strings_it.xtb b/chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_it.xtb similarity index 100% rename from chrome/android/java/strings/vr_translations/android_chrome_vr_strings_it.xtb rename to chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_it.xtb
diff --git a/chrome/android/java/strings/vr_translations/android_chrome_vr_strings_iw.xtb b/chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_iw.xtb similarity index 100% rename from chrome/android/java/strings/vr_translations/android_chrome_vr_strings_iw.xtb rename to chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_iw.xtb
diff --git a/chrome/android/java/strings/vr_translations/android_chrome_vr_strings_ja.xtb b/chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_ja.xtb similarity index 100% rename from chrome/android/java/strings/vr_translations/android_chrome_vr_strings_ja.xtb rename to chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_ja.xtb
diff --git a/chrome/android/java/strings/vr_translations/android_chrome_vr_strings_kn.xtb b/chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_kn.xtb similarity index 100% rename from chrome/android/java/strings/vr_translations/android_chrome_vr_strings_kn.xtb rename to chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_kn.xtb
diff --git a/chrome/android/java/strings/vr_translations/android_chrome_vr_strings_ko.xtb b/chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_ko.xtb similarity index 100% rename from chrome/android/java/strings/vr_translations/android_chrome_vr_strings_ko.xtb rename to chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_ko.xtb
diff --git a/chrome/android/java/strings/vr_translations/android_chrome_vr_strings_lt.xtb b/chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_lt.xtb similarity index 100% rename from chrome/android/java/strings/vr_translations/android_chrome_vr_strings_lt.xtb rename to chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_lt.xtb
diff --git a/chrome/android/java/strings/vr_translations/android_chrome_vr_strings_lv.xtb b/chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_lv.xtb similarity index 100% rename from chrome/android/java/strings/vr_translations/android_chrome_vr_strings_lv.xtb rename to chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_lv.xtb
diff --git a/chrome/android/java/strings/vr_translations/android_chrome_vr_strings_ml.xtb b/chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_ml.xtb similarity index 100% rename from chrome/android/java/strings/vr_translations/android_chrome_vr_strings_ml.xtb rename to chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_ml.xtb
diff --git a/chrome/android/java/strings/vr_translations/android_chrome_vr_strings_mr.xtb b/chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_mr.xtb similarity index 100% rename from chrome/android/java/strings/vr_translations/android_chrome_vr_strings_mr.xtb rename to chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_mr.xtb
diff --git a/chrome/android/java/strings/vr_translations/android_chrome_vr_strings_ms.xtb b/chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_ms.xtb similarity index 100% rename from chrome/android/java/strings/vr_translations/android_chrome_vr_strings_ms.xtb rename to chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_ms.xtb
diff --git a/chrome/android/java/strings/vr_translations/android_chrome_vr_strings_nl.xtb b/chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_nl.xtb similarity index 100% rename from chrome/android/java/strings/vr_translations/android_chrome_vr_strings_nl.xtb rename to chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_nl.xtb
diff --git a/chrome/android/java/strings/vr_translations/android_chrome_vr_strings_no.xtb b/chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_no.xtb similarity index 100% rename from chrome/android/java/strings/vr_translations/android_chrome_vr_strings_no.xtb rename to chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_no.xtb
diff --git a/chrome/android/java/strings/vr_translations/android_chrome_vr_strings_pl.xtb b/chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_pl.xtb similarity index 100% rename from chrome/android/java/strings/vr_translations/android_chrome_vr_strings_pl.xtb rename to chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_pl.xtb
diff --git a/chrome/android/java/strings/vr_translations/android_chrome_vr_strings_pt-BR.xtb b/chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_pt-BR.xtb similarity index 100% rename from chrome/android/java/strings/vr_translations/android_chrome_vr_strings_pt-BR.xtb rename to chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_pt-BR.xtb
diff --git a/chrome/android/java/strings/vr_translations/android_chrome_vr_strings_pt-PT.xtb b/chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_pt-PT.xtb similarity index 100% rename from chrome/android/java/strings/vr_translations/android_chrome_vr_strings_pt-PT.xtb rename to chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_pt-PT.xtb
diff --git a/chrome/android/java/strings/vr_translations/android_chrome_vr_strings_ro.xtb b/chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_ro.xtb similarity index 100% rename from chrome/android/java/strings/vr_translations/android_chrome_vr_strings_ro.xtb rename to chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_ro.xtb
diff --git a/chrome/android/java/strings/vr_translations/android_chrome_vr_strings_ru.xtb b/chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_ru.xtb similarity index 100% rename from chrome/android/java/strings/vr_translations/android_chrome_vr_strings_ru.xtb rename to chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_ru.xtb
diff --git a/chrome/android/java/strings/vr_translations/android_chrome_vr_strings_sk.xtb b/chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_sk.xtb similarity index 100% rename from chrome/android/java/strings/vr_translations/android_chrome_vr_strings_sk.xtb rename to chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_sk.xtb
diff --git a/chrome/android/java/strings/vr_translations/android_chrome_vr_strings_sl.xtb b/chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_sl.xtb similarity index 100% rename from chrome/android/java/strings/vr_translations/android_chrome_vr_strings_sl.xtb rename to chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_sl.xtb
diff --git a/chrome/android/java/strings/vr_translations/android_chrome_vr_strings_sr.xtb b/chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_sr.xtb similarity index 100% rename from chrome/android/java/strings/vr_translations/android_chrome_vr_strings_sr.xtb rename to chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_sr.xtb
diff --git a/chrome/android/java/strings/vr_translations/android_chrome_vr_strings_sv.xtb b/chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_sv.xtb similarity index 100% rename from chrome/android/java/strings/vr_translations/android_chrome_vr_strings_sv.xtb rename to chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_sv.xtb
diff --git a/chrome/android/java/strings/vr_translations/android_chrome_vr_strings_sw.xtb b/chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_sw.xtb similarity index 100% rename from chrome/android/java/strings/vr_translations/android_chrome_vr_strings_sw.xtb rename to chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_sw.xtb
diff --git a/chrome/android/java/strings/vr_translations/android_chrome_vr_strings_ta.xtb b/chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_ta.xtb similarity index 100% rename from chrome/android/java/strings/vr_translations/android_chrome_vr_strings_ta.xtb rename to chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_ta.xtb
diff --git a/chrome/android/java/strings/vr_translations/android_chrome_vr_strings_te.xtb b/chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_te.xtb similarity index 100% rename from chrome/android/java/strings/vr_translations/android_chrome_vr_strings_te.xtb rename to chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_te.xtb
diff --git a/chrome/android/java/strings/vr_translations/android_chrome_vr_strings_th.xtb b/chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_th.xtb similarity index 100% rename from chrome/android/java/strings/vr_translations/android_chrome_vr_strings_th.xtb rename to chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_th.xtb
diff --git a/chrome/android/java/strings/vr_translations/android_chrome_vr_strings_tr.xtb b/chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_tr.xtb similarity index 100% rename from chrome/android/java/strings/vr_translations/android_chrome_vr_strings_tr.xtb rename to chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_tr.xtb
diff --git a/chrome/android/java/strings/vr_translations/android_chrome_vr_strings_uk.xtb b/chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_uk.xtb similarity index 100% rename from chrome/android/java/strings/vr_translations/android_chrome_vr_strings_uk.xtb rename to chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_uk.xtb
diff --git a/chrome/android/java/strings/vr_translations/android_chrome_vr_strings_vi.xtb b/chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_vi.xtb similarity index 100% rename from chrome/android/java/strings/vr_translations/android_chrome_vr_strings_vi.xtb rename to chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_vi.xtb
diff --git a/chrome/android/java/strings/vr_translations/android_chrome_vr_strings_zh-CN.xtb b/chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_zh-CN.xtb similarity index 100% rename from chrome/android/java/strings/vr_translations/android_chrome_vr_strings_zh-CN.xtb rename to chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_zh-CN.xtb
diff --git a/chrome/android/java/strings/vr_translations/android_chrome_vr_strings_zh-TW.xtb b/chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_zh-TW.xtb similarity index 100% rename from chrome/android/java/strings/vr_translations/android_chrome_vr_strings_zh-TW.xtb rename to chrome/android/features/vr/java/strings/translations/android_chrome_vr_strings_zh-TW.xtb
diff --git a/chrome/android/features/vr/public_vr_java_sources.gni b/chrome/android/features/vr/public_vr_java_sources.gni new file mode 100644 index 0000000..c399fbce --- /dev/null +++ b/chrome/android/features/vr/public_vr_java_sources.gni
@@ -0,0 +1,16 @@ +# Copyright 2019 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +public_vr_java_sources = [ + "//chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/OnExitVrRequestListener.java", + "//chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrDelegate.java", + "//chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrDelegateFallback.java", + "//chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrFallbackUtils.java", + "//chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrIntentDelegateFallback.java", + "//chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrDelegateProvider.java", + "//chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrDelegateProviderFallback.java", + "//chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrIntentDelegate.java", + "//chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrModeObserver.java", + "//chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrModuleProvider.java", +]
diff --git a/chrome/android/features/vr/vr_module_tmpl.gni b/chrome/android/features/vr/vr_module_tmpl.gni index e6f9522..926ca2e0 100644 --- a/chrome/android/features/vr/vr_module_tmpl.gni +++ b/chrome/android/features/vr/vr_module_tmpl.gni
@@ -19,7 +19,7 @@ _manifest = "$target_gen_dir/$target_name/AndroidManifest.xml" _manifest_target = "${target_name}__manifest" jinja_template(_manifest_target) { - input = "//chrome/android/features/vr/AndroidManifest.xml" + input = "//chrome/android/features/vr/java/AndroidManifest.xml" output = _manifest variables = [ "target_sdk_version=$android_sdk_version", @@ -39,7 +39,7 @@ android_manifest = _manifest android_manifest_dep = ":${_manifest_target}" deps = [ - "//chrome/browser/android/vr:java", + "//chrome/android/features/vr:java", ] proguard_enabled = !is_java_debug if (!defined(invoker.uncompress_shared_libraries)) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java index 60cbe63..ffa6962 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeFeatureList.java
@@ -193,8 +193,6 @@ public static final String CLEAR_OLD_BROWSING_DATA = "ClearOldBrowsingData"; public static final String CLIPBOARD_CONTENT_SETTING = "ClipboardContentSetting"; public static final String COMMAND_LINE_ON_NON_ROOTED = "CommandLineOnNonRooted"; - public static final String CONTENT_SUGGESTIONS_FAVICONS_FROM_NEW_SERVER = - "ContentSuggestionsFaviconsFromNewServer"; public static final String CONTENT_SUGGESTIONS_NOTIFICATIONS = "ContentSuggestionsNotifications"; public static final String CONTENT_SUGGESTIONS_SCROLL_TO_LOAD =
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java index dccd87b..38139214 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
@@ -2282,7 +2282,7 @@ // If the current active tab is showing a tab modal dialog, an app menu shouldn't be shown // in any cases, e.g. when a hardware menu button is clicked. Tab tab = getActivityTab(); - if (TabModalPresenter.isDialogShowing(tab)) return false; + if (tab != null && TabModalPresenter.isDialogShowing(tab)) return false; return super.shouldShowAppMenu(); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiController.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiController.java index cf11637..93a90e2 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiController.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiController.java
@@ -8,7 +8,6 @@ import android.support.annotation.Nullable; -import org.chromium.base.Callback; import org.chromium.base.annotations.CalledByNative; import org.chromium.base.annotations.JNINamespace; import org.chromium.base.task.PostTask; @@ -17,7 +16,6 @@ import org.chromium.chrome.browser.ChromeActivity; import org.chromium.chrome.browser.autofill_assistant.carousel.AssistantCarouselModel; import org.chromium.chrome.browser.autofill_assistant.carousel.AssistantChip; -import org.chromium.chrome.browser.autofill_assistant.carousel.AssistantChipType; import org.chromium.chrome.browser.autofill_assistant.metrics.DropOutReason; import org.chromium.chrome.browser.customtabs.CustomTabActivity; import org.chromium.chrome.browser.snackbar.SnackbarManager.SnackbarController; @@ -208,38 +206,78 @@ } @CalledByNative - private void setSuggestions(int[] types, String[] texts) { - assert types.length == texts.length; - setChips(getModel().getSuggestionsModel(), - buildChips(types, texts, this::safeNativeOnSuggestionSelected)); - } - - private List<AssistantChip> buildChips( - int[] types, String[] texts, Callback<Integer> callback) { + private void setSuggestions(String[] texts) { List<AssistantChip> chips = new ArrayList<>(); - for (int i = 0; i < types.length; i++) { - int index = i; - int type = types[i]; - chips.add(new AssistantChip(type, texts[i], () -> callback.onResult(index))); + for (int i = 0; i < texts.length; i++) { + final int suggestionIndex = i; + chips.add(new AssistantChip(AssistantChip.Type.CHIP_ASSISTIVE, texts[i], + () -> safeNativeOnSuggestionSelected(suggestionIndex))); } - return chips; + AssistantCarouselModel model = getModel().getSuggestionsModel(); + model.set(ALIGNMENT, AssistantCarouselModel.Alignment.START); + setChips(model, chips); } - @AssistantCarouselModel.Alignment - private int computeAlignment(List<AssistantChip> chips) { - int alignment = AssistantCarouselModel.Alignment.START; - for (AssistantChip chip : chips) { - if (chip.getType() != AssistantChipType.CHIP_ASSISTIVE) { - alignment = chips.size() == 1 ? AssistantCarouselModel.Alignment.CENTER - : AssistantCarouselModel.Alignment.END; - } - } - return alignment; + @CalledByNative + private void clearActions() { + getModel().getActionsModel().getChipsModel().set(Collections.emptyList()); + } + + /** Creates an empty list of chips. */ + @CalledByNative + private static List<AssistantChip> createChipList() { + return new ArrayList<AssistantChip>(); + } + + /** + * Adds an action button to the chip list, which executes the action {@code actionIndex}. + */ + @CalledByNative + private void addActionButton(List<AssistantChip> chips, String text, int actionIndex) { + chips.add(new AssistantChip(AssistantChip.Type.BUTTON_HAIRLINE, text, + () -> safeNativeOnActionSelected(actionIndex))); + } + + /** + * Adds a highlighted action button to the chip list, which executes the action {@code + * actionIndex}. + */ + @CalledByNative + private void addHighlightedActionButton( + List<AssistantChip> chips, String text, int actionIndex) { + chips.add(new AssistantChip(AssistantChip.Type.BUTTON_FILLED_BLUE, text, + () -> safeNativeOnActionSelected(actionIndex))); + } + + /** + * Adds a cancel action button to the chip list, which shows the snackbar and then executes + * {@code actionIndex}, or shuts down Autofill Assistant if {@code actionIndex} is {@code -1}. + */ + @CalledByNative + private void addCancelButton(List<AssistantChip> chips, String text, int actionIndex) { + chips.add(new AssistantChip(AssistantChip.Type.BUTTON_HAIRLINE, text, + () -> safeNativeOnCancelButtonClicked(actionIndex))); + } + + /** + * Adds a close action button to the chip list, which shuts down Autofill Assistant. + */ + @CalledByNative + private void addCloseButton(List<AssistantChip> chips, String text) { + chips.add(new AssistantChip( + AssistantChip.Type.BUTTON_HAIRLINE, text, this::safeNativeOnCloseButtonClicked)); + } + + @CalledByNative + private void setActions(List<AssistantChip> chips) { + AssistantCarouselModel model = getModel().getActionsModel(); + model.set(ALIGNMENT, + chips.size() == 1 ? AssistantCarouselModel.Alignment.CENTER + : AssistantCarouselModel.Alignment.END); + setChips(model, chips); } private void setChips(AssistantCarouselModel model, List<AssistantChip> chips) { - model.set(ALIGNMENT, computeAlignment(chips)); - // We apply the minimum set of operations on the current chips to transform it in the target // list of chips. When testing for chip equivalence, we only compare their type and text but // all substitutions will still be applied so we are sure we display the given {@code chips} @@ -248,33 +286,6 @@ (a, b) -> a.getType() == b.getType() && a.getText().equals(b.getText())); } - @CalledByNative - private void setActions( - int[] types, String[] texts, boolean isStopping, boolean isShowingPaymentRequest) { - AssistantCarouselModel actionsModel = getModel().getActionsModel(); - if (isShowingPaymentRequest) { - actionsModel.getChipsModel().set(Collections.emptyList()); - return; - } - - assert types.length == texts.length; - List<AssistantChip> chips = buildChips(types, texts, this::safeNativeOnActionSelected); - addCancelOrCloseButton(chips, isStopping); - setChips(actionsModel, chips); - } - - private void addCancelOrCloseButton(List<AssistantChip> chips, boolean isStopping) { - int textResId = isStopping ? R.string.close : R.string.cancel; - chips.add(new AssistantChip(AssistantChipType.BUTTON_HAIRLINE, - mActivity.getResources().getString(textResId), () -> { - if (isStopping) { - safeNativeOnCloseButtonClicked(); - } else { - safeNativeOnCancelButtonClicked(); - } - })); - } - // Native methods. private void safeSnackbarResult(boolean undo) { if (mNativeUiController != 0) nativeSnackbarResult(mNativeUiController, undo); @@ -302,10 +313,10 @@ } private native void nativeOnActionSelected(long nativeUiControllerAndroid, int index); - private void safeNativeOnCancelButtonClicked() { - if (mNativeUiController != 0) nativeOnCancelButtonClicked(mNativeUiController); + private void safeNativeOnCancelButtonClicked(int index) { + if (mNativeUiController != 0) nativeOnCancelButtonClicked(mNativeUiController, index); } - private native void nativeOnCancelButtonClicked(long nativeUiControllerAndroid); + private native void nativeOnCancelButtonClicked(long nativeUiControllerAndroid, int index); private void safeNativeOnCloseButtonClicked() { if (mNativeUiController != 0) nativeOnCloseButtonClicked(mNativeUiController);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/carousel/AssistantChip.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/carousel/AssistantChip.java index daeda5d..31af6008 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/carousel/AssistantChip.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/carousel/AssistantChip.java
@@ -4,15 +4,28 @@ package org.chromium.chrome.browser.autofill_assistant.carousel; +import android.support.annotation.IntDef; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + /** * A chip to display to the user. */ public class AssistantChip { - private final @AssistantChipType int mType; + @IntDef({Type.CHIP_ASSISTIVE, Type.BUTTON_FILLED_BLUE, Type.BUTTON_HAIRLINE}) + @Retention(RetentionPolicy.SOURCE) + public @interface Type { + int CHIP_ASSISTIVE = 0; + int BUTTON_FILLED_BLUE = 1; + int BUTTON_HAIRLINE = 2; + } + + private final @Type int mType; private final String mText; private final Runnable mSelectedListener; - public AssistantChip(@AssistantChipType int type, String text, Runnable selectedListener) { + public AssistantChip(@Type int type, String text, Runnable selectedListener) { mType = type; mText = text; mSelectedListener = selectedListener;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/carousel/AssistantChipViewHolder.java b/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/carousel/AssistantChipViewHolder.java index 3bb9537e..6e8bda68 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/carousel/AssistantChipViewHolder.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/autofill_assistant/carousel/AssistantChipViewHolder.java
@@ -28,13 +28,13 @@ int resId = -1; switch (viewType) { // TODO: inflate normal chrome buttons instead. - case AssistantChipType.CHIP_ASSISTIVE: + case AssistantChip.Type.CHIP_ASSISTIVE: resId = R.layout.autofill_assistant_chip_assistive; break; - case AssistantChipType.BUTTON_FILLED_BLUE: + case AssistantChip.Type.BUTTON_FILLED_BLUE: resId = R.layout.autofill_assistant_button_filled; break; - case AssistantChipType.BUTTON_HAIRLINE: + case AssistantChip.Type.BUTTON_HAIRLINE: resId = R.layout.autofill_assistant_button_hairline; break; default:
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetsConfig.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetsConfig.java index e61d16de..ea85bb7 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetsConfig.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/snippets/SnippetsConfig.java
@@ -16,9 +16,4 @@ public static boolean isIncreasedCardVisibilityEnabled() { return ChromeFeatureList.isEnabled(ChromeFeatureList.NTP_SNIPPETS_INCREASED_VISIBILITY); } - - public static boolean isFaviconsFromNewServerEnabled() { - return ChromeFeatureList.isEnabled( - ChromeFeatureList.CONTENT_SUGGESTIONS_FAVICONS_FROM_NEW_SERVER); - } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabWebContentsDelegateAndroid.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabWebContentsDelegateAndroid.java index b861d3b..9ea3e0b 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tab/TabWebContentsDelegateAndroid.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/TabWebContentsDelegateAndroid.java
@@ -14,7 +14,7 @@ import android.media.AudioManager; import android.os.Build; import android.os.Handler; -import android.util.Pair; +import android.support.v4.util.ArrayMap; import android.view.KeyEvent; import android.view.View; @@ -79,6 +79,8 @@ private final Runnable mCloseContentsRunnable; protected final Tab mTab; + private final ArrayMap<WebContents, String> mWebContentsUrlMapping = new ArrayMap<>(); + protected Handler mHandler; private FindResultListener mFindResultListener; private FindMatchRectsListener mFindMatchRectsListener; @@ -255,8 +257,12 @@ openerRenderFrameId, frameName, targetUrl, newWebContents); } // The URL can't be taken from the WebContents if it's paused. Save it for later. - assert mWebContentsUrlMapping == null; - mWebContentsUrlMapping = Pair.create(newWebContents, targetUrl); + // TODO(crbug.com/758186): Remove after debugging. + if (mWebContentsUrlMapping.containsKey(newWebContents)) { + Log.e(TAG, "Duplicate mWebContentsUrlMapping key"); + } + assert !mWebContentsUrlMapping.containsKey(newWebContents); + mWebContentsUrlMapping.put(newWebContents, targetUrl); // TODO(dfalcantara): Re-remove this once crbug.com/508366 is fixed. TabCreator tabCreator = mTab.getActivity().getTabCreator(mTab.isIncognito()); @@ -292,8 +298,6 @@ mTab.openNewTab(url, null, extraHeaders, postData, disposition, true, isRendererInitiated); } - private Pair<WebContents, String> mWebContentsUrlMapping; - protected TabModel getTabModel() { // TODO(dfalcantara): Remove this when DocumentActivity.getTabModelSelector() // can return a TabModelSelector that activateContents() can use. @@ -311,14 +315,17 @@ @CalledByNative public boolean addNewContents(WebContents sourceWebContents, WebContents webContents, int disposition, Rect initialPosition, boolean userGesture) { - assert mWebContentsUrlMapping.first == webContents; + // TODO(crbug.com/758186): Remove after debugging. + if (!mWebContentsUrlMapping.containsKey(webContents)) { + Log.e(TAG, "Missing mWebContentsUrlMapping key"); + } + assert mWebContentsUrlMapping.containsKey(webContents); TabCreator tabCreator = mTab.getActivity().getTabCreator(mTab.isIncognito()); assert tabCreator != null; // Grab the URL, which might not be available via the Tab. - String url = mWebContentsUrlMapping.second; - mWebContentsUrlMapping = null; + String url = mWebContentsUrlMapping.remove(webContents); // Skip opening a new Tab if it doesn't make sense. if (mTab.isClosing()) return false;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tasks/tab_list_ui/GridTabSwitcherCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/tasks/tab_list_ui/GridTabSwitcherCoordinator.java index 5778f4c..15d53d5 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tasks/tab_list_ui/GridTabSwitcherCoordinator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tasks/tab_list_ui/GridTabSwitcherCoordinator.java
@@ -21,7 +21,8 @@ /** * Parent coordinator that is responsible for showing a grid of tabs for the main TabSwitcher UI. */ -public class GridTabSwitcherCoordinator implements Destroyable { +public class GridTabSwitcherCoordinator + implements Destroyable, GridTabSwitcherMediator.ResetHandler { private final PropertyModelChangeProcessor mContainerViewChangeProcessor; private final ActivityLifecycleDispatcher mLifecycleDispatcher; private final TabListCoordinator mTabGridCoordinator; @@ -58,7 +59,8 @@ * Reset the tab grid with the given {@link TabModel}. Can be null. * @param tabModel The current {@link TabModel} to show the tabs for in the grid. */ - void resetWithTabModel(TabModel tabModel) { + @Override + public void resetWithTabModel(TabModel tabModel) { mTabGridCoordinator.resetWithTabModel(tabModel); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tasks/tab_list_ui/GridTabSwitcherMediator.java b/chrome/android/java/src/org/chromium/chrome/browser/tasks/tab_list_ui/GridTabSwitcherMediator.java index 921a884..253e330 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tasks/tab_list_ui/GridTabSwitcherMediator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tasks/tab_list_ui/GridTabSwitcherMediator.java
@@ -21,6 +21,7 @@ import org.chromium.chrome.browser.tabmodel.TabModelSelector; import org.chromium.chrome.browser.tabmodel.TabModelSelectorObserver; import org.chromium.chrome.browser.tabmodel.TabModelSelectorTabModelObserver; +import org.chromium.chrome.browser.tabmodel.TabSelectionType; import org.chromium.ui.modelutil.PropertyModel; import java.util.ArrayList; @@ -34,9 +35,9 @@ implements OverviewModeController, TabListRecyclerView.VisibilityListener { // This should be the same as TabListCoordinator.GRID_LAYOUT_SPAN_COUNT for the selected tab // to be on the 2nd row. - private static final int INITIAL_SCROLL_INDEX_OFFSET = 2; + static final int INITIAL_SCROLL_INDEX_OFFSET = 2; - private final GridTabSwitcherCoordinator mCoordinator; + private final ResetHandler mResetHandler; private final PropertyModel mContainerViewModel; private final TabModelSelector mTabModelSelector; private final TabModelSelectorTabModelObserver mTabModelObserver; @@ -62,23 +63,29 @@ }; /** - * In cases where a didSelectTab was due to closing a tab or switching models with a toggle, + * In cases where a didSelectTab was due to switching models with a toggle, * we don't change tab grid visibility. */ private boolean mShouldIgnoreNextSelect; /** + * Interface to delegate resetting the tab grid. + */ + interface ResetHandler { + void resetWithTabModel(TabModel tabModel); + } + + /** * Basic constructor for the Mediator. - * @param coordinator The {@link GridTabSwitcherCoordinator} that owns this Mediator. + * @param resetHandler The {@link ResetHandler} that handles reset for this Mediator. * @param containerViewModel The {@link PropertyModel} to keep state on the View containing the * grid. * @param tabModelSelector {@link TabModelSelector} to observer for model and selection changes. * @param fullscreenManager {@link FullscreenManager} to use. */ - GridTabSwitcherMediator(GridTabSwitcherCoordinator coordinator, - PropertyModel containerViewModel, TabModelSelector tabModelSelector, - ChromeFullscreenManager fullscreenManager) { - mCoordinator = coordinator; + GridTabSwitcherMediator(ResetHandler resetHandler, PropertyModel containerViewModel, + TabModelSelector tabModelSelector, ChromeFullscreenManager fullscreenManager) { + mResetHandler = resetHandler; mContainerViewModel = containerViewModel; mTabModelSelector = tabModelSelector; mFullscreenManager = fullscreenManager; @@ -87,36 +94,22 @@ @Override public void onTabModelSelected(TabModel newModel, TabModel oldModel) { mShouldIgnoreNextSelect = true; - mCoordinator.resetWithTabModel(newModel); + mResetHandler.resetWithTabModel(newModel); mContainerViewModel.set(IS_INCOGNITO, newModel.isIncognito()); } }; mTabModelSelector.addObserver(mTabModelSelectorObserver); - mTabModelSelector.setOverviewModeBehavior(this); - mTabModelObserver = new TabModelSelectorTabModelObserver(mTabModelSelector) { @Override public void didSelectTab(Tab tab, int type, int lastId) { - if (mShouldIgnoreNextSelect) { + if (type == TabSelectionType.FROM_CLOSE || mShouldIgnoreNextSelect) { mShouldIgnoreNextSelect = false; return; } setVisibility(false); } - - @Override - public void willCloseTab(Tab tab, boolean animate) { - // Needed to handle the extra select for closing the currently selected tab. - mShouldIgnoreNextSelect = true; - } - - @Override - public void didCloseTab(int tabId, boolean incognito) { - // Handles most of the tab closes. - mShouldIgnoreNextSelect = true; - } }; mFullscreenManager.addListener(mFullscreenListener); @@ -131,7 +124,7 @@ private void setVisibility(boolean isVisible) { if (isVisible) { - mCoordinator.resetWithTabModel(mTabModelSelector.getCurrentModel()); + mResetHandler.resetWithTabModel(mTabModelSelector.getCurrentModel()); int initialPosition = Math.max( mTabModelSelector.getCurrentModel().index() - INITIAL_SCROLL_INDEX_OFFSET, 0); mContainerViewModel.set(INITIAL_SCROLL_INDEX, initialPosition); @@ -170,7 +163,7 @@ } @Override - public void startedShowing() { + public void startedShowing(boolean isAnimating) { for (OverviewModeObserver observer : mObservers) { observer.onOverviewModeStartedShowing(true); } @@ -184,7 +177,7 @@ } @Override - public void startedHiding() { + public void startedHiding(boolean isAnimating) { for (OverviewModeObserver observer : mObservers) { observer.onOverviewModeStartedHiding(true, false); } @@ -192,7 +185,7 @@ @Override public void finishedHiding() { - mCoordinator.resetWithTabModel(null); + mResetHandler.resetWithTabModel(null); mContainerViewModel.set(INITIAL_SCROLL_INDEX, 0); for (OverviewModeObserver observer : mObservers) { observer.onOverviewModeFinishedHiding();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tasks/tab_list_ui/TabListRecyclerView.java b/chrome/android/java/src/org/chromium/chrome/browser/tasks/tab_list_ui/TabListRecyclerView.java index c1b613df..f4cfc6d6 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tasks/tab_list_ui/TabListRecyclerView.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tasks/tab_list_ui/TabListRecyclerView.java
@@ -27,8 +27,9 @@ interface VisibilityListener { /** * Called before the animation to show the tab list has started. + * @param isAnimating Whether visibility is changing with animation */ - void startedShowing(); + void startedShowing(boolean isAnimating); /** * Called when the animation to show the tab list is finished. @@ -37,8 +38,9 @@ /** * Called before the animation to hide the tab list has started. + * @param isAnimating Whether visibility is changing with animation */ - void startedHiding(); + void startedHiding(boolean isAnimating); /** * Called when the animation to show the tab list is finished. @@ -70,7 +72,7 @@ * @param animate Whether the visibility change should be animated. */ void startShowing(boolean animate) { - mListener.startedShowing(); + mListener.startedShowing(animate); cancelAllAnimations(); setAlpha(0); setVisibility(View.VISIBLE); @@ -92,7 +94,7 @@ * @param animate Whether the visibility change should be animated. */ void startHiding(boolean animate) { - mListener.startedHiding(); + mListener.startedHiding(animate); cancelAllAnimations(); mFadeOutAnimator = ObjectAnimator.ofFloat(this, View.ALPHA, 0); mFadeOutAnimator.setInterpolator(BakedBezierInterpolator.FADE_OUT_CURVE);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/vr/SilenceLintErrors.java b/chrome/android/java/src/org/chromium/chrome/browser/vr/SilenceLintErrors.java deleted file mode 100644 index 099ee54..0000000 --- a/chrome/android/java/src/org/chromium/chrome/browser/vr/SilenceLintErrors.java +++ /dev/null
@@ -1,18 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package org.chromium.chrome.browser.vr; - -import org.chromium.chrome.R; - -// TODO(crbug.com/870056): This class purely exists to silence lint errors. Remove this class once -// we have moved resources into VR DFM. -/* package */ class SilenceLintErrors { - private int[] mRes = new int[] { - R.anim.stay_hidden, - org.chromium.chrome.vr.pub.R.drawable.vr_services, - }; - - private SilenceLintErrors() {} -}
diff --git a/chrome/android/java/strings/android_chrome_vr_strings.grd b/chrome/android/java/strings/android_chrome_vr_strings.grd deleted file mode 100644 index 58f81820..0000000 --- a/chrome/android/java/strings/android_chrome_vr_strings.grd +++ /dev/null
@@ -1,130 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- android_chrome_strings.grd contains strings for VR DFM of Chrome for Android. --> -<grit current_release="1" latest_public_release="0" output_all_resource_defines="false"> - <outputs> - <output filename="values-am/android_chrome_vr_strings.xml" lang="am" type="android" /> - <output filename="values-ar/android_chrome_vr_strings.xml" lang="ar" type="android" /> - <output filename="values-bg/android_chrome_vr_strings.xml" lang="bg" type="android" /> - <output filename="values-ca/android_chrome_vr_strings.xml" lang="ca" type="android" /> - <output filename="values-cs/android_chrome_vr_strings.xml" lang="cs" type="android" /> - <output filename="values-da/android_chrome_vr_strings.xml" lang="da" type="android" /> - <output filename="values-de/android_chrome_vr_strings.xml" lang="de" type="android" /> - <output filename="values-el/android_chrome_vr_strings.xml" lang="el" type="android" /> - <output filename="values/android_chrome_vr_strings.xml" lang="en" type="android" /> - <output filename="values-en-rGB/android_chrome_vr_strings.xml" lang="en-GB" type="android" /> - <output filename="values-es/android_chrome_vr_strings.xml" lang="es" type="android" /> - <output filename="values-es-rUS/android_chrome_vr_strings.xml" lang="es-419" type="android" /> - <output filename="values-fa/android_chrome_vr_strings.xml" lang="fa" type="android" /> - <output filename="values-fi/android_chrome_vr_strings.xml" lang="fi" type="android" /> - <output filename="values-tl/android_chrome_vr_strings.xml" lang="fil" type="android" /> - <output filename="values-fr/android_chrome_vr_strings.xml" lang="fr" type="android" /> - <output filename="values-hi/android_chrome_vr_strings.xml" lang="hi" type="android" /> - <output filename="values-hr/android_chrome_vr_strings.xml" lang="hr" type="android" /> - <output filename="values-hu/android_chrome_vr_strings.xml" lang="hu" type="android" /> - <output filename="values-in/android_chrome_vr_strings.xml" lang="id" type="android" /> - <output filename="values-it/android_chrome_vr_strings.xml" lang="it" type="android" /> - <output filename="values-iw/android_chrome_vr_strings.xml" lang="iw" type="android" /> - <output filename="values-ja/android_chrome_vr_strings.xml" lang="ja" type="android" /> - <output filename="values-ko/android_chrome_vr_strings.xml" lang="ko" type="android" /> - <output filename="values-lt/android_chrome_vr_strings.xml" lang="lt" type="android" /> - <output filename="values-lv/android_chrome_vr_strings.xml" lang="lv" type="android" /> - <output filename="values-nl/android_chrome_vr_strings.xml" lang="nl" type="android" /> - <output filename="values-nb/android_chrome_vr_strings.xml" lang="no" type="android" /> - <output filename="values-pl/android_chrome_vr_strings.xml" lang="pl" type="android" /> - <output filename="values-pt-rBR/android_chrome_vr_strings.xml" lang="pt-BR" type="android" /> - <output filename="values-pt-rPT/android_chrome_vr_strings.xml" lang="pt-PT" type="android" /> - <output filename="values-ro/android_chrome_vr_strings.xml" lang="ro" type="android" /> - <output filename="values-ru/android_chrome_vr_strings.xml" lang="ru" type="android" /> - <output filename="values-sk/android_chrome_vr_strings.xml" lang="sk" type="android" /> - <output filename="values-sl/android_chrome_vr_strings.xml" lang="sl" type="android" /> - <output filename="values-sr/android_chrome_vr_strings.xml" lang="sr" type="android" /> - <output filename="values-sv/android_chrome_vr_strings.xml" lang="sv" type="android" /> - <output filename="values-sw/android_chrome_vr_strings.xml" lang="sw" type="android" /> - <output filename="values-th/android_chrome_vr_strings.xml" lang="th" type="android" /> - <output filename="values-tr/android_chrome_vr_strings.xml" lang="tr" type="android" /> - <output filename="values-uk/android_chrome_vr_strings.xml" lang="uk" type="android" /> - <output filename="values-vi/android_chrome_vr_strings.xml" lang="vi" type="android" /> - <output filename="values-zh-rCN/android_chrome_vr_strings.xml" lang="zh-CN" type="android" /> - <output filename="values-zh-rTW/android_chrome_vr_strings.xml" lang="zh-TW" type="android" /> - </outputs> - <translations> - <file lang="am" path="vr_translations/android_chrome_vr_strings_am.xtb" /> - <file lang="ar" path="vr_translations/android_chrome_vr_strings_ar.xtb" /> - <file lang="bg" path="vr_translations/android_chrome_vr_strings_bg.xtb" /> - <file lang="bn" path="vr_translations/android_chrome_vr_strings_bn.xtb" /> - <file lang="ca" path="vr_translations/android_chrome_vr_strings_ca.xtb" /> - <file lang="cs" path="vr_translations/android_chrome_vr_strings_cs.xtb" /> - <file lang="da" path="vr_translations/android_chrome_vr_strings_da.xtb" /> - <file lang="de" path="vr_translations/android_chrome_vr_strings_de.xtb" /> - <file lang="el" path="vr_translations/android_chrome_vr_strings_el.xtb" /> - <file lang="en-GB" path="vr_translations/android_chrome_vr_strings_en-GB.xtb" /> - <file lang="es" path="vr_translations/android_chrome_vr_strings_es.xtb" /> - <file lang="es-419" path="vr_translations/android_chrome_vr_strings_es-419.xtb" /> - <file lang="et" path="vr_translations/android_chrome_vr_strings_et.xtb" /> - <file lang="fa" path="vr_translations/android_chrome_vr_strings_fa.xtb" /> - <file lang="fi" path="vr_translations/android_chrome_vr_strings_fi.xtb" /> - <file lang="fil" path="vr_translations/android_chrome_vr_strings_fil.xtb" /> - <file lang="fr" path="vr_translations/android_chrome_vr_strings_fr.xtb" /> - <file lang="gu" path="vr_translations/android_chrome_vr_strings_gu.xtb" /> - <file lang="hi" path="vr_translations/android_chrome_vr_strings_hi.xtb" /> - <file lang="hr" path="vr_translations/android_chrome_vr_strings_hr.xtb" /> - <file lang="hu" path="vr_translations/android_chrome_vr_strings_hu.xtb" /> - <file lang="id" path="vr_translations/android_chrome_vr_strings_id.xtb" /> - <file lang="it" path="vr_translations/android_chrome_vr_strings_it.xtb" /> - <file lang="iw" path="vr_translations/android_chrome_vr_strings_iw.xtb" /> - <file lang="ja" path="vr_translations/android_chrome_vr_strings_ja.xtb" /> - <file lang="ko" path="vr_translations/android_chrome_vr_strings_ko.xtb" /> - <file lang="kn" path="vr_translations/android_chrome_vr_strings_kn.xtb" /> - <file lang="lt" path="vr_translations/android_chrome_vr_strings_lt.xtb" /> - <file lang="lv" path="vr_translations/android_chrome_vr_strings_lv.xtb" /> - <file lang="ml" path="vr_translations/android_chrome_vr_strings_ml.xtb" /> - <file lang="mr" path="vr_translations/android_chrome_vr_strings_mr.xtb" /> - <file lang="ms" path="vr_translations/android_chrome_vr_strings_ms.xtb" /> - <file lang="nl" path="vr_translations/android_chrome_vr_strings_nl.xtb" /> - <file lang="no" path="vr_translations/android_chrome_vr_strings_no.xtb" /> - <file lang="pl" path="vr_translations/android_chrome_vr_strings_pl.xtb" /> - <file lang="pt-BR" path="vr_translations/android_chrome_vr_strings_pt-BR.xtb" /> - <file lang="pt-PT" path="vr_translations/android_chrome_vr_strings_pt-PT.xtb" /> - <file lang="ro" path="vr_translations/android_chrome_vr_strings_ro.xtb" /> - <file lang="ru" path="vr_translations/android_chrome_vr_strings_ru.xtb" /> - <file lang="sk" path="vr_translations/android_chrome_vr_strings_sk.xtb" /> - <file lang="sl" path="vr_translations/android_chrome_vr_strings_sl.xtb" /> - <file lang="sr" path="vr_translations/android_chrome_vr_strings_sr.xtb" /> - <file lang="sv" path="vr_translations/android_chrome_vr_strings_sv.xtb" /> - <file lang="sw" path="vr_translations/android_chrome_vr_strings_sw.xtb" /> - <file lang="ta" path="vr_translations/android_chrome_vr_strings_ta.xtb" /> - <file lang="te" path="vr_translations/android_chrome_vr_strings_te.xtb" /> - <file lang="th" path="vr_translations/android_chrome_vr_strings_th.xtb" /> - <file lang="tr" path="vr_translations/android_chrome_vr_strings_tr.xtb" /> - <file lang="uk" path="vr_translations/android_chrome_vr_strings_uk.xtb" /> - <file lang="vi" path="vr_translations/android_chrome_vr_strings_vi.xtb" /> - <file lang="zh-CN" path="vr_translations/android_chrome_vr_strings_zh-CN.xtb" /> - <file lang="zh-TW" path="vr_translations/android_chrome_vr_strings_zh-TW.xtb" /> - </translations> - <release allow_pseudo="false" seq="1"> - <messages fallback_to_english="true"> - <!-- Chrome VR feedback infobar --> - <message name="IDS_VR_SHELL_FEEDBACK_INFOBAR_DESCRIPTION" desc="Description for infobar prompting the user for feedback on their VR browsing experience."> - Help improve the VR experience in Chrome - </message> - <message name="IDS_VR_SHELL_FEEDBACK_INFOBAR_FEEDBACK_BUTTON" desc="Brief button text asking the user to provide feedback in the VR feedback infobar."> - Provide feedback - </message> - - <!-- VR services check infobar --> - <message name="IDS_VR_SERVICES_CHECK_INFOBAR_INSTALL_TEXT" desc="Text to be displayed in the VR Services check infobar. When a WebVR page is loaded if the VR services that are needed to display WebVR don't exist an infobar will be shown to the user prompting them to install VR services."> - To view virtual reality content, install Google VR Services - </message> - <message name="IDS_VR_SERVICES_CHECK_INFOBAR_UPDATE_TEXT" desc="Text to be displayed in the VR Services check infobar. When a WebVR page is loaded if the VR services that are needed to display WebVR are out of date an infobar will be shown to the user prompting them to update VR services."> - To view virtual reality content, update Google VR Services - </message> - <message name="IDS_VR_SERVICES_CHECK_INFOBAR_INSTALL_BUTTON" desc="Text to be displayed in the VR Services check infobar confirm button for installing."> - Install - </message> - <message name="IDS_VR_SERVICES_CHECK_INFOBAR_UPDATE_BUTTON" desc="Text to be displayed in the VR Services check infobar confirm button for updating."> - Update - </message> - </messages> - </release> -</grit> -
diff --git a/chrome/android/java_sources.gni b/chrome/android/java_sources.gni index dce526c..736772b 100644 --- a/chrome/android/java_sources.gni +++ b/chrome/android/java_sources.gni
@@ -1688,16 +1688,6 @@ "java/src/org/chromium/chrome/browser/util/ViewUtils.java", "java/src/org/chromium/chrome/browser/vr/ArDelegate.java", "java/src/org/chromium/chrome/browser/vr/ArDelegateProvider.java", - "java/src/org/chromium/chrome/browser/vr/OnExitVrRequestListener.java", - "java/src/org/chromium/chrome/browser/vr/VrDelegate.java", - "java/src/org/chromium/chrome/browser/vr/VrDelegateFallback.java", - "java/src/org/chromium/chrome/browser/vr/VrFallbackUtils.java", - "java/src/org/chromium/chrome/browser/vr/VrIntentDelegateFallback.java", - "java/src/org/chromium/chrome/browser/vr/VrDelegateProvider.java", - "java/src/org/chromium/chrome/browser/vr/VrDelegateProviderFallback.java", - "java/src/org/chromium/chrome/browser/vr/VrIntentDelegate.java", - "java/src/org/chromium/chrome/browser/vr/VrModeObserver.java", - "java/src/org/chromium/chrome/browser/vr/VrModuleProvider.java", "java/src/org/chromium/chrome/browser/webapps/ActivityAssigner.java", "java/src/org/chromium/chrome/browser/webapps/AddToHomescreenDialog.java", "java/src/org/chromium/chrome/browser/webapps/AddToHomescreenManager.java", @@ -1868,10 +1858,7 @@ ] if (enable_vr) { - chrome_java_sources += [ - "java/src/org/chromium/chrome/browser/component_updater/VrAssetsComponentInstaller.java", - "java/src/org/chromium/chrome/browser/vr/SilenceLintErrors.java", - ] + chrome_java_sources += [ "java/src/org/chromium/chrome/browser/component_updater/VrAssetsComponentInstaller.java" ] } chrome_test_java_sources = [ @@ -2330,6 +2317,7 @@ "javatests/src/org/chromium/chrome/browser/tabmodel/UndoTabModelTest.java", "javatests/src/org/chromium/chrome/browser/tabmodel/document/MockDocumentTabModel.java", "javatests/src/org/chromium/chrome/browser/tasks/tab_list_ui/TabListViewHolderTest.java", + "javatests/src/org/chromium/chrome/browser/tasks/tab_list_ui/TabGridContainerViewBinderTest.java", "javatests/src/org/chromium/chrome/browser/tasks/tab_list_ui/TestRecyclerViewSimpleViewBinder.java", "javatests/src/org/chromium/chrome/browser/test/ChromeBrowserTestRule.java", "javatests/src/org/chromium/chrome/browser/test/ClearAppDataTestRule.java", @@ -2547,6 +2535,7 @@ "junit/src/org/chromium/chrome/browser/tab/TabAttributesTest.java", "junit/src/org/chromium/chrome/browser/tabmodel/TabPersistentStoreUnitTest.java", "junit/src/org/chromium/chrome/browser/tabstate/TabStateUnitTest.java", + "junit/src/org/chromium/chrome/browser/tasks/tab_list_ui/GridTabSwitcherMediatorUnitTest.java", "junit/src/org/chromium/chrome/browser/tasks/tab_list_ui/TabListMediatorUnitTest.java", "junit/src/org/chromium/chrome/browser/toolbar/ToolbarSecurityIconTest.java", "junit/src/org/chromium/chrome/browser/usage_stats/EventTrackerTest.java",
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiTest.java index c98e4e7..0975817 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantUiTest.java
@@ -33,7 +33,6 @@ import org.chromium.chrome.browser.autofill_assistant.carousel.AssistantCarouselCoordinator; import org.chromium.chrome.browser.autofill_assistant.carousel.AssistantCarouselModel; import org.chromium.chrome.browser.autofill_assistant.carousel.AssistantChip; -import org.chromium.chrome.browser.autofill_assistant.carousel.AssistantChipType; import org.chromium.chrome.browser.autofill_assistant.details.AssistantDetails; import org.chromium.chrome.browser.autofill_assistant.details.AssistantDetailsModel; import org.chromium.chrome.browser.autofill_assistant.header.AssistantHeaderModel; @@ -182,8 +181,8 @@ AssistantCarouselCoordinator carouselCoordinator) { List<AssistantChip> chips = Arrays.asList( new AssistantChip( - AssistantChipType.CHIP_ASSISTIVE, "chip 0", () -> {/* do nothing */}), - new AssistantChip(AssistantChipType.CHIP_ASSISTIVE, "chip 1", mRunnableMock)); + AssistantChip.Type.CHIP_ASSISTIVE, "chip 0", () -> {/* do nothing */}), + new AssistantChip(AssistantChip.Type.CHIP_ASSISTIVE, "chip 1", mRunnableMock)); ThreadUtils.runOnUiThreadBlocking(() -> carouselModel.getChipsModel().set(chips)); RecyclerView chipsViewContainer = carouselCoordinator.getView(); Assert.assertEquals(2, chipsViewContainer.getAdapter().getItemCount());
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/invalidation/DelayedInvalidationsControllerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/invalidation/DelayedInvalidationsControllerTest.java index 432d437..573aff3a 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/invalidation/DelayedInvalidationsControllerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/invalidation/DelayedInvalidationsControllerTest.java
@@ -12,6 +12,7 @@ import android.support.test.filters.SmallTest; import android.support.test.rule.UiThreadTestRule; +import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Rule; @@ -75,6 +76,11 @@ setApplicationState(ActivityState.RESUMED); } + @After + public void tearDown() { + setApplicationState(ActivityState.DESTROYED); + } + private void setApplicationState(int newState) { ApplicationStatus.onStateChangeForTesting(mPlaceholderActivity, newState); }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabWindowManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabWindowManagerTest.java index 65e78d3a..af5e4757 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabWindowManagerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/TabWindowManagerTest.java
@@ -9,6 +9,7 @@ import android.support.test.filters.SmallTest; import android.support.test.rule.UiThreadTestRule; +import org.junit.After; import org.junit.Assert; import org.junit.Rule; import org.junit.Test; @@ -24,12 +25,16 @@ import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.chrome.test.util.browser.tabmodel.MockTabModelSelector; +import java.util.ArrayList; +import java.util.List; + /** * Test for {@link TabWindowManager} APIs. Makes sure the class handles multiple {@link Activity}s * requesting {@link TabModelSelector}s, {@link Activity}s getting destroyed, etc.. */ @RunWith(ChromeJUnit4ClassRunner.class) public class TabWindowManagerTest { + private List<Activity> mActivities = new ArrayList<>(); private final TabModelSelectorFactory mMockTabModelSelectorFactory = new TabModelSelectorFactory() { @Override @@ -41,16 +46,30 @@ private ChromeActivity buildActivity() { ChromeActivity activity = new CustomTabActivity(); + mActivities.add(activity); ApplicationStatus.onStateChangeForTesting(activity, ActivityState.CREATED); return activity; } + private void destroyActivity(Activity a) { + mActivities.remove(a); + ApplicationStatus.onStateChangeForTesting(a, ActivityState.DESTROYED); + } + private MockTabModelSelector requestSelector(ChromeActivity activity, int requestedIndex) { final TabWindowManager manager = TabWindowManager.getInstance(); manager.setTabModelSelectorFactory(mMockTabModelSelectorFactory); return (MockTabModelSelector) manager.requestSelector(activity, activity, requestedIndex); } + @After + public void tearDown() { + for (Activity a : mActivities) { + ApplicationStatus.onStateChangeForTesting(a, ActivityState.DESTROYED); + } + mActivities.clear(); + } + @Rule public UiThreadTestRule mRule = new UiThreadTestRule(); @@ -103,11 +122,13 @@ @UiThreadTest public void testTooManyActivities() { for (int i = 0; i < TabWindowManager.MAX_SIMULTANEOUS_SELECTORS; i++) { - Assert.assertNotNull("Could not build selector", requestSelector(buildActivity(), 0)); + ChromeActivity a = buildActivity(); + Assert.assertNotNull("Could not build selector", requestSelector(a, 0)); } - Assert.assertNull("Built selectors past the max number supported", - requestSelector(buildActivity(), 0)); + ChromeActivity activity = buildActivity(); + Assert.assertNull( + "Built selectors past the max number supported", requestSelector(activity, 0)); } /** @@ -176,7 +197,7 @@ Assert.assertNotNull("Was not able to build the TabModelSelector", selector0); Assert.assertEquals("Unexpected model index", 0, manager.getIndexForWindow(activity0)); - ApplicationStatus.onStateChangeForTesting(activity0, ActivityState.DESTROYED); + destroyActivity(activity0); Assert.assertEquals("Still found model", TabWindowManager.INVALID_WINDOW_INDEX, manager.getIndexForWindow(activity0)); @@ -199,7 +220,7 @@ Assert.assertNotNull("Was not able to build the TabModelSelector", selector0); Assert.assertEquals("Unexpected model index", 0, manager.getIndexForWindow(activity0)); - ApplicationStatus.onStateChangeForTesting(activity0, ActivityState.DESTROYED); + destroyActivity(activity0); Assert.assertEquals("Still found model", TabWindowManager.INVALID_WINDOW_INDEX, manager.getIndexForWindow(activity0)); @@ -235,7 +256,7 @@ Assert.assertEquals("Unexpected model index", 0, manager.getIndexForWindow(activity0)); Assert.assertEquals("Unexpected model index", 1, manager.getIndexForWindow(activity1)); - ApplicationStatus.onStateChangeForTesting(activity1, ActivityState.DESTROYED); + destroyActivity(activity1); Assert.assertEquals("Still found model", TabWindowManager.INVALID_WINDOW_INDEX, manager.getIndexForWindow(activity1));
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tasks/tab_list_ui/TabGridContainerViewBinderTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tasks/tab_list_ui/TabGridContainerViewBinderTest.java new file mode 100644 index 0000000..e7a544dc --- /dev/null +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tasks/tab_list_ui/TabGridContainerViewBinderTest.java
@@ -0,0 +1,251 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.tasks.tab_list_ui; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.instanceOf; +import static org.hamcrest.MatcherAssert.assertThat; + +import android.graphics.drawable.ColorDrawable; +import android.os.Build; +import android.support.test.annotation.UiThreadTest; +import android.support.test.filters.MediumTest; +import android.view.View; +import android.widget.FrameLayout; + +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.chromium.base.ApiCompatibilityUtils; +import org.chromium.base.ThreadUtils; +import org.chromium.base.test.util.CallbackHelper; +import org.chromium.chrome.R; +import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +import org.chromium.chrome.test.ui.DummyUiActivity; +import org.chromium.chrome.test.ui.DummyUiActivityTestCase; +import org.chromium.content_public.browser.test.util.Criteria; +import org.chromium.content_public.browser.test.util.CriteriaHelper; +import org.chromium.ui.modelutil.PropertyModel; +import org.chromium.ui.modelutil.PropertyModelChangeProcessor; + +/** + * Tests for {@link TabListRecyclerView} and {@link TabGridContainerViewBinder} + */ +@RunWith(ChromeJUnit4ClassRunner.class) +public class TabGridContainerViewBinderTest extends DummyUiActivityTestCase { + private static final int CONTAINER_HEIGHT = 56; + private TabGridContainerViewBinder mTabGridContainerViewHolder; + private PropertyModel mContainerModel; + private PropertyModelChangeProcessor mMCP; + private TabListRecyclerView mRecyclerView; + private CallbackHelper mStartedShowingCallback; + private CallbackHelper mFinishedShowingCallback; + private CallbackHelper mStartedHidingCallback; + private CallbackHelper mFinishedHidingCallback; + private boolean mIsAnimating; + + private TabListRecyclerView.VisibilityListener mMockVisibilityListener = + new TabListRecyclerView.VisibilityListener() { + @Override + public void startedShowing(boolean isAnimating) { + mStartedShowingCallback.notifyCalled(); + mIsAnimating = isAnimating; + } + + @Override + public void finishedShowing() { + mFinishedShowingCallback.notifyCalled(); + } + + @Override + public void startedHiding(boolean isAnimating) { + mStartedHidingCallback.notifyCalled(); + mIsAnimating = isAnimating; + } + + @Override + public void finishedHiding() { + mFinishedHidingCallback.notifyCalled(); + } + }; + + @BeforeClass + public static void setUpBeforeActivityLaunched() { + DummyUiActivity.setTestTheme(R.style.Theme_Chromium_Activity_Fullscreen); + } + + @Override + public void setUpTest() throws Exception { + super.setUpTest(); + + ThreadUtils.runOnUiThreadBlocking(() -> { + getActivity().setContentView(R.layout.tab_list_recycler_view_layout); + + mRecyclerView = getActivity().findViewById(R.id.tab_list_view); + }); + + mStartedShowingCallback = new CallbackHelper(); + mFinishedShowingCallback = new CallbackHelper(); + mStartedHidingCallback = new CallbackHelper(); + mFinishedHidingCallback = new CallbackHelper(); + + mContainerModel = new PropertyModel(TabListContainerProperties.ALL_KEYS); + + mMCP = PropertyModelChangeProcessor.create( + mContainerModel, mRecyclerView, TabGridContainerViewBinder::bind); + } + + @Test + @MediumTest + public void testShowWithAnimation() throws Exception { + ThreadUtils.runOnUiThreadBlocking(() -> { + mContainerModel.set( + TabListContainerProperties.VISIBILITY_LISTENER, mMockVisibilityListener); + + mContainerModel.set(TabListContainerProperties.ANIMATE_VISIBILITY_CHANGES, true); + mContainerModel.set(TabListContainerProperties.IS_VISIBLE, true); + }); + + assertThat(mStartedShowingCallback.getCallCount(), equalTo(1)); + assertThat(mRecyclerView.getVisibility(), equalTo(View.VISIBLE)); + // TODO(yusufo): Find a way to test this on KitKat. + if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT) { + assertThat(mRecyclerView.getAlpha(), equalTo(0.0f)); + } + assertThat(mIsAnimating, equalTo(true)); + + CriteriaHelper.pollUiThread(new Criteria() { + @Override + public boolean isSatisfied() { + return mRecyclerView.getAlpha() == 1.0f; + } + }); + } + + @Test + @MediumTest + @UiThreadTest + public void testShowWithoutAnimation() throws Exception { + mContainerModel.set( + TabListContainerProperties.VISIBILITY_LISTENER, mMockVisibilityListener); + + mContainerModel.set(TabListContainerProperties.ANIMATE_VISIBILITY_CHANGES, false); + mContainerModel.set(TabListContainerProperties.IS_VISIBLE, true); + + assertThat(mStartedShowingCallback.getCallCount(), equalTo(1)); + assertThat(mRecyclerView.getVisibility(), equalTo(View.VISIBLE)); + assertThat(mRecyclerView.isAnimating(), equalTo(false)); + assertThat(mRecyclerView.getAlpha(), equalTo(1.0f)); + assertThat(mFinishedShowingCallback.getCallCount(), equalTo(1)); + } + + @Test + @MediumTest + public void testHidesWithAnimation() throws Exception { + ThreadUtils.runOnUiThreadBlocking(() -> { + mContainerModel.set( + TabListContainerProperties.VISIBILITY_LISTENER, mMockVisibilityListener); + + mContainerModel.set(TabListContainerProperties.ANIMATE_VISIBILITY_CHANGES, false); + mContainerModel.set(TabListContainerProperties.IS_VISIBLE, true); + }); + + assertThat(mRecyclerView.getVisibility(), equalTo(View.VISIBLE)); + assertThat(mRecyclerView.getAlpha(), equalTo(1.0f)); + + ThreadUtils.runOnUiThreadBlocking(() -> { + mContainerModel.set(TabListContainerProperties.ANIMATE_VISIBILITY_CHANGES, true); + mContainerModel.set(TabListContainerProperties.IS_VISIBLE, false); + }); + + assertThat(mStartedHidingCallback.getCallCount(), equalTo(1)); + assertThat(mRecyclerView.getVisibility(), equalTo(View.VISIBLE)); + // TODO(yusufo): Find a way to test this on KitKat. + if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT) { + assertThat(mRecyclerView.getAlpha(), equalTo(1.0f)); + } + assertThat(mIsAnimating, equalTo(true)); + + CriteriaHelper.pollUiThread(new Criteria() { + @Override + public boolean isSatisfied() { + return mRecyclerView.getAlpha() == 0.0f; + } + }); + assertThat(mRecyclerView.getVisibility(), equalTo(View.INVISIBLE)); + } + + @Test + @MediumTest + @UiThreadTest + public void testHidesWithoutAnimation() throws Exception { + mContainerModel.set( + TabListContainerProperties.VISIBILITY_LISTENER, mMockVisibilityListener); + + mContainerModel.set(TabListContainerProperties.ANIMATE_VISIBILITY_CHANGES, false); + mContainerModel.set(TabListContainerProperties.IS_VISIBLE, true); + + assertThat(mRecyclerView.getVisibility(), equalTo(View.VISIBLE)); + assertThat(mRecyclerView.getAlpha(), equalTo(1.0f)); + + mContainerModel.set(TabListContainerProperties.IS_VISIBLE, false); + + assertThat(mStartedHidingCallback.getCallCount(), equalTo(1)); + assertThat(mRecyclerView.isAnimating(), equalTo(false)); + assertThat(mRecyclerView.getAlpha(), equalTo(0.0f)); + assertThat(mRecyclerView.getVisibility(), equalTo(View.INVISIBLE)); + assertThat(mFinishedHidingCallback.getCallCount(), equalTo(1)); + } + + @Test + @MediumTest + @UiThreadTest + public void testIsIncognitoSetsBackgroundColor() throws Exception { + mContainerModel.set(TabListContainerProperties.IS_INCOGNITO, true); + assertThat(mRecyclerView.getBackground(), instanceOf(ColorDrawable.class)); + assertThat(((ColorDrawable) mRecyclerView.getBackground()).getColor(), + equalTo(ApiCompatibilityUtils.getColor( + mRecyclerView.getResources(), R.color.incognito_modern_primary_color))); + + mContainerModel.set(TabListContainerProperties.IS_INCOGNITO, false); + assertThat(mRecyclerView.getBackground(), instanceOf(ColorDrawable.class)); + assertThat(((ColorDrawable) mRecyclerView.getBackground()).getColor(), + equalTo(ApiCompatibilityUtils.getColor( + mRecyclerView.getResources(), R.color.modern_primary_color))); + } + + @Test + @MediumTest + @UiThreadTest + public void testTopContainerHeightSetsTopMargin() throws Exception { + assertThat(mRecyclerView.getLayoutParams(), instanceOf(FrameLayout.LayoutParams.class)); + assertThat( + ((FrameLayout.LayoutParams) mRecyclerView.getLayoutParams()).topMargin, equalTo(0)); + + mContainerModel.set(TabListContainerProperties.TOP_CONTROLS_HEIGHT, CONTAINER_HEIGHT); + assertThat(((FrameLayout.LayoutParams) mRecyclerView.getLayoutParams()).topMargin, + equalTo(CONTAINER_HEIGHT)); + } + + @Test + @MediumTest + @UiThreadTest + public void testBottomContainerHeightSetsBottomMargin() throws Exception { + assertThat(mRecyclerView.getLayoutParams(), instanceOf(FrameLayout.LayoutParams.class)); + assertThat(((FrameLayout.LayoutParams) mRecyclerView.getLayoutParams()).bottomMargin, + equalTo(0)); + + mContainerModel.set(TabListContainerProperties.BOTTOM_CONTROLS_HEIGHT, CONTAINER_HEIGHT); + assertThat(((FrameLayout.LayoutParams) mRecyclerView.getLayoutParams()).bottomMargin, + equalTo(CONTAINER_HEIGHT)); + } + + @Override + public void tearDownTest() throws Exception { + mMCP.destroy(); + super.tearDownTest(); + } +}
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/tasks/tab_list_ui/GridTabSwitcherMediatorUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/tasks/tab_list_ui/GridTabSwitcherMediatorUnitTest.java new file mode 100644 index 0000000..4fac63d --- /dev/null +++ b/chrome/android/junit/src/org/chromium/chrome/browser/tasks/tab_list_ui/GridTabSwitcherMediatorUnitTest.java
@@ -0,0 +1,363 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.tasks.tab_list_ui; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.instanceOf; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.doNothing; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.inOrder; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import static org.chromium.chrome.browser.tasks.tab_list_ui.GridTabSwitcherMediator.INITIAL_SCROLL_INDEX_OFFSET; + +import android.content.Context; +import android.content.res.Resources; +import android.graphics.Bitmap; +import android.view.View; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; +import org.mockito.InOrder; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.annotation.Config; + +import org.chromium.base.UserDataHost; +import org.chromium.base.metrics.RecordHistogram; +import org.chromium.base.metrics.RecordUserAction; +import org.chromium.chrome.browser.compositor.layouts.OverviewModeBehavior; +import org.chromium.chrome.browser.compositor.layouts.content.TabContentManager; +import org.chromium.chrome.browser.fullscreen.ChromeFullscreenManager; +import org.chromium.chrome.browser.tab.Tab; +import org.chromium.chrome.browser.tabmodel.TabModel; +import org.chromium.chrome.browser.tabmodel.TabModelObserver; +import org.chromium.chrome.browser.tabmodel.TabModelSelectorImpl; +import org.chromium.chrome.browser.tabmodel.TabModelSelectorObserver; +import org.chromium.chrome.browser.tabmodel.TabSelectionType; +import org.chromium.testing.local.LocalRobolectricTestRunner; +import org.chromium.ui.modelutil.PropertyKey; +import org.chromium.ui.modelutil.PropertyModel; +import org.chromium.ui.modelutil.PropertyObservable; + +import java.util.ArrayList; +import java.util.List; + +/** + * Tests for {@link GridTabSwitcherMediatorUnitTest}. + */ +@RunWith(LocalRobolectricTestRunner.class) +@Config(manifest = Config.NONE) +public class GridTabSwitcherMediatorUnitTest { + private static final int CONTROL_HEIGHT_DEFAULT = 56; + private static final int CONTROL_HEIGHT_MODIFIED = 0; + + private static final String TAB1_TITLE = "Tab1"; + private static final String TAB2_TITLE = "Tab2"; + private static final String TAB3_TITLE = "Tab3"; + private static final String NEW_TITLE = "New title"; + private static final int TAB1_ID = 456; + private static final int TAB2_ID = 789; + private static final int TAB3_ID = 123; + + @Mock + GridTabSwitcherMediator.ResetHandler mResetHandler; + @Mock + TabContentManager mTabContentManager; + @Mock + TabModelSelectorImpl mTabModelSelector; + @Mock + TabModel mTabModel; + @Mock + Context mContext; + @Mock + Resources mResources; + @Mock + ChromeFullscreenManager mFullscreenManager; + @Mock + PropertyObservable.PropertyObserver<PropertyKey> mPropertyObserver; + @Mock + OverviewModeBehavior.OverviewModeObserver mOverviewModeObserver; + + @Captor + ArgumentCaptor<TabModelObserver> mTabModelObserverCaptor; + @Captor + ArgumentCaptor<TabModelSelectorObserver> mTabModelSelectorObserverCaptor; + @Captor + ArgumentCaptor<ChromeFullscreenManager.FullscreenListener> mFullscreenListenerCaptor; + @Captor + ArgumentCaptor<Tab> mTabCaptor; + + private Tab mTab1; + private Tab mTab2; + private Tab mTab3; + private GridTabSwitcherMediator mMediator; + private PropertyModel mModel; + + @Before + public void setUp() { + RecordUserAction.setDisabledForTests(true); + RecordHistogram.setDisabledForTests(true); + + MockitoAnnotations.initMocks(this); + + mTab1 = prepareTab(TAB1_ID, TAB1_TITLE); + mTab2 = prepareTab(TAB2_ID, TAB2_TITLE); + mTab3 = prepareTab(TAB3_ID, TAB3_TITLE); + + List<TabModel> tabModelList = new ArrayList<>(); + tabModelList.add(mTabModel); + + doNothing().when(mTabContentManager).getTabThumbnailWithCallback(any(), any()); + doReturn(mResources).when(mContext).getResources(); + + doReturn(mTabModel).when(mTabModelSelector).getCurrentModel(); + doReturn(tabModelList).when(mTabModelSelector).getModels(); + doNothing().when(mTabModelSelector).addObserver(mTabModelSelectorObserverCaptor.capture()); + + doNothing().when(mTabModel).addObserver(mTabModelObserverCaptor.capture()); + doReturn(mTab1).when(mTabModel).getTabAt(0); + doReturn(mTab2).when(mTabModel).getTabAt(1); + doReturn(mTab2).when(mTabModel).getTabAt(2); + doReturn(false).when(mTabModel).isIncognito(); + doReturn(2).when(mTabModel).index(); + doReturn(3).when(mTabModel).getCount(); + + doReturn(CONTROL_HEIGHT_DEFAULT).when(mFullscreenManager).getBottomControlsHeight(); + doReturn(CONTROL_HEIGHT_DEFAULT).when(mFullscreenManager).getTopControlsHeight(); + doNothing().when(mFullscreenManager).addListener(mFullscreenListenerCaptor.capture()); + + mModel = new PropertyModel(TabListContainerProperties.ALL_KEYS); + mModel.addObserver(mPropertyObserver); + mMediator = new GridTabSwitcherMediator( + mResetHandler, mModel, mTabModelSelector, mFullscreenManager); + mMediator.addOverviewModeObserver(mOverviewModeObserver); + } + + @After + public void tearDown() { + RecordUserAction.setDisabledForTests(false); + RecordHistogram.setDisabledForTests(false); + } + + @Test + public void initializesWithCurrentModelOnCreation() { + initAndAssertAllProperties(); + } + + @Test + public void showsWithAnimation() { + initAndAssertAllProperties(); + mMediator.showOverview(true); + + verify(mResetHandler).resetWithTabModel(mTabModel); + + assertThat( + mModel.get(TabListContainerProperties.ANIMATE_VISIBILITY_CHANGES), equalTo(true)); + assertThat(mModel.get(TabListContainerProperties.IS_VISIBLE), equalTo(true)); + assertThat(mMediator.overviewVisible(), equalTo(true)); + } + + @Test + public void showsWithoutAnimation() { + initAndAssertAllProperties(); + mMediator.showOverview(false); + + InOrder inOrder = inOrder(mPropertyObserver, mPropertyObserver); + inOrder.verify(mPropertyObserver) + .onPropertyChanged(mModel, TabListContainerProperties.ANIMATE_VISIBILITY_CHANGES); + inOrder.verify(mPropertyObserver) + .onPropertyChanged(mModel, TabListContainerProperties.IS_VISIBLE); + inOrder.verify(mPropertyObserver) + .onPropertyChanged(mModel, TabListContainerProperties.ANIMATE_VISIBILITY_CHANGES); + + verify(mResetHandler).resetWithTabModel(mTabModel); + + assertThat( + mModel.get(TabListContainerProperties.ANIMATE_VISIBILITY_CHANGES), equalTo(true)); + assertThat(mModel.get(TabListContainerProperties.IS_VISIBLE), equalTo(true)); + assertThat(mMediator.overviewVisible(), equalTo(true)); + } + + @Test + public void hidesWithAnimation() { + initAndAssertAllProperties(); + mMediator.showOverview(true); + + assertThat( + mModel.get(TabListContainerProperties.ANIMATE_VISIBILITY_CHANGES), equalTo(true)); + assertThat(mModel.get(TabListContainerProperties.IS_VISIBLE), equalTo(true)); + + mMediator.hideOverview(true); + + assertThat( + mModel.get(TabListContainerProperties.ANIMATE_VISIBILITY_CHANGES), equalTo(true)); + assertThat(mModel.get(TabListContainerProperties.IS_VISIBLE), equalTo(false)); + assertThat(mMediator.overviewVisible(), equalTo(false)); + } + + @Test + public void hidesWithoutAnimation() { + initAndAssertAllProperties(); + mMediator.showOverview(true); + + assertThat( + mModel.get(TabListContainerProperties.ANIMATE_VISIBILITY_CHANGES), equalTo(true)); + assertThat(mModel.get(TabListContainerProperties.IS_VISIBLE), equalTo(true)); + + mMediator.hideOverview(false); + + InOrder inOrder = inOrder(mPropertyObserver, mPropertyObserver); + inOrder.verify(mPropertyObserver) + .onPropertyChanged(mModel, TabListContainerProperties.ANIMATE_VISIBILITY_CHANGES); + inOrder.verify(mPropertyObserver) + .onPropertyChanged(mModel, TabListContainerProperties.IS_VISIBLE); + inOrder.verify(mPropertyObserver) + .onPropertyChanged(mModel, TabListContainerProperties.ANIMATE_VISIBILITY_CHANGES); + + assertThat( + mModel.get(TabListContainerProperties.ANIMATE_VISIBILITY_CHANGES), equalTo(true)); + assertThat(mModel.get(TabListContainerProperties.IS_VISIBLE), equalTo(false)); + assertThat(mMediator.overviewVisible(), equalTo(false)); + } + + @Test + public void startedShowingPropagatesToObservers() { + initAndAssertAllProperties(); + mModel.get(TabListContainerProperties.VISIBILITY_LISTENER).startedShowing(true); + verify(mOverviewModeObserver).onOverviewModeStartedShowing(eq(true)); + } + + @Test + public void finishedShowingPropagatesToObservers() { + initAndAssertAllProperties(); + mModel.get(TabListContainerProperties.VISIBILITY_LISTENER).finishedShowing(); + verify(mOverviewModeObserver).onOverviewModeFinishedShowing(); + } + + @Test + public void startedHidingPropagatesToObservers() { + initAndAssertAllProperties(); + mModel.get(TabListContainerProperties.VISIBILITY_LISTENER).startedHiding(true); + verify(mOverviewModeObserver).onOverviewModeStartedHiding(eq(true), eq(false)); + } + + @Test + public void finishedHidingPropagatesToObservers() { + initAndAssertAllProperties(); + mModel.get(TabListContainerProperties.VISIBILITY_LISTENER).finishedHiding(); + verify(mOverviewModeObserver).onOverviewModeFinishedHiding(); + } + + @Test + public void resetsToNullAfterHidingFinishes() { + initAndAssertAllProperties(); + mMediator.finishedHiding(); + verify(mResetHandler).resetWithTabModel(eq(null)); + assertThat(mModel.get(TabListContainerProperties.INITIAL_SCROLL_INDEX), equalTo(0)); + } + + @Test + public void resetsAfterNewTabModelSelected() { + initAndAssertAllProperties(); + + doReturn(true).when(mTabModel).isIncognito(); + mTabModelSelectorObserverCaptor.getValue().onTabModelSelected(mTabModel, null); + verify(mResetHandler).resetWithTabModel(eq(mTabModel)); + assertThat(mModel.get(TabListContainerProperties.IS_INCOGNITO), equalTo(true)); + + // Switching TabModels by itself shouldn't cause visibility changes. + assertThat(mModel.get(TabListContainerProperties.IS_VISIBLE), equalTo(false)); + } + + @Test + public void updatesMarginWithBottomBarChanges() { + initAndAssertAllProperties(); + + assertThat(mModel.get(TabListContainerProperties.BOTTOM_CONTROLS_HEIGHT), + equalTo(CONTROL_HEIGHT_DEFAULT)); + + mFullscreenListenerCaptor.getValue().onBottomControlsHeightChanged(CONTROL_HEIGHT_MODIFIED); + assertThat(mModel.get(TabListContainerProperties.BOTTOM_CONTROLS_HEIGHT), + equalTo(CONTROL_HEIGHT_MODIFIED)); + } + + @Test + public void hidesWhenATabIsSelected() { + initAndAssertAllProperties(); + mMediator.showOverview(true); + assertThat(mModel.get(TabListContainerProperties.IS_VISIBLE), equalTo(true)); + + mTabModelObserverCaptor.getValue().didSelectTab(mTab1, TabSelectionType.FROM_USER, TAB3_ID); + + assertThat(mModel.get(TabListContainerProperties.IS_VISIBLE), equalTo(false)); + } + + @Test + public void doesNotHideWhenSelectedTabChangedDueToTabClosure() { + initAndAssertAllProperties(); + mMediator.showOverview(true); + assertThat(mModel.get(TabListContainerProperties.IS_VISIBLE), equalTo(true)); + + doReturn(true).when(mTab3).isClosing(); + mTabModelObserverCaptor.getValue().didSelectTab( + mTab1, TabSelectionType.FROM_CLOSE, TAB3_ID); + assertThat(mModel.get(TabListContainerProperties.IS_VISIBLE), equalTo(true)); + + mTabModelObserverCaptor.getValue().didSelectTab(mTab1, TabSelectionType.FROM_USER, TAB3_ID); + assertThat(mModel.get(TabListContainerProperties.IS_VISIBLE), equalTo(false)); + } + + @Test + public void doesNotHideWhenSelectedTabChangedDueToModelChange() { + initAndAssertAllProperties(); + mMediator.showOverview(true); + assertThat(mModel.get(TabListContainerProperties.IS_VISIBLE), equalTo(true)); + + mTabModelSelectorObserverCaptor.getValue().onTabModelSelected(mTabModel, null); + mTabModelObserverCaptor.getValue().didSelectTab(mTab1, TabSelectionType.FROM_USER, TAB3_ID); + assertThat(mModel.get(TabListContainerProperties.IS_VISIBLE), equalTo(true)); + + mTabModelObserverCaptor.getValue().didSelectTab(mTab1, TabSelectionType.FROM_USER, TAB3_ID); + assertThat(mModel.get(TabListContainerProperties.IS_VISIBLE), equalTo(false)); + } + + private void initAndAssertAllProperties() { + assertThat(mModel.get(TabListContainerProperties.VISIBILITY_LISTENER), + instanceOf(GridTabSwitcherMediator.class)); + assertThat( + mModel.get(TabListContainerProperties.ANIMATE_VISIBILITY_CHANGES), equalTo(true)); + assertThat(mModel.get(TabListContainerProperties.IS_INCOGNITO), + equalTo(mTabModel.isIncognito())); + assertThat(mModel.get(TabListContainerProperties.IS_VISIBLE), equalTo(false)); + assertThat(mModel.get(TabListContainerProperties.TOP_CONTROLS_HEIGHT), + equalTo(CONTROL_HEIGHT_DEFAULT)); + assertThat(mModel.get(TabListContainerProperties.BOTTOM_CONTROLS_HEIGHT), + equalTo(CONTROL_HEIGHT_DEFAULT)); + assertThat(mModel.get(TabListContainerProperties.INITIAL_SCROLL_INDEX), + equalTo(Math.max(mTabModel.index() - INITIAL_SCROLL_INDEX_OFFSET, 0))); + } + + private Tab prepareTab(int id, String title) { + Tab tab = mock(Tab.class); + when(tab.getView()).thenReturn(mock(View.class)); + when(tab.getUserDataHost()).thenReturn(new UserDataHost()); + doReturn(id).when(tab).getId(); + doReturn("").when(tab).getUrl(); + doReturn(title).when(tab).getTitle(); + doReturn(Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888)).when(tab).getFavicon(); + doReturn(false).when(tab).isClosing(); + return tab; + } +}
diff --git a/chrome/app/android/chrome_jni_onload.h b/chrome/app/android/chrome_jni_onload.h index efa9a8d..cd60af6 100644 --- a/chrome/app/android/chrome_jni_onload.h +++ b/chrome/app/android/chrome_jni_onload.h
@@ -9,8 +9,6 @@ namespace android { -bool OnJNIOnLoadRegisterJNI(JNIEnv* env); - bool OnJNIOnLoadInit(); } // namespace android
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index f973effb..394df8a 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -1396,13 +1396,6 @@ {"enable_messages_web_push", flag_descriptions::kEnableMessagesWebPushName, flag_descriptions::kEnableMessagesWebPushDescription, kOsCrOS, FEATURE_VALUE_TYPE(chromeos::features::kEnableMessagesWebPush)}, - { - "enable-background-blur", - flag_descriptions::kEnableBackgroundBlurName, - flag_descriptions::kEnableBackgroundBlurDescription, - kOsCrOS, - FEATURE_VALUE_TYPE(app_list_features::kEnableBackgroundBlur), - }, {"enable-notification-indicator", flag_descriptions::kNotificationIndicatorName, flag_descriptions::kNotificationIndicatorDescription, kOsCrOS, @@ -2246,11 +2239,6 @@ flag_descriptions::kContextualSuggestionsOptOutName, flag_descriptions::kContextualSuggestionsOptOutDescription, kOsAndroid, FEATURE_VALUE_TYPE(contextual_suggestions::kContextualSuggestionsOptOut)}, - {"enable-content-suggestions-new-favicon-server", - flag_descriptions::kEnableContentSuggestionsNewFaviconServerName, - flag_descriptions::kEnableContentSuggestionsNewFaviconServerDescription, - kOsAndroid, - FEATURE_VALUE_TYPE(ntp_snippets::kPublisherFaviconsFromNewServerFeature)}, {"enable-content-suggestions-thumbnail-dominant-color", flag_descriptions::kEnableContentSuggestionsThumbnailDominantColorName, flag_descriptions:: @@ -2628,13 +2616,6 @@ FEATURE_VALUE_TYPE( autofill::features::kAutofillSendExperimentIdsInPaymentsRPCs)}, -#if defined(OS_WIN) - {"windows10-custom-titlebar", - flag_descriptions::kWindows10CustomTitlebarName, - flag_descriptions::kWindows10CustomTitlebarDescription, kOsWin, - FEATURE_VALUE_TYPE(kWindows10CustomTitlebar)}, -#endif // OS_WIN - #if defined(OS_ANDROID) {"enable-autofill-manual-fallback", flag_descriptions::kAutofillManualFallbackAndroidName, @@ -2792,13 +2773,6 @@ FEATURE_VALUE_TYPE(features::kWebNfc)}, #endif -#if defined(OS_ANDROID) - {"enable-clipboard-provider", - flag_descriptions::kEnableOmniboxClipboardProviderName, - flag_descriptions::kEnableOmniboxClipboardProviderDescription, kOsAndroid, - FEATURE_VALUE_TYPE(omnibox::kEnableClipboardProvider)}, -#endif - {"autoplay-policy", flag_descriptions::kAutoplayPolicyName, flag_descriptions::kAutoplayPolicyDescription, kOsAll, MULTI_VALUE_TYPE(kAutoplayPolicyChoices)}, @@ -3103,13 +3077,6 @@ FEATURE_VALUE_TYPE(base::kDCheckIsFatalFeature)}, #endif // defined(DCHECK_IS_CONFIGURABLE) -#if defined(OS_CHROMEOS) - {"slide-top-chrome-with-page-scrolls", - flag_descriptions::kSlideTopChromeWithPageScrollsName, - flag_descriptions::kSlideTopChromeWithPageScrollsDescription, kOsCrOS, - FEATURE_VALUE_TYPE(features::kSlideTopChromeWithPageScrolls)}, -#endif // defined(OS_CHROMEOS) - {"enable-improved-geolanguage-data", flag_descriptions::kImprovedGeoLanguageDataName, flag_descriptions::kImprovedGeoLanguageDataDescription, kOsAll,
diff --git a/chrome/browser/android/autofill_assistant/ui_controller_android.cc b/chrome/browser/android/autofill_assistant/ui_controller_android.cc index 9051597..e7938f4 100644 --- a/chrome/browser/android/autofill_assistant/ui_controller_android.cc +++ b/chrome/browser/android/autofill_assistant/ui_controller_android.cc
@@ -78,9 +78,8 @@ header_delegate_(this), payment_request_delegate_(this), weak_ptr_factory_(this) { - java_autofill_assistant_ui_controller_ = - Java_AutofillAssistantUiController_create( - env, jactivity, reinterpret_cast<intptr_t>(this)); + java_object_ = Java_AutofillAssistantUiController_create( + env, jactivity, reinterpret_cast<intptr_t>(this)); // Register overlay_delegate_ as delegate for the overlay. Java_AssistantOverlayModel_setDelegate(env, GetOverlayModel(), @@ -108,8 +107,8 @@ JNIEnv* env = AttachCurrentThread(); auto java_web_contents = web_contents->GetJavaWebContents(); - Java_AutofillAssistantUiController_setWebContents( - env, java_autofill_assistant_ui_controller_, java_web_contents); + Java_AutofillAssistantUiController_setWebContents(env, java_object_, + java_web_contents); Java_AssistantPaymentRequestModel_setWebContents( env, GetPaymentRequestModel(), java_web_contents); Java_AssistantOverlayModel_setWebContents(env, GetOverlayModel(), @@ -133,13 +132,13 @@ } UiControllerAndroid::~UiControllerAndroid() { - Java_AutofillAssistantUiController_clearNativePtr( - AttachCurrentThread(), java_autofill_assistant_ui_controller_); + Java_AutofillAssistantUiController_clearNativePtr(AttachCurrentThread(), + java_object_); } base::android::ScopedJavaLocalRef<jobject> UiControllerAndroid::GetModel() { - return Java_AutofillAssistantUiController_getModel( - AttachCurrentThread(), java_autofill_assistant_ui_controller_); + return Java_AutofillAssistantUiController_getModel(AttachCurrentThread(), + java_object_); } // Header related methods. @@ -233,8 +232,8 @@ } void UiControllerAndroid::ExpandBottomSheet() { - Java_AutofillAssistantUiController_expandBottomSheet( - AttachCurrentThread(), java_autofill_assistant_ui_controller_); + Java_AutofillAssistantUiController_expandBottomSheet(AttachCurrentThread(), + java_object_); } void UiControllerAndroid::SetProgressPulsingEnabled(bool enabled) { @@ -250,7 +249,7 @@ void UiControllerAndroid::OnFeedbackButtonClicked() { JNIEnv* env = AttachCurrentThread(); Java_AutofillAssistantUiController_showFeedback( - env, java_autofill_assistant_ui_controller_, + env, java_object_, base::android::ConvertUTF8ToJavaString(env, GetDebugContext())); } @@ -270,8 +269,7 @@ Java_AssistantModel_setVisible(env, jmodel, false); snackbar_action_ = std::move(action); Java_AutofillAssistantUiController_showSnackbar( - env, java_autofill_assistant_ui_controller_, - base::android::ConvertUTF8ToJavaString(env, message)); + env, java_object_, base::android::ConvertUTF8ToJavaString(env, message)); } void UiControllerAndroid::SnackbarResult( @@ -306,38 +304,83 @@ void UiControllerAndroid::OnSuggestionsChanged( const std::vector<Chip>& suggestions) { JNIEnv* env = AttachCurrentThread(); - std::vector<int> types; std::vector<std::string> texts; for (const auto& suggestion : suggestions) { - types.emplace_back(suggestion.type); texts.emplace_back(suggestion.text); } Java_AutofillAssistantUiController_setSuggestions( - env, java_autofill_assistant_ui_controller_, - base::android::ToJavaIntArray(env, types), - base::android::ToJavaArrayOfStrings(env, texts)); + env, java_object_, base::android::ToJavaArrayOfStrings(env, texts)); } void UiControllerAndroid::UpdateActions() { + DCHECK(ui_delegate_); + JNIEnv* env = AttachCurrentThread(); - std::vector<int> types; - std::vector<std::string> texts; - for (const auto& action : ui_delegate_->GetActions()) { - types.emplace_back(action.type); - texts.emplace_back(action.text); + + // TODO(crbug.com/806868): Remove this case once payment request reuses the + // carousel. + if (ui_delegate_->GetPaymentRequestOptions()) { + Java_AutofillAssistantUiController_clearActions(env, java_object_); + return; } - DCHECK(ui_delegate_); - bool is_stopped = ui_delegate_->GetState() == AutofillAssistantState::STOPPED; + bool has_close_or_cancel = false; + auto chips = Java_AutofillAssistantUiController_createChipList(env); + const auto& actions = ui_delegate_->GetActions(); + int action_count = static_cast<int>(actions.size()); + for (int i = 0; i < action_count; i++) { + const auto& action = actions[i]; + auto text = base::android::ConvertUTF8ToJavaString(env, action.text); + switch (action.type) { + case HIGHLIGHTED_ACTION: + Java_AutofillAssistantUiController_addHighlightedActionButton( + env, java_object_, chips, text, i); + break; - // TODO(crbug.com/806868): Remove this boolean once payment request reuses the - // carousel. - bool is_showing_payment_request = ui_delegate_->GetPaymentRequestOptions(); - Java_AutofillAssistantUiController_setActions( - env, java_autofill_assistant_ui_controller_, - base::android::ToJavaIntArray(env, types), - base::android::ToJavaArrayOfStrings(env, texts), is_stopped, - is_showing_payment_request); + case NORMAL_ACTION: + Java_AutofillAssistantUiController_addActionButton(env, java_object_, + chips, text, i); + break; + + case CANCEL_ACTION: + // A Cancel button sneaks in an UNDO snackbar before executing the + // action, while a close button behaves like a normal button. + Java_AutofillAssistantUiController_addCancelButton(env, java_object_, + chips, text, i); + has_close_or_cancel = true; + break; + + case CLOSE_ACTION: + Java_AutofillAssistantUiController_addActionButton(env, java_object_, + chips, text, i); + has_close_or_cancel = true; + break; + + case SUGGESTION: // Suggestions are handled separately. + case UNKNOWN_CHIP_TYPE: // Ignore unknown types + break; + + // Default intentionally left out to cause a compilation error when a + // new type is added. + } + } + + if (!has_close_or_cancel) { + if (ui_delegate_->GetState() == AutofillAssistantState::STOPPED) { + Java_AutofillAssistantUiController_addCloseButton( + env, java_object_, chips, + base::android::ConvertUTF8ToJavaString( + env, l10n_util::GetStringUTF8(IDS_CLOSE))); + } else { + Java_AutofillAssistantUiController_addCancelButton( + env, java_object_, chips, + base::android::ConvertUTF8ToJavaString( + env, l10n_util::GetStringUTF8(IDS_CANCEL)), + -1); + } + } + + Java_AutofillAssistantUiController_setActions(env, java_object_, chips); } void UiControllerAndroid::OnActionsChanged(const std::vector<Chip>& actions) { @@ -362,15 +405,28 @@ void UiControllerAndroid::OnCancelButtonClicked( JNIEnv* env, - const base::android::JavaParamRef<jobject>& jcaller) { - OnCancelButtonClicked(); + const base::android::JavaParamRef<jobject>& jcaller, + jint index) { + OnCancelButtonWithActionIndexClicked(index); } void UiControllerAndroid::OnCancelButtonClicked() { - ShowSnackbar( - l10n_util::GetStringUTF8(IDS_AUTOFILL_ASSISTANT_STOPPED), - base::BindOnce(&UiControllerAndroid::Shutdown, - weak_ptr_factory_.GetWeakPtr(), Metrics::SHEET_CLOSED)); + OnCancelButtonWithActionIndexClicked(-1); +} + +void UiControllerAndroid::OnCancelButtonWithActionIndexClicked( + int action_index) { + ShowSnackbar(l10n_util::GetStringUTF8(IDS_AUTOFILL_ASSISTANT_STOPPED), + base::BindOnce(&UiControllerAndroid::OnCancel, + weak_ptr_factory_.GetWeakPtr(), action_index)); +} + +void UiControllerAndroid::OnCancel(int action_index) { + if (action_index == -1 || !ui_delegate_) { + Shutdown(Metrics::SHEET_CLOSED); + return; + } + ui_delegate_->SelectAction(action_index); } void UiControllerAndroid::OnCloseButtonClicked( @@ -426,14 +482,14 @@ void UiControllerAndroid::ShowOnboarding( JNIEnv* env, const base::android::JavaParamRef<jobject>& on_accept) { - Java_AutofillAssistantUiController_onShowOnboarding( - env, java_autofill_assistant_ui_controller_, on_accept); + Java_AutofillAssistantUiController_onShowOnboarding(env, java_object_, + on_accept); } void UiControllerAndroid::WillShutdown(Metrics::DropOutReason reason) { if (reason == Metrics::CUSTOM_TAB_CLOSED) { Java_AutofillAssistantUiController_scheduleCloseCustomTab( - AttachCurrentThread(), java_autofill_assistant_ui_controller_); + AttachCurrentThread(), java_object_); } // Capture the debug context, for including into a feedback possibly sent
diff --git a/chrome/browser/android/autofill_assistant/ui_controller_android.h b/chrome/browser/android/autofill_assistant/ui_controller_android.h index e26ca26..51914b5b 100644 --- a/chrome/browser/android/autofill_assistant/ui_controller_android.h +++ b/chrome/browser/android/autofill_assistant/ui_controller_android.h
@@ -101,7 +101,8 @@ jint index); void OnCancelButtonClicked( JNIEnv* env, - const base::android::JavaParamRef<jobject>& jcaller); + const base::android::JavaParamRef<jobject>& jcaller, + jint actionIndex); void OnCloseButtonClicked( JNIEnv* env, const base::android::JavaParamRef<jobject>& jcaller); @@ -139,14 +140,15 @@ // action after a short delay unless the user taps the undo button. void ShowSnackbar(const std::string& message, base::OnceCallback<void()> action); + void OnCancelButtonWithActionIndexClicked(int action_index); + void OnCancel(int action_index); // Debug context captured previously. If non-empty, GetDebugContext() returns // this context. std::string captured_debug_context_; // Java-side AutofillAssistantUiController object. - base::android::ScopedJavaGlobalRef<jobject> - java_autofill_assistant_ui_controller_; + base::android::ScopedJavaGlobalRef<jobject> java_object_; base::WeakPtrFactory<UiControllerAndroid> weak_ptr_factory_;
diff --git a/chrome/browser/android/chrome_feature_list.cc b/chrome/browser/android/chrome_feature_list.cc index 736422791..2d396532 100644 --- a/chrome/browser/android/chrome_feature_list.cc +++ b/chrome/browser/android/chrome_feature_list.cc
@@ -176,7 +176,6 @@ &ntp_snippets::kArticleSuggestionsFeature, &ntp_snippets::kIncreasedVisibility, &ntp_snippets::kNotificationsFeature, - &ntp_snippets::kPublisherFaviconsFromNewServerFeature, &ntp_tiles::kSiteExplorationUiFeature, &offline_pages::kBackgroundLoaderForDownloadsFeature, &offline_pages::kOfflineIndicatorFeature,
diff --git a/chrome/browser/android/vr/BUILD.gn b/chrome/browser/android/vr/BUILD.gn index 1ebddbfa..7a078fc 100644 --- a/chrome/browser/android/vr/BUILD.gn +++ b/chrome/browser/android/vr/BUILD.gn
@@ -39,6 +39,8 @@ "mailbox_to_surface_bridge.h", "metrics_util_android.cc", "metrics_util_android.h", + "register_gvr_jni.cc", + "register_gvr_jni.h", "register_jni.h", "scoped_gpu_trace.cc", "scoped_gpu_trace.h", @@ -93,9 +95,9 @@ } deps = [ - ":vr_jni_headers", "//base", "//cc", + "//chrome/android/features/vr:jni_headers", "//chrome/browser/ui:ui", "//chrome/browser/vr:vr_common", "//chrome/common:common", @@ -140,62 +142,6 @@ } } -android_library("java") { - java_files = [ - "//chrome/android/java/src/org/chromium/chrome/browser/vr/AndroidUiGestureTarget.java", - "//chrome/android/java/src/org/chromium/chrome/browser/vr/AndroidVSyncHelper.java", - "//chrome/android/java/src/org/chromium/chrome/browser/vr/EmptySniffingVrViewContainer.java", - "//chrome/android/java/src/org/chromium/chrome/browser/vr/keyboard/BuildConstants.java", - "//chrome/android/java/src/org/chromium/chrome/browser/vr/keyboard/GvrKeyboardLoaderClient.java", - "//chrome/android/java/src/org/chromium/chrome/browser/vr/keyboard/TextEditAction.java", - "//chrome/android/java/src/org/chromium/chrome/browser/vr/keyboard/VrInputMethodManagerWrapper.java", - "//chrome/android/java/src/org/chromium/chrome/browser/vr/NoopCanvas.java", - "//chrome/android/java/src/org/chromium/chrome/browser/vr/OnDispatchTouchEventCallback.java", - "//chrome/android/java/src/org/chromium/chrome/browser/vr/VrAlertDialog.java", - "//chrome/android/java/src/org/chromium/chrome/browser/vr/VrCancelAnimationActivity.java", - "//chrome/android/java/src/org/chromium/chrome/browser/vr/VrCompositorSurfaceManager.java", - "//chrome/android/java/src/org/chromium/chrome/browser/vr/VrCoreInfo.java", - "//chrome/android/java/src/org/chromium/chrome/browser/vr/VrCoreVersionChecker.java", - "//chrome/android/java/src/org/chromium/chrome/browser/vr/VrDaydreamApi.java", - "//chrome/android/java/src/org/chromium/chrome/browser/vr/VrDelegateImpl.java", - "//chrome/android/java/src/org/chromium/chrome/browser/vr/VrIntentDelegateImpl.java", - "//chrome/android/java/src/org/chromium/chrome/browser/vr/VrDelegateProviderImpl.java", - "//chrome/android/java/src/org/chromium/chrome/browser/vr/VrDialog.java", - "//chrome/android/java/src/org/chromium/chrome/browser/vr/VrDialogManager.java", - "//chrome/android/java/src/org/chromium/chrome/browser/vr/VrFeedbackStatus.java", - "//chrome/android/java/src/org/chromium/chrome/browser/vr/VrFirstRunActivity.java", - "//chrome/android/java/src/org/chromium/chrome/browser/vr/VrInputConnection.java", - "//chrome/android/java/src/org/chromium/chrome/browser/vr/VrModalPresenter.java", - "//chrome/android/java/src/org/chromium/chrome/browser/vr/VrPopupWindow.java", - "//chrome/android/java/src/org/chromium/chrome/browser/vr/VrShell.java", - "//chrome/android/java/src/org/chromium/chrome/browser/vr/VrShellDelegate.java", - "//chrome/android/java/src/org/chromium/chrome/browser/vr/VrToast.java", - "//chrome/android/java/src/org/chromium/chrome/browser/vr/VrToastManager.java", - "//chrome/android/java/src/org/chromium/chrome/browser/vr/VrUiWidgetFactory.java", - "//chrome/android/java/src/org/chromium/chrome/browser/vr/VrViewContainer.java", - "//chrome/android/java/src/org/chromium/chrome/browser/vr/VrWindowAndroid.java", - ] - - classpath_deps = [ - "//base:base_java", - "//chrome/android:chrome_java", - "//components/policy/android:policy_java", - "//content/public/android:content_java", - "//third_party/android_deps:android_arch_lifecycle_common_java", - "//third_party/android_deps:android_arch_lifecycle_runtime_java", - "//third_party/android_deps:android_support_annotations_java", - "//third_party/android_deps:android_support_v7_appcompat_java", - "//third_party/gvr-android-keyboard:kb_java", - "//ui/android:ui_full_java", - "//ui/android:ui_utils_java", - ] - - deps = [ - ":vr_java_resources", - "//third_party/gvr-android-sdk:gvr_common_java", - ] -} - android_library("ar_java") { deps = [ "//third_party/android_deps:com_google_ar_core_java", @@ -209,82 +155,6 @@ ] } -android_resources("vr_java_resources") { - resource_dirs = [] - - deps = [ - ":vr_strings_grd", - ] - - custom_package = "org.chromium.chrome.vr" -} - -java_strings_grd("vr_strings_grd") { - defines = chrome_grit_defines - grd_file = "//chrome/android/java/strings/android_chrome_vr_strings.grd" - outputs = [ - "values-am/android_chrome_vr_strings.xml", - "values-ar/android_chrome_vr_strings.xml", - "values-bg/android_chrome_vr_strings.xml", - "values-ca/android_chrome_vr_strings.xml", - "values-cs/android_chrome_vr_strings.xml", - "values-da/android_chrome_vr_strings.xml", - "values-de/android_chrome_vr_strings.xml", - "values-el/android_chrome_vr_strings.xml", - "values/android_chrome_vr_strings.xml", - "values-en-rGB/android_chrome_vr_strings.xml", - "values-es/android_chrome_vr_strings.xml", - "values-es-rUS/android_chrome_vr_strings.xml", - "values-fa/android_chrome_vr_strings.xml", - "values-fi/android_chrome_vr_strings.xml", - "values-tl/android_chrome_vr_strings.xml", - "values-fr/android_chrome_vr_strings.xml", - "values-hi/android_chrome_vr_strings.xml", - "values-hr/android_chrome_vr_strings.xml", - "values-hu/android_chrome_vr_strings.xml", - "values-in/android_chrome_vr_strings.xml", - "values-it/android_chrome_vr_strings.xml", - "values-iw/android_chrome_vr_strings.xml", - "values-ja/android_chrome_vr_strings.xml", - "values-ko/android_chrome_vr_strings.xml", - "values-lt/android_chrome_vr_strings.xml", - "values-lv/android_chrome_vr_strings.xml", - "values-nl/android_chrome_vr_strings.xml", - "values-nb/android_chrome_vr_strings.xml", - "values-pl/android_chrome_vr_strings.xml", - "values-pt-rBR/android_chrome_vr_strings.xml", - "values-pt-rPT/android_chrome_vr_strings.xml", - "values-ro/android_chrome_vr_strings.xml", - "values-ru/android_chrome_vr_strings.xml", - "values-sk/android_chrome_vr_strings.xml", - "values-sl/android_chrome_vr_strings.xml", - "values-sr/android_chrome_vr_strings.xml", - "values-sv/android_chrome_vr_strings.xml", - "values-sw/android_chrome_vr_strings.xml", - "values-th/android_chrome_vr_strings.xml", - "values-tr/android_chrome_vr_strings.xml", - "values-uk/android_chrome_vr_strings.xml", - "values-vi/android_chrome_vr_strings.xml", - "values-zh-rCN/android_chrome_vr_strings.xml", - "values-zh-rTW/android_chrome_vr_strings.xml", - ] -} - -generate_jni("vr_jni_headers") { - sources = [ - "//chrome/android/java/src/org/chromium/chrome/browser/vr/AndroidUiGestureTarget.java", - "//chrome/android/java/src/org/chromium/chrome/browser/vr/AndroidVSyncHelper.java", - "//chrome/android/java/src/org/chromium/chrome/browser/vr/VrCoreInfo.java", - "//chrome/android/java/src/org/chromium/chrome/browser/vr/VrInputConnection.java", - "//chrome/android/java/src/org/chromium/chrome/browser/vr/VrModuleProvider.java", - "//chrome/android/java/src/org/chromium/chrome/browser/vr/VrShell.java", - "//chrome/android/java/src/org/chromium/chrome/browser/vr/VrShellDelegate.java", - "//chrome/android/java/src/org/chromium/chrome/browser/vr/keyboard/GvrKeyboardLoaderClient.java", - "//chrome/android/java/src/org/chromium/chrome/browser/vr/keyboard/TextEditAction.java", - ] - jni_package = "vr" -} - if (enable_arcore) { generate_jni("ar_jni_headers") { sources = [ @@ -296,7 +166,7 @@ if (current_toolchain == default_toolchain) { generate_jni_registration("jni_registration") { - target = ":java" + target = "//chrome/android/features/vr:java" header_output = "$target_gen_dir/${target_name}.h" namespace = "vr" }
diff --git a/chrome/browser/android/vr/register_gvr_jni.cc b/chrome/browser/android/vr/register_gvr_jni.cc new file mode 100644 index 0000000..b9dcd51 --- /dev/null +++ b/chrome/browser/android/vr/register_gvr_jni.cc
@@ -0,0 +1,36 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/android/vr/register_gvr_jni.h" + +#include "base/android/jni_android.h" +#include "base/android/jni_registrar.h" +#include "base/android/jni_utils.h" +#include "base/stl_util.h" + +#include "third_party/gvr-android-sdk/display_synchronizer_jni.h" +#include "third_party/gvr-android-sdk/gvr_api_jni.h" +#include "third_party/gvr-android-sdk/native_callbacks_jni.h" + +namespace vr { + +// These VR native functions are not handled by the automatic registration, so +// they are manually registered here. +static const base::android::RegistrationMethod kGvrRegisteredMethods[] = { + {"DisplaySynchronizer", + DisplaySynchronizer::RegisterDisplaySynchronizerNatives}, + {"GvrApi", GvrApi::RegisterGvrApiNatives}, + {"NativeCallbacks", NativeCallbacks::RegisterNativeCallbacksNatives}, +}; + +bool RegisterGvrJni(JNIEnv* env) { + if (!base::android::IsSelectiveJniRegistrationEnabled(env) && + !RegisterNativeMethods(env, kGvrRegisteredMethods, + base::size(kGvrRegisteredMethods))) { + return false; + } + return true; +} + +} // namespace vr
diff --git a/chrome/browser/android/vr/register_gvr_jni.h b/chrome/browser/android/vr/register_gvr_jni.h new file mode 100644 index 0000000..cad32d2 --- /dev/null +++ b/chrome/browser/android/vr/register_gvr_jni.h
@@ -0,0 +1,16 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_ANDROID_VR_REGISTER_GVR_JNI_H_ +#define CHROME_BROWSER_ANDROID_VR_REGISTER_GVR_JNI_H_ + +#include <jni.h> + +namespace vr { + +bool RegisterGvrJni(JNIEnv* env); + +} // namespace vr + +#endif // CHROME_BROWSER_ANDROID_VR_REGISTER_GVR_JNI_H_
diff --git a/chrome/browser/android/vr/register_jni.cc b/chrome/browser/android/vr/register_jni.cc index 11ada65..bfacf816 100644 --- a/chrome/browser/android/vr/register_jni.cc +++ b/chrome/browser/android/vr/register_jni.cc
@@ -4,39 +4,23 @@ #include "chrome/browser/android/vr/register_jni.h" -#include "chrome/browser/android/vr/jni_registration.h" - -#include "base/android/jni_android.h" -#include "base/android/jni_registrar.h" #include "base/android/jni_utils.h" -#include "base/stl_util.h" - -#include "third_party/gvr-android-sdk/display_synchronizer_jni.h" -#include "third_party/gvr-android-sdk/gvr_api_jni.h" -#include "third_party/gvr-android-sdk/native_callbacks_jni.h" +#include "chrome/browser/android/vr/jni_registration.h" +#include "chrome/browser/android/vr/register_gvr_jni.h" namespace vr { -// These VR native functions are not handled by the automatic registration, so -// they are manually registered here. -static const base::android::RegistrationMethod kGvrRegisteredMethods[] = { - {"DisplaySynchronizer", - DisplaySynchronizer::RegisterDisplaySynchronizerNatives}, - {"GvrApi", GvrApi::RegisterGvrApiNatives}, - {"NativeCallbacks", NativeCallbacks::RegisterNativeCallbacksNatives}, -}; - bool RegisterJni(JNIEnv* env) { - if (!base::android::IsSelectiveJniRegistrationEnabled(env)) { - if (!vr::RegisterNonMainDexNatives(env) || - !RegisterNativeMethods(env, kGvrRegisteredMethods, - base::size(kGvrRegisteredMethods))) { - return false; - } + if (!base::android::IsSelectiveJniRegistrationEnabled(env) && + !vr::RegisterNonMainDexNatives(env)) { + return false; } if (!vr::RegisterMainDexNatives(env)) { return false; } + if (!vr::RegisterGvrJni(env)) { + return false; + } return true; }
diff --git a/chrome/browser/chromeos/login/screens/mock_welcome_screen.h b/chrome/browser/chromeos/login/screens/mock_welcome_screen.h index db3f0a629..4d050f4a 100644 --- a/chrome/browser/chromeos/login/screens/mock_welcome_screen.h +++ b/chrome/browser/chromeos/login/screens/mock_welcome_screen.h
@@ -5,6 +5,8 @@ #ifndef CHROME_BROWSER_CHROMEOS_LOGIN_SCREENS_MOCK_WELCOME_SCREEN_H_ #define CHROME_BROWSER_CHROMEOS_LOGIN_SCREENS_MOCK_WELCOME_SCREEN_H_ +#include <string> + #include "base/macros.h" #include "chrome/browser/chromeos/login/screens/welcome_screen.h" #include "chrome/browser/chromeos/login/screens/welcome_view.h" @@ -41,6 +43,8 @@ MOCK_METHOD0(Hide, void()); MOCK_METHOD0(StopDemoModeDetection, void()); MOCK_METHOD0(ReloadLocalizedContent, void()); + MOCK_METHOD1(SetInputMethodId, void(const std::string& input_method_id)); + MOCK_METHOD1(SetTimezoneId, void(const std::string& timezone_id)); private: WelcomeScreen* screen_ = nullptr;
diff --git a/chrome/browser/chromeos/login/screens/welcome_screen.cc b/chrome/browser/chromeos/login/screens/welcome_screen.cc index 37a8ef1..e52ab60 100644 --- a/chrome/browser/chromeos/login/screens/welcome_screen.cc +++ b/chrome/browser/chromeos/login/screens/welcome_screen.cc
@@ -5,6 +5,7 @@ #include "chrome/browser/chromeos/login/screens/welcome_screen.h" #include <utility> +#include <vector> #include "ash/public/interfaces/constants.mojom.h" #include "base/bind.h" @@ -39,9 +40,6 @@ constexpr char kUserActionContinueButtonClicked[] = "continue"; constexpr char kUserActionConnectDebuggingFeaturesClicked[] = "connect-debugging-features"; -constexpr char kContextKeyLocale[] = "locale"; -constexpr char kContextKeyInputMethod[] = "input-method"; -constexpr char kContextKeyTimezone[] = "timezone"; } // namespace @@ -122,6 +120,37 @@ return input_method_; } +void WelcomeScreen::SetApplicationLocale(const std::string& locale) { + const std::string& app_locale = g_browser_process->GetApplicationLocale(); + if (app_locale == locale || locale.empty()) + return; + + // Block UI while resource bundle is being reloaded. + // (InputEventsBlocker will live until callback is finished.) + locale_util::SwitchLanguageCallback callback(base::Bind( + &WelcomeScreen::OnLanguageChangedCallback, weak_factory_.GetWeakPtr(), + base::Owned(new chromeos::InputEventsBlocker), std::string())); + locale_util::SwitchLanguage(locale, true /* enableLocaleKeyboardLayouts */, + true /* login_layouts_only */, callback, + ProfileManager::GetActiveUserProfile()); +} + +void WelcomeScreen::SetInputMethod(const std::string& input_method) { + const std::vector<std::string>& input_methods = + input_method::InputMethodManager::Get() + ->GetActiveIMEState() + ->GetActiveInputMethodIds(); + if (input_method.empty() || + !base::ContainsValue(input_methods, input_method)) { + LOG(WARNING) << "The input method is empty or ineligible!"; + return; + } + input_method_ = input_method; + input_method::InputMethodManager::Get() + ->GetActiveIMEState() + ->ChangeInputMethod(input_method_, false /* show_message */); +} + void WelcomeScreen::SetTimezone(const std::string& timezone_id) { if (timezone_id.empty()) return; @@ -185,18 +214,6 @@ } } -void WelcomeScreen::OnContextKeyUpdated( - const ::login::ScreenContext::KeyType& key) { - if (key == kContextKeyLocale) - SetApplicationLocale(context_.GetString(kContextKeyLocale)); - else if (key == kContextKeyInputMethod) - SetInputMethod(context_.GetString(kContextKeyInputMethod)); - else if (key == kContextKeyTimezone) - SetTimezone(context_.GetString(kContextKeyTimezone)); - else - BaseScreen::OnContextKeyUpdated(key); -} - //////////////////////////////////////////////////////////////////////////////// // WelcomeScreen, InputMethodManager::Observer implementation: @@ -204,45 +221,15 @@ input_method::InputMethodManager* manager, Profile* /* proflie */, bool /* show_message */) { - GetContextEditor().SetString( - kContextKeyInputMethod, - manager->GetActiveIMEState()->GetCurrentInputMethod().id()); + if (view_) { + view_->SetInputMethodId( + manager->GetActiveIMEState()->GetCurrentInputMethod().id()); + } } //////////////////////////////////////////////////////////////////////////////// // WelcomeScreen, private: -void WelcomeScreen::SetApplicationLocale(const std::string& locale) { - const std::string& app_locale = g_browser_process->GetApplicationLocale(); - if (app_locale == locale || locale.empty()) - return; - - // Block UI while resource bundle is being reloaded. - // (InputEventsBlocker will live until callback is finished.) - locale_util::SwitchLanguageCallback callback(base::Bind( - &WelcomeScreen::OnLanguageChangedCallback, weak_factory_.GetWeakPtr(), - base::Owned(new chromeos::InputEventsBlocker), std::string())); - locale_util::SwitchLanguage(locale, true /* enableLocaleKeyboardLayouts */, - true /* login_layouts_only */, callback, - ProfileManager::GetActiveUserProfile()); -} - -void WelcomeScreen::SetInputMethod(const std::string& input_method) { - const std::vector<std::string>& input_methods = - input_method::InputMethodManager::Get() - ->GetActiveIMEState() - ->GetActiveInputMethodIds(); - if (input_method.empty() || - !base::ContainsValue(input_methods, input_method)) { - LOG(WARNING) << "The input method is empty or ineligible!"; - return; - } - input_method_ = input_method; - input_method::InputMethodManager::Get() - ->GetActiveIMEState() - ->ChangeInputMethod(input_method_, false /* show_message */); -} - void WelcomeScreen::InitializeTimezoneObserver() { timezone_subscription_ = CrosSettings::Get()->AddSettingsObserver( kSystemTimezone, base::Bind(&WelcomeScreen::OnSystemTimezoneChanged, @@ -301,9 +288,11 @@ } void WelcomeScreen::OnSystemTimezoneChanged() { - std::string current_timezone_id; - CrosSettings::Get()->GetString(kSystemTimezone, ¤t_timezone_id); - GetContextEditor().SetString(kContextKeyTimezone, current_timezone_id); + if (view_) { + std::string current_timezone_id; + CrosSettings::Get()->GetString(kSystemTimezone, ¤t_timezone_id); + view_->SetTimezoneId(current_timezone_id); + } } void WelcomeScreen::ConnectToLocaleUpdateController() {
diff --git a/chrome/browser/chromeos/login/screens/welcome_screen.h b/chrome/browser/chromeos/login/screens/welcome_screen.h index 125eac5..037009e 100644 --- a/chrome/browser/chromeos/login/screens/welcome_screen.h +++ b/chrome/browser/chromeos/login/screens/welcome_screen.h
@@ -73,6 +73,8 @@ std::string GetApplicationLocale(); std::string GetInputMethod() const; + void SetApplicationLocale(const std::string& locale); + void SetInputMethod(const std::string& input_method); void SetTimezone(const std::string& timezone_id); std::string GetTimezone() const; @@ -84,16 +86,12 @@ void Show() override; void Hide() override; void OnUserAction(const std::string& action_id) override; - void OnContextKeyUpdated(const ::login::ScreenContext::KeyType& key) override; // InputMethodManager::Observer implementation: void InputMethodChanged(input_method::InputMethodManager* manager, Profile* profile, bool show_message) override; - void SetApplicationLocale(const std::string& locale); - void SetInputMethod(const std::string& input_method); - // Subscribe to timezone changes. void InitializeTimezoneObserver();
diff --git a/chrome/browser/chromeos/login/screens/welcome_view.h b/chrome/browser/chromeos/login/screens/welcome_view.h index 0b7ccd8..0d97861 100644 --- a/chrome/browser/chromeos/login/screens/welcome_view.h +++ b/chrome/browser/chromeos/login/screens/welcome_view.h
@@ -5,6 +5,8 @@ #ifndef CHROME_BROWSER_CHROMEOS_LOGIN_SCREENS_WELCOME_VIEW_H_ #define CHROME_BROWSER_CHROMEOS_LOGIN_SCREENS_WELCOME_VIEW_H_ +#include <string> + #include "chrome/browser/chromeos/login/oobe_screen.h" namespace chromeos { @@ -36,6 +38,12 @@ // Reloads localized contents. virtual void ReloadLocalizedContent() = 0; + + // Change the current input method. + virtual void SetInputMethodId(const std::string& input_method_id) = 0; + + // Change the current timezone. + virtual void SetTimezoneId(const std::string& timezone_id) = 0; }; } // namespace chromeos
diff --git a/chrome/browser/chromeos/login/ui/webui_login_view.cc b/chrome/browser/chromeos/login/ui/webui_login_view.cc index 0273d8e..1369359 100644 --- a/chrome/browser/chromeos/login/ui/webui_login_view.cc +++ b/chrome/browser/chromeos/login/ui/webui_login_view.cc
@@ -18,7 +18,6 @@ #include "base/values.h" #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/chromeos/app_mode/kiosk_app_manager.h" -#include "chrome/browser/chromeos/lock_screen_apps/state_controller.h" #include "chrome/browser/chromeos/login/ui/login_display_host_webui.h" #include "chrome/browser/chromeos/login/ui/login_display_webui.h" #include "chrome/browser/chromeos/login/ui/web_contents_forced_title.h" @@ -394,18 +393,6 @@ return webui_login_.get(); } -void WebUILoginView::SetLockScreenAppFocusCyclerDelegate() { - delegates_lock_screen_app_focus_cycle_ = true; - lock_screen_apps::StateController::Get()->SetFocusCyclerDelegate(this); -} - -void WebUILoginView::ClearLockScreenAppFocusCyclerDelegate() { - if (!delegates_lock_screen_app_focus_cycle_) - return; - lock_screen_apps::StateController::Get()->SetFocusCyclerDelegate(nullptr); - delegates_lock_screen_app_focus_cycle_ = false; -} - //////////////////////////////////////////////////////////////////////////////// // ChromeKeyboardControllerClient::Observer @@ -463,15 +450,6 @@ if (!reverse && MoveFocusToSystemTray(reverse)) return true; - // Either if tab order is reversed (in which case system tray focus was not - // attempted), or system tray focus failed (in which case focusing an app - // window is preferrable to focus returning to login UI), try moving focus - // to the app window. - if (!lock_screen_app_focus_handler_.is_null()) { - lock_screen_app_focus_handler_.Run(reverse); - return true; - } - // If initial MoveFocusToSystemTray was skipped due to lock screen app being // a preferred option (due to traversal direction), try focusing system tray // again. @@ -509,28 +487,7 @@ return blink::WebInputEvent::IsPinchGestureEventType(event.GetType()); } -void WebUILoginView::RegisterLockScreenAppFocusHandler( - const LockScreenAppFocusCallback& focus_handler) { - lock_screen_app_focus_handler_ = focus_handler; -} - -void WebUILoginView::UnregisterLockScreenAppFocusHandler() { - lock_screen_app_focus_handler_.Reset(); -} - -void WebUILoginView::HandleLockScreenAppFocusOut(bool reverse) { - if (reverse && MoveFocusToSystemTray(reverse)) - return; - - AboutToRequestFocusFromTabTraversal(reverse); -} - void WebUILoginView::OnFocusLeavingSystemTray(bool reverse) { - if (!reverse && !lock_screen_app_focus_handler_.is_null()) { - lock_screen_app_focus_handler_.Run(reverse); - return; - } - AboutToRequestFocusFromTabTraversal(reverse); }
diff --git a/chrome/browser/chromeos/login/ui/webui_login_view.h b/chrome/browser/chromeos/login/ui/webui_login_view.h index 0824a24..6287597 100644 --- a/chrome/browser/chromeos/login/ui/webui_login_view.h +++ b/chrome/browser/chromeos/login/ui/webui_login_view.h
@@ -12,7 +12,6 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/observer_list.h" -#include "chrome/browser/chromeos/lock_screen_apps/focus_cycler_delegate.h" #include "chrome/browser/ui/ash/keyboard/chrome_keyboard_controller_client.h" #include "chrome/browser/ui/chrome_web_modal_dialog_manager_delegate.h" #include "components/web_modal/web_contents_modal_dialog_host.h" @@ -46,7 +45,6 @@ public content::NotificationObserver, public ChromeWebModalDialogManagerDelegate, public web_modal::WebContentsModalDialogHost, - public lock_screen_apps::FocusCyclerDelegate, public ash::SystemTrayFocusObserver { public: struct WebViewSettings { @@ -133,14 +131,6 @@ views::WebView* web_view(); - // Sets |this| as lock_screen_apps::StateController's - // lock_screen_apps::FocusCyclerDelegate. - void SetLockScreenAppFocusCyclerDelegate(); - - // Resets the lock_screen_apps::StateController's FocusCyclerDelegate, - // provided that |this| was set as the delegate. - void ClearLockScreenAppFocusCyclerDelegate(); - private: // Map type for the accelerator-to-identifier map. typedef std::map<ui::Accelerator, std::string> AccelMap; @@ -165,12 +155,6 @@ bool PreHandleGestureEvent(content::WebContents* source, const blink::WebGestureEvent& event) override; - // lock_screen_apps::FocusCyclerDelegate: - void RegisterLockScreenAppFocusHandler( - const LockScreenAppFocusCallback& focus_handler) override; - void UnregisterLockScreenAppFocusHandler() override; - void HandleLockScreenAppFocusOut(bool reverse) override; - // Overridden from ash::SystemTrayFocusObserver. void OnFocusLeavingSystemTray(bool reverse) override; @@ -211,15 +195,6 @@ // True to forward keyboard event. bool forward_keyboard_event_ = true; - // If set, the callback that should be called when focus should be moved to - // a lock screen app window. - // It gets registered using |RegisterLockScreenAppFocusHandler|. - LockScreenAppFocusCallback lock_screen_app_focus_handler_; - - // Whether this was set as lock_screen_apps::StateController's - // FocusCyclerDelegate. - bool delegates_lock_screen_app_focus_cycle_ = false; - bool observing_system_tray_focus_ = false; base::ObserverList<web_modal::ModalDialogHostObserver>::Unchecked
diff --git a/chrome/browser/chromeos/login/users/remove_supervised_users_browsertest.cc b/chrome/browser/chromeos/login/users/remove_supervised_users_browsertest.cc index b15f6f7..6ffdd1c 100644 --- a/chrome/browser/chromeos/login/users/remove_supervised_users_browsertest.cc +++ b/chrome/browser/chromeos/login/users/remove_supervised_users_browsertest.cc
@@ -81,8 +81,9 @@ : public RemoveSupervisedUsersBrowserTest { protected: void SetUpInProcessBrowserTestFixture() override { - scoped_feature_list_.InitAndEnableFeature( - features::kRemoveSupervisedUsersOnStartup); + scoped_feature_list_.InitWithFeatures( + {features::kRemoveSupervisedUsersOnStartup}, + {user_manager::kHideSupervisedUsers}); } private: @@ -93,8 +94,9 @@ : public RemoveSupervisedUsersBrowserTest { protected: void SetUpInProcessBrowserTestFixture() override { - scoped_feature_list_.InitAndDisableFeature( - features::kRemoveSupervisedUsersOnStartup); + scoped_feature_list_.InitWithFeatures( + {}, {user_manager::kHideSupervisedUsers, + features::kRemoveSupervisedUsersOnStartup}); } private:
diff --git a/chrome/browser/extensions/updater/OWNERS b/chrome/browser/extensions/updater/OWNERS index 917b82e6..7421bdb 100644 --- a/chrome/browser/extensions/updater/OWNERS +++ b/chrome/browser/extensions/updater/OWNERS
@@ -1,4 +1,3 @@ -mxnguyen@chromium.org sorin@chromium.org waffles@chromium.org
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index 5ce15bd5..d949b7e 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -913,11 +913,6 @@ "expiry_milestone": 76 }, { - "name": "enable-background-blur", - // "owners": [ "your-team" ], - "expiry_milestone": 76 - }, - { "name": "enable-ble-advertising-in-apps", // "owners": [ "your-team" ], "expiry_milestone": 76 @@ -968,11 +963,6 @@ "expiry_milestone": 76 }, { - "name": "enable-clipboard-provider", - "owners": [ "orinj", "mpearson", "jdonnelly" ], - "expiry_milestone": 76 - }, - { "name": "enable-cloud-print-xps", "owners": [ "//printing/OWNERS" ], "expiry_milestone": 76 @@ -993,11 +983,6 @@ "expiry_milestone": 76 }, { - "name": "enable-content-suggestions-new-favicon-server", - // "owners": [ "your-team" ], - "expiry_milestone": 76 - }, - { "name": "enable-content-suggestions-thumbnail-dominant-color", // "owners": [ "your-team" ], "expiry_milestone": 76 @@ -3025,8 +3010,10 @@ }, { "name": "ui-disable-partial-swap", - // "owners": [ "your-team" ], - "expiry_milestone": 76 + "owners": [ "//components/viz/OWNERS" ], + // This flag is used for in-the-field debugging of rendering issues, + // especially on Chrome OS. + "expiry_milestone": -1 }, { "name": "ui-show-composited-layer-borders", @@ -3195,11 +3182,6 @@ "expiry_milestone": 76 }, { - "name": "windows10-custom-titlebar", - // "owners": [ "your-team" ], - "expiry_milestone": 76 - }, - { "name": "windows-mixed-reality", "owners": [ "//device/vr/OWNERS", "xr-dev@chromium.org" ], "expiry_milestone": 76
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index a610c14..5a37916 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -2318,12 +2318,6 @@ const char kEnableCommandLineOnNoRootedDescription[] = "Enable reading command line file on non-rooted devices (DANGEROUS)."; -const char kEnableContentSuggestionsNewFaviconServerName[] = - "Get favicons for content suggestions from a new server."; -const char kEnableContentSuggestionsNewFaviconServerDescription[] = - "If enabled, the content suggestions (on the NTP) will get favicons from a " - "new favicon server."; - const char kEnableContentSuggestionsThumbnailDominantColorName[] = "Use content suggestions thumbnail dominant color."; const char kEnableContentSuggestionsThumbnailDominantColorDescription[] = @@ -2335,12 +2329,6 @@ "Enables a new context menu when a link, image, or video is pressed within " "Chrome."; -const char kEnableOmniboxClipboardProviderName[] = - "Omnibox clipboard URL suggestions"; -const char kEnableOmniboxClipboardProviderDescription[] = - "Provide a suggestion of the URL stored in the clipboard (if any) upon " - "focus in the omnibox."; - const char kEnableNtpAssetDownloadSuggestionsName[] = "Show asset downloads on the New Tab page"; const char kEnableNtpAssetDownloadSuggestionsDescription[] = @@ -2908,11 +2896,6 @@ "Use Windows Runtime MIDI API for WebMIDI (effective only on Windows 10 or " "later)."; -const char kWindows10CustomTitlebarName[] = "Custom-drawn Windows 10 Titlebar"; -const char kWindows10CustomTitlebarDescription[] = - "If enabled, Chrome will draw the titlebar and caption buttons instead of " - "deferring to Windows."; - #endif // defined(OS_WIN) // Mac ------------------------------------------------------------------------- @@ -3144,10 +3127,6 @@ const char kEnableAssistantAppSupportDescription[] = "Enable the Assistant App Support feature"; -const char kEnableBackgroundBlurName[] = "Enable background blur."; -const char kEnableBackgroundBlurDescription[] = - "Enables background blur for the Peeking Launcher and Tab Switcher."; - const char kEnableChromeOsAccountManagerName[] = "Enable Account Manager"; const char kEnableChromeOsAccountManagerDescription[] = "Enables the Chrome OS Account Manager"; @@ -3375,12 +3354,6 @@ "Runs the system UI (ash) as a mojo service, but inside the browser " "process. The browser uses the mojo window service (ws) APIs."; -const char kSlideTopChromeWithPageScrollsName[] = - "Slide top-chrome with page scrolls"; -const char kSlideTopChromeWithPageScrollsDescription[] = - "If enabled, page scrolls in tablet mode will also scroll the top-chrome" - " UI."; - const char kSmartTextSelectionName[] = "Smart Text Selection"; const char kSmartTextSelectionDescription[] = "Shows quick actions for text "
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index 0f316d5..d2f184f 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -1373,18 +1373,12 @@ extern const char kEnableCommandLineOnNonRootedName[]; extern const char kEnableCommandLineOnNoRootedDescription[]; -extern const char kEnableContentSuggestionsNewFaviconServerName[]; -extern const char kEnableContentSuggestionsNewFaviconServerDescription[]; - extern const char kEnableContentSuggestionsThumbnailDominantColorName[]; extern const char kEnableContentSuggestionsThumbnailDominantColorDescription[]; extern const char kEnableCustomContextMenuName[]; extern const char kEnableCustomContextMenuDescription[]; -extern const char kEnableOmniboxClipboardProviderName[]; -extern const char kEnableOmniboxClipboardProviderDescription[]; - extern const char kEnableNtpAssetDownloadSuggestionsName[]; extern const char kEnableNtpAssetDownloadSuggestionsDescription[]; @@ -1711,9 +1705,6 @@ extern const char kUseWinrtMidiApiName[]; extern const char kUseWinrtMidiApiDescription[]; -extern const char kWindows10CustomTitlebarName[]; -extern const char kWindows10CustomTitlebarDescription[]; - #endif // defined(OS_WIN) // Mac ------------------------------------------------------------------------ @@ -1877,9 +1868,6 @@ extern const char kEnableAssistantAppSupportName[]; extern const char kEnableAssistantAppSupportDescription[]; -extern const char kEnableBackgroundBlurName[]; -extern const char kEnableBackgroundBlurDescription[]; - extern const char kEnableChromeOsAccountManagerName[]; extern const char kEnableChromeOsAccountManagerDescription[]; @@ -2015,9 +2003,6 @@ extern const char kSingleProcessMashName[]; extern const char kSingleProcessMashDescription[]; -extern const char kSlideTopChromeWithPageScrollsName[]; -extern const char kSlideTopChromeWithPageScrollsDescription[]; - extern const char kSmartTextSelectionName[]; extern const char kSmartTextSelectionDescription[];
diff --git a/chrome/browser/net/chrome_network_delegate.cc b/chrome/browser/net/chrome_network_delegate.cc index 13a78cd8..5562e1bd 100644 --- a/chrome/browser/net/chrome_network_delegate.cc +++ b/chrome/browser/net/chrome_network_delegate.cc
@@ -14,7 +14,6 @@ #include "base/command_line.h" #include "base/debug/alias.h" #include "base/debug/dump_without_crashing.h" -#include "base/debug/stack_trace.h" #include "base/logging.h" #include "base/macros.h" #include "base/metrics/user_metrics.h"
diff --git a/chrome/browser/printing/print_browsertest.cc b/chrome/browser/printing/print_browsertest.cc index c84e4ea..a511f72 100644 --- a/chrome/browser/printing/print_browsertest.cc +++ b/chrome/browser/printing/print_browsertest.cc
@@ -45,7 +45,7 @@ namespace { -static constexpr int kDefaultDocumentCookie = 1234; +constexpr int kDefaultDocumentCookie = 1234; class PrintPreviewObserver : PrintPreviewUI::TestingDelegate { public: @@ -84,7 +84,7 @@ class TestPrintFrameContentMsgFilter : public content::BrowserMessageFilter { public: TestPrintFrameContentMsgFilter(int document_cookie, - base::RepeatingClosure msg_callback) + const base::RepeatingClosure& msg_callback) : content::BrowserMessageFilter(PrintMsgStart), document_cookie_(document_cookie), task_runner_(base::SequencedTaskRunnerHandle::Get()), @@ -103,7 +103,7 @@ } private: - ~TestPrintFrameContentMsgFilter() override {} + ~TestPrintFrameContentMsgFilter() override = default; void CheckMessage(int document_cookie, const PrintHostMsg_DidPrintContent_Params& param) { @@ -133,7 +133,7 @@ } private: - ~KillPrintFrameContentMsgFilter() override {} + ~KillPrintFrameContentMsgFilter() override = default; void KillRenderProcess(int document_cookie, const PrintHostMsg_DidPrintContent_Params& param) { @@ -147,8 +147,8 @@ class PrintBrowserTest : public InProcessBrowserTest { public: - PrintBrowserTest() {} - ~PrintBrowserTest() override {} + PrintBrowserTest() = default; + ~PrintBrowserTest() override = default; void SetUp() override { num_expected_messages_ = 1; // By default, only wait on one message. @@ -166,9 +166,8 @@ void PrintAndWaitUntilPreviewIsReady(bool print_only_selection) { PrintPreviewObserver print_preview_observer; - printing::StartPrint(browser()->tab_strip_model()->GetActiveWebContents(), - /*print_preview_disabled=*/false, - print_only_selection); + StartPrint(browser()->tab_strip_model()->GetActiveWebContents(), + /*print_preview_disabled=*/false, print_only_selection); print_preview_observer.WaitUntilPreviewIsReady(); } @@ -226,8 +225,8 @@ class SitePerProcessPrintBrowserTest : public PrintBrowserTest { public: - SitePerProcessPrintBrowserTest() {} - ~SitePerProcessPrintBrowserTest() override {} + SitePerProcessPrintBrowserTest() = default; + ~SitePerProcessPrintBrowserTest() override = default; // content::BrowserTestBase void SetUpCommandLine(base::CommandLine* command_line) override { @@ -239,8 +238,8 @@ public: static constexpr char kIsolatedSite[] = "b.com"; - IsolateOriginsPrintBrowserTest() {} - ~IsolateOriginsPrintBrowserTest() override {} + IsolateOriginsPrintBrowserTest() = default; + ~IsolateOriginsPrintBrowserTest() override = default; // content::BrowserTestBase void SetUpCommandLine(base::CommandLine* command_line) override { @@ -260,15 +259,14 @@ class PrintExtensionBrowserTest : public extensions::ExtensionBrowserTest { public: - PrintExtensionBrowserTest() {} - ~PrintExtensionBrowserTest() override {} + PrintExtensionBrowserTest() = default; + ~PrintExtensionBrowserTest() override = default; void PrintAndWaitUntilPreviewIsReady(bool print_only_selection) { PrintPreviewObserver print_preview_observer; - printing::StartPrint(browser()->tab_strip_model()->GetActiveWebContents(), - /*print_preview_disabled=*/false, - print_only_selection); + StartPrint(browser()->tab_strip_model()->GetActiveWebContents(), + /*print_preview_disabled=*/false, print_only_selection); print_preview_observer.WaitUntilPreviewIsReady(); }
diff --git a/chrome/browser/profiles/profile_attributes_storage.cc b/chrome/browser/profiles/profile_attributes_storage.cc index 8cde230..615be3a 100644 --- a/chrome/browser/profiles/profile_attributes_storage.cc +++ b/chrome/browser/profiles/profile_attributes_storage.cc
@@ -5,13 +5,13 @@ #include "chrome/browser/profiles/profile_attributes_storage.h" #include <algorithm> +#include <unordered_set> #include <utility> #include "base/bind.h" #include "base/files/file_util.h" #include "base/i18n/number_formatting.h" #include "base/i18n/string_compare.h" -#include "base/rand_util.h" #include "base/stl_util.h" #include "base/strings/string_number_conversions.h" #include "base/strings/utf_string_conversions.h" @@ -140,29 +140,6 @@ return a->GetPath().value() < b->GetPath().value(); } -// Tries to find an random icon index that satisfies all the given conditions. -// Returns true if an icon was found, false otherwise. -bool GetRandomAvatarIconIndex( - bool allow_generic_icon, - bool must_be_unused, - const std::unordered_set<size_t>& used_icon_indices, - size_t* out_icon_index) { - size_t start = allow_generic_icon ? 0 : profiles::GetGenericAvatarIconCount(); - size_t end = profiles::GetDefaultAvatarIconCount(); - size_t count = end - start; - - int rand = base::RandInt(0, count); - for (size_t i = 0; i < count; ++i) { - size_t icon_index = start + (rand + i) % count; - if (!must_be_unused || used_icon_indices.count(icon_index) == 0u) { - *out_icon_index = icon_index; - return true; - } - } - - return false; -} - } // namespace ProfileAttributesStorage::ProfileAttributesStorage(PrefService* prefs) @@ -277,23 +254,7 @@ for (const ProfileAttributesEntry* entry : entries) used_icon_indices.insert(entry->GetAvatarIconIndex()); - size_t icon_index = 0; -#if defined(OS_CHROMEOS) || defined(OS_ANDROID) - // For ChromeOS and Android, try to find a unique, non-generic icon. - if (GetRandomAvatarIconIndex(false, true, used_icon_indices, &icon_index)) - return icon_index; -#endif - - // Try to find any unique icon. - if (GetRandomAvatarIconIndex(true, true, used_icon_indices, &icon_index)) - return icon_index; - - // Settle for any random icon, even if it's not already used. - if (GetRandomAvatarIconIndex(true, false, used_icon_indices, &icon_index)) - return icon_index; - - NOTREACHED(); - return 0; + return profiles::GetRandomAvatarIconIndex(used_icon_indices); } const gfx::Image* ProfileAttributesStorage::LoadAvatarPictureFromPath(
diff --git a/chrome/browser/profiles/profile_attributes_storage.h b/chrome/browser/profiles/profile_attributes_storage.h index 6877b43..4084eaa 100644 --- a/chrome/browser/profiles/profile_attributes_storage.h +++ b/chrome/browser/profiles/profile_attributes_storage.h
@@ -10,7 +10,6 @@ #include <memory> #include <string> #include <unordered_map> -#include <unordered_set> #include <vector> #include "base/files/file_path.h"
diff --git a/chrome/browser/profiles/profile_attributes_storage_unittest.cc b/chrome/browser/profiles/profile_attributes_storage_unittest.cc index f63e762c..5079efb 100644 --- a/chrome/browser/profiles/profile_attributes_storage_unittest.cc +++ b/chrome/browser/profiles/profile_attributes_storage_unittest.cc
@@ -612,13 +612,6 @@ // Icon must not be used. ASSERT_EQ(0u, used_icon_indices.count(icon_index)); ASSERT_GT(total_icon_count, icon_index); - -#if defined(OS_CHROMEOS) || defined(OS_ANDROID) - if (i < total_icon_count - generic_icon_count) - ASSERT_LE(generic_icon_count, icon_index); - else - ASSERT_GT(generic_icon_count, icon_index); -#endif } used_icon_indices.insert(icon_index);
diff --git a/chrome/browser/profiles/profile_avatar_icon_util.cc b/chrome/browser/profiles/profile_avatar_icon_util.cc index 1c310f9..ace1174 100644 --- a/chrome/browser/profiles/profile_avatar_icon_util.cc +++ b/chrome/browser/profiles/profile_avatar_icon_util.cc
@@ -12,6 +12,7 @@ #include "base/format_macros.h" #include "base/macros.h" #include "base/path_service.h" +#include "base/rand_util.h" #include "base/strings/string_number_conversions.h" #include "base/strings/stringprintf.h" #include "base/values.h" @@ -288,12 +289,6 @@ profiles::SHAPE_SQUARE); } -gfx::Image GetAvatarIconForMenu(const gfx::Image& image, - bool is_rectangle) { - return GetSizedAvatarIcon( - image, is_rectangle, kAvatarIconWidth, kAvatarIconHeight); -} - gfx::Image GetAvatarIconForWebUI(const gfx::Image& image, bool is_rectangle) { return GetSizedAvatarIcon(image, is_rectangle, @@ -519,4 +514,17 @@ return avatars; } +size_t GetRandomAvatarIconIndex( + const std::unordered_set<size_t>& used_icon_indices) { + int rand = base::RandInt(0, GetDefaultAvatarIconCount()); + // Find the next unused index. + for (size_t i = 0; i < GetDefaultAvatarIconCount(); ++i) { + size_t icon_index = (rand + i) % GetDefaultAvatarIconCount(); + if (used_icon_indices.count(icon_index) == 0u) + return icon_index; + } + // All indices are used, so return a random one. + return rand; +} + } // namespace profiles
diff --git a/chrome/browser/profiles/profile_avatar_icon_util.h b/chrome/browser/profiles/profile_avatar_icon_util.h index 53a4880..dec4541 100644 --- a/chrome/browser/profiles/profile_avatar_icon_util.h +++ b/chrome/browser/profiles/profile_avatar_icon_util.h
@@ -9,6 +9,7 @@ #include <memory> #include <string> +#include <unordered_set> #include "third_party/skia/include/core/SkColor.h" @@ -58,10 +59,6 @@ int width, int height); -// Returns a version of |image| suitable for use in menus. -gfx::Image GetAvatarIconForMenu(const gfx::Image& image, - bool is_rectangle); - // Returns a version of |image| suitable for use in WebUI. gfx::Image GetAvatarIconForWebUI(const gfx::Image& image, bool is_rectangle); @@ -119,6 +116,11 @@ // according to the avatars' default order. std::unique_ptr<base::ListValue> GetDefaultProfileAvatarIconsAndLabels(); +// This method tries to find a random avatar index that is not in +// |used_icon_indices|. If there is no such index, a random index is returned. +size_t GetRandomAvatarIconIndex( + const std::unordered_set<size_t>& used_icon_indices); + } // namespace profiles #endif // CHROME_BROWSER_PROFILES_PROFILE_AVATAR_ICON_UTIL_H_
diff --git a/chrome/browser/profiles/profile_avatar_icon_util_unittest.cc b/chrome/browser/profiles/profile_avatar_icon_util_unittest.cc index afe04c6..02655cfa4 100644 --- a/chrome/browser/profiles/profile_avatar_icon_util_unittest.cc +++ b/chrome/browser/profiles/profile_avatar_icon_util_unittest.cc
@@ -53,23 +53,6 @@ VerifyScaling(result2, size); } -TEST(ProfileInfoUtilTest, MenuIcon) { - // Test that an avatar icon isn't changed. - const gfx::Image& profile_image( - ui::ResourceBundle::GetSharedInstance().GetImageNamed( - IDR_PROFILE_AVATAR_0)); - gfx::Image result = profiles::GetAvatarIconForMenu(profile_image, false); - EXPECT_FALSE(gfx::test::IsEmpty(result)); - EXPECT_TRUE(gfx::test::AreImagesEqual(profile_image, result)); - - // Test that a rectangular picture is changed. - gfx::Image rect_picture(gfx::test::CreateImage()); - gfx::Size size(profiles::kAvatarIconWidth, profiles::kAvatarIconHeight); - gfx::Image result2 = profiles::GetAvatarIconForMenu(rect_picture, true); - - VerifyScaling(result2, size); -} - TEST(ProfileInfoUtilTest, WebUIIcon) { // Test that an avatar icon isn't changed. const gfx::Image& profile_image(
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/editing.js b/chrome/browser/resources/chromeos/chromevox/cvox2/background/editing.js index 217fb77..3a3fa49 100644 --- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/editing.js +++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/editing.js
@@ -281,10 +281,6 @@ this.updateIntraLineState_(this.line_); /** - * @private {string|undefined} - */ - this.fontFamily_; - /** * @private {number|undefined} */ this.fontSize_; @@ -292,6 +288,38 @@ * @private {string|undefined} */ this.fontColor_; + /** + * @private {boolean|undefined} + */ + this.linked_; + /** + * @private {boolean|undefined} + */ + this.subscript_; + /** + * @private {boolean|undefined} + */ + this.superscript_; + /** + * @private {boolean} + */ + this.bold_ = false; + /** + * @private {boolean} + */ + this.italic_ = false; + /** + * @private {boolean} + */ + this.underline_ = false; + /** + * @private {boolean} + */ + this.lineThrough_ = false; + /** + * @private {string|undefined} + */ + this.fontFamily_; } AutomationRichEditableText.prototype = { @@ -420,13 +448,7 @@ if (markerEndIndex > -1) this.speakTextMarker_(container.markerTypes[markerEndIndex], true); } - - // Start of the container. - if (cur.containerStartOffset == cur.startOffset) - this.speakTextStyle_(container); - else if (cur.containerEndOffset == cur.endOffset) - this.speakTextStyle_(container, true); - + this.speakTextStyle_(container); return; } @@ -603,62 +625,69 @@ /** * @param {!AutomationNode} style - * @param {boolean=} opt_end * @private */ - speakTextStyle_: function(style, opt_end) { + speakTextStyle_: function(style) { var msgs = []; - var fontFamily = style.fontFamily; var fontSize = style.fontSize; var fontColor = Color.getColorDescription(style.color); - var msg; + var linked = style.state[StateType.LINKED]; + var subscript = style.state.subscript; + var superscript = style.state.superscript; + var bold = style.bold; + var italic = style.italic; + var underline = style.underline; + var lineThrough = style.lineThrough; + var fontFamily = style.fontFamily; + // Only report text style attributes if they change. if (fontSize && (fontSize !== this.fontSize_)) { this.fontSize_ = fontSize; - msg = opt_end ? 'font_size_end' : 'font_size_start'; - msgs.push({'msg': msg, 'opt_subs': [this.fontSize_]}); + msgs.push({msg: 'font_size', opt_subs: [this.fontSize_]}); } if (fontColor && (fontColor !== this.fontColor_)) { this.fontColor_ = fontColor; - msg = opt_end ? 'font_color_end' : 'font_color_start'; - msgs.push({'msg': msg, 'opt_subs': [this.fontColor_]}); + msgs.push({msg: 'font_color', opt_subs: [this.fontColor_]}); } - if (style.state.linked) { - msgs.push(opt_end ? {'msg': 'link_end'} : {'msg': 'link_start'}); + if (linked !== this.linked_) { + this.linked_ = linked; + msgs.push(this.linked_ ? {msg: 'link'} : {msg: 'not_link'}); } - if (style.subscript) { + if (style.subscript !== this.subscript_) { + this.subscript_ = subscript; + msgs.push(this.subscript_ ? {msg: 'subscript'} : {msg: 'not_subscript'}); + } + if (style.superscript !== this.superscript_) { + this.superscript_ = superscript; msgs.push( - opt_end ? {'msg': 'subscript_end'} : {'msg': 'subscript_start'}); + this.superscript_ ? {msg: 'superscript'} : {msg: 'not_superscript'}); } - if (style.superscript) { + if (bold !== this.bold_) { + this.bold_ = bold; + msgs.push(this.bold_ ? {msg: 'bold'} : {msg: 'not_bold'}); + } + if (italic !== this.italic_) { + this.italic_ = italic; + msgs.push(this.italic_ ? {msg: 'italic'} : {msg: 'not_italic'}); + } + if (underline !== this.underline_) { + this.underline_ = underline; + msgs.push(this.underline_ ? {msg: 'underline'} : {msg: 'not_underline'}); + } + if (lineThrough !== this.lineThrough_) { + this.lineThrough_ = lineThrough; msgs.push( - opt_end ? {'msg': 'superscript_end'} : {'msg': 'superscript_start'}); - } - if (style.bold) { - msgs.push(opt_end ? {'msg': 'bold_end'} : {'msg': 'bold_start'}); - } - if (style.italic) { - msgs.push(opt_end ? {'msg': 'italic_end'} : {'msg': 'italic_start'}); - } - if (style.underline) { - msgs.push( - opt_end ? {'msg': 'underline_end'} : {'msg': 'underline_start'}); - } - if (style.lineThrough) { - msgs.push( - opt_end ? {'msg': 'line_through_end'} : - {'msg': 'line_through_start'}); + this.lineThrough_ ? {msg: 'linethrough'} : {msg: 'not_linethrough'}); } if (fontFamily && (fontFamily !== this.fontFamily_)) { this.fontFamily_ = fontFamily; - msg = opt_end ? 'font_family_end' : 'font_family_start'; - msgs.push({'msg': msg, 'opt_subs': [this.fontFamily_]}); + msgs.push({msg: 'font_family', opt_subs: [this.fontFamily_]}); } if (msgs.length) { msgs.forEach(function(obj) { cvox.ChromeVox.tts.speak( - Msgs.getMsg(obj['msg'], obj['opt_subs']), cvox.QueueMode.QUEUE, + Msgs.getMsg(obj.msg, obj.opt_subs), cvox.QueueMode.QUEUE, cvox.AbstractTts.PERSONALITY_ANNOTATION); }); }
diff --git a/chrome/browser/resources/chromeos/chromevox/cvox2/background/editing_test.extjs b/chrome/browser/resources/chromeos/chromevox/cvox2/background/editing_test.extjs index 9783b97d..3f09d04 100644 --- a/chrome/browser/resources/chromeos/chromevox/cvox2/background/editing_test.extjs +++ b/chrome/browser/resources/chromeos/chromevox/cvox2/background/editing_test.extjs
@@ -231,16 +231,16 @@ .call(moveByChar) .expectSpeech('i') - .expectSpeech('Bold start') + .expectSpeech('Bold') .expectBraille(lineText, { startIndex: 5, endIndex: 5 }) .call(moveByChar) .expectSpeech('s') - .expectSpeech('Bold end') .expectBraille(lineText, { startIndex: 6, endIndex: 6 }) .call(moveByChar) .expectSpeech(' ') + .expectSpeech('Not bold') .expectBraille(lineText, { startIndex: 7, endIndex: 7 }) .call(moveByChar) @@ -262,11 +262,12 @@ this.runWithLoadedTree(function() {/*! <div role="textbox" contenteditable> <p style="font-size:20px; font-family:times"> - <b style="color:#ff0000">Move</b> <i>through</i> - <u style="font-family:georgia">text</u> by - <strike style="font-size:12px; color:#0000ff">character</strike> test + <b style="color:#ff0000">Move</b> <i>through</i> <u style="font-family:georgia">text</u> + by <strike style="font-size:12px; color:#0000ff">character</strike> + <a href="#">test</a>! </p> </div> + <button id="go">Go</button> <script> @@ -279,24 +280,30 @@ var input = root.find({role: RoleType.TEXT_FIELD}); var go = root.find({role: RoleType.BUTTON}); var moveByChar = go.doDefault.bind(go); - var lineText = 'Move through text by character test mled'; + var lineText = 'Move through text by character test! mled'; + var lineOnLinkText = 'Move through text by character test lnk ! mled'; this.listenOnce(input, chrome.automation.EventType.FOCUS, function() { mockFeedback.call(moveByChar) - .expectSpeech('o').expectBraille(lineText, { startIndex: 1, endIndex: 1 }) + .expectSpeech('o') + .expectSpeech('Size 20') + .expectSpeech('Red, 100% opacity.') + .expectSpeech('Bold') + .expectSpeech('Font times') + .expectBraille(lineText, { startIndex: 1, endIndex: 1 }) .call(moveByChar) .expectSpeech('v').expectBraille(lineText, { startIndex: 2, endIndex: 2 }) .call(moveByChar) .expectSpeech('e') - .expectSpeech('Bold end') .expectBraille(lineText, { startIndex: 3, endIndex: 3 }) .call(moveByChar) .expectSpeech(' ') - .expectSpeech('Black, 100% opacity. start') + .expectSpeech('Black, 100% opacity.') + .expectSpeech('Not bold') .expectBraille(lineText, { startIndex: 4, endIndex: 4 }) .call(moveByChar) .expectSpeech('t') - .expectSpeech('Italic start') + .expectSpeech('Italic') .expectBraille(lineText, { startIndex: 5, endIndex: 5 }) .call(moveByChar) .expectSpeech('h').expectBraille(lineText, { startIndex: 6, endIndex: 6 }) @@ -310,14 +317,15 @@ .expectSpeech('g').expectBraille(lineText, { startIndex: 10, endIndex: 10 }) .call(moveByChar) .expectSpeech('h') - .expectSpeech('Italic end') .expectBraille(lineText, { startIndex: 11, endIndex: 11 }) .call(moveByChar) - .expectSpeech(' ').expectBraille(lineText, { startIndex: 12, endIndex: 12 }) + .expectSpeech(' ') + .expectSpeech('Not italic') + .expectBraille(lineText, { startIndex: 12, endIndex: 12 }) .call(moveByChar) .expectSpeech('t') - .expectSpeech('Underline start') - .expectSpeech('georgia start') + .expectSpeech('Underline') + .expectSpeech('Font georgia') .expectBraille(lineText, { startIndex: 13, endIndex: 13 }) .call(moveByChar) .expectSpeech('e').expectBraille(lineText, { startIndex: 14, endIndex: 14 }) @@ -325,11 +333,11 @@ .expectSpeech('x').expectBraille(lineText, { startIndex: 15, endIndex: 15 }) .call(moveByChar) .expectSpeech('t') - .expectSpeech('Underline end') .expectBraille(lineText, { startIndex: 16, endIndex: 16 }) .call(moveByChar) .expectSpeech(' ') - .expectSpeech('times start') + .expectSpeech('Not underline') + .expectSpeech('Font times') .expectBraille(lineText, { startIndex: 17, endIndex: 17 }) .call(moveByChar) .expectSpeech('b').expectBraille(lineText, { startIndex: 18, endIndex: 18 }) @@ -339,9 +347,9 @@ .expectSpeech(' ').expectBraille(lineText, { startIndex: 20, endIndex: 20 }) .call(moveByChar) .expectSpeech('c') - .expectSpeech('Size 12 start') - .expectSpeech('Blue, 100% opacity. start') - .expectSpeech('Strike through start') + .expectSpeech('Size 12') + .expectSpeech('Blue, 100% opacity.') + .expectSpeech('Line through') .expectBraille(lineText, { startIndex: 21, endIndex: 21 }) .call(moveByChar) .expectSpeech('h').expectBraille(lineText, { startIndex: 22, endIndex: 22 }) @@ -359,21 +367,31 @@ .expectSpeech('e').expectBraille(lineText, { startIndex: 28, endIndex: 28 }) .call(moveByChar) .expectSpeech('r') - .expectSpeech('Strike through end') .expectBraille(lineText, { startIndex: 29, endIndex: 29 }) .call(moveByChar) .expectSpeech(' ') - .expectSpeech('Size 20 start') - .expectSpeech('Black, 100% opacity. start') + .expectSpeech('Size 20') + .expectSpeech('Black, 100% opacity.') + .expectSpeech('Not line through') .expectBraille(lineText, { startIndex: 30, endIndex: 30 }) .call(moveByChar) - .expectSpeech('t').expectBraille(lineText, { startIndex: 31, endIndex: 31 }) + .expectSpeech('t') + .expectSpeech('Blue, 100% opacity.') + .expectSpeech('Link') + .expectSpeech('Underline') + .expectBraille(lineOnLinkText, { startIndex: 31, endIndex: 31 }) .call(moveByChar) - .expectSpeech('e').expectBraille(lineText, { startIndex: 32, endIndex: 32 }) + .expectSpeech('e').expectBraille(lineOnLinkText, { startIndex: 32, endIndex: 32 }) .call(moveByChar) - .expectSpeech('s').expectBraille(lineText, { startIndex: 33, endIndex: 33 }) + .expectSpeech('s').expectBraille(lineOnLinkText, { startIndex: 33, endIndex: 33 }) .call(moveByChar) - .expectSpeech('t').expectBraille(lineText, { startIndex: 34, endIndex: 34 }) + .expectSpeech('t').expectBraille(lineOnLinkText, { startIndex: 34, endIndex: 34 }) + .call(moveByChar) + .expectSpeech('!') + .expectSpeech('Black, 100% opacity.') + .expectSpeech('Not link') + .expectSpeech('Not underline') + .expectBraille(lineText, {startIndex: 35, endIndex: 35 }) .replay(); }); @@ -487,8 +505,9 @@ .expectBraille(lineText, { startIndex: 1, endIndex: 1 }) .call(moveByChar) .expectSpeech('t') - .expectSpeech('Link start') - .expectSpeech('Underline start') + .expectSpeech('Blue, 100% opacity.') + .expectSpeech('Link') + .expectSpeech('Underline') .expectBraille(lineOnLinkText, { startIndex: 2, endIndex: 2 }) .call(moveByChar) .expectSpeech('e') @@ -498,8 +517,6 @@ .expectBraille(lineOnLinkText, { startIndex: 4, endIndex: 4 }) .call(moveByChar) .expectSpeech('t') - .expectSpeech('Link end') - .expectSpeech('Underline end') .expectBraille(lineOnLinkText, { startIndex: 5, endIndex: 5 }) .replay();
diff --git a/chrome/browser/resources/chromeos/chromevox/strings/chromevox_strings.grd b/chrome/browser/resources/chromeos/chromevox/strings/chromevox_strings.grd index 271e8a2..5a01cb8 100644 --- a/chrome/browser/resources/chromeos/chromevox/strings/chromevox_strings.grd +++ b/chrome/browser/resources/chromeos/chromevox/strings/chromevox_strings.grd
@@ -2989,80 +2989,58 @@ <message desc="Spoken when a user navigates to the end of a text match from a find in page." name="IDS_CHROMEVOX_TEXT_MATCH_END"> Text match end </message> - <message desc="Spoken when a user navigates to the beginning of subscript text." name="IDS_CHROMEVOX_SUBSCRIPT_START"> - Subscript start + + <message desc="Spoken to describe text that is superscript." name="IDS_CHROMEVOX_SUPERSCRIPT"> + Superscript </message> - <message desc="Spoken when a user navigates to the end of subscript text." name="IDS_CHROMEVOX_SUBSCRIPT_END"> - Subscript end + <message desc="Spoken to describe text that is not superscript." name="IDS_CHROMEVOX_NOT_SUPERSCRIPT"> + Not superscript </message> - <message desc="Spoken when a user navigates to the beginning of superscript text." name="IDS_CHROMEVOX_SUPERSCRIPT_START"> - Superscript start + <message desc="Spoken to describe text that is subscript." name="IDS_CHROMEVOX_SUBSCRIPT"> + Subscript </message> - <message desc="Spoken when a user navigates to the end of superscript text." name="IDS_CHROMEVOX_SUPERSCRIPT_END"> - Superscript end - </message> - <message desc="Spoken when a user navigates to the beginning of bolded text." name="IDS_CHROMEVOX_BOLD_START"> - Bold start - </message> - <message desc="Spoken when a user navigates to the end of bolded text." name="IDS_CHROMEVOX_BOLD_END"> - Bold end - </message> - <message desc="Spoken when a user navigates to the beginning of italic text." name="IDS_CHROMEVOX_ITALIC_START"> - Italic start - </message> - <message desc="Spoken when a user navigates to the end of italic text." name="IDS_CHROMEVOX_ITALIC_END"> - Italic end - </message> - <message desc="Spoken when a user navigates to the beginning of underline text." name="IDS_CHROMEVOX_UNDERLINE_START"> - Underline start - </message> - <message desc="Spoken when a user navigates to the end of underline text." name="IDS_CHROMEVOX_UNDERLINE_END"> - Underline end - </message> - <message desc="Spoken when a user navigates to the beginning of strike through text." name="IDS_CHROMEVOX_LINE_THROUGH_START"> - Strike through start - </message> - <message desc="Spoken when a user navigates to the end of strike through text." name="IDS_CHROMEVOX_LINE_THROUGH_END"> - Strike through end + <message desc="Spoken to describe text that is not subscript." name="IDS_CHROMEVOX_NOT_SUBSCRIPT"> + Not subscript </message> <message desc="Spoken to describe bolded text." name="IDS_CHROMEVOX_BOLD"> Bold </message> + <message desc="Spoken to describe non bolded text." name="IDS_CHROMEVOX_NOT_BOLD"> + Not bold + </message> <message desc="Spoken to describe italicized text." name="IDS_CHROMEVOX_ITALIC"> Italic </message> + <message desc="Spoken to describe non italicized text." name="IDS_CHROMEVOX_NOT_ITALIC"> + Not italic + </message> <message desc="Spoken to describe underlined text." name="IDS_CHROMEVOX_UNDERLINE"> Underline </message> + <message desc="Spoken to describe non underlined text." name="IDS_CHROMEVOX_NOT_UNDERLINE"> + Not underline + </message> <message desc="Spoken to describe line-through text." name="IDS_CHROMEVOX_LINETHROUGH"> Line through </message> - <message desc="Spoken when a user navigates to the beginning of a link's text." name="IDS_CHROMEVOX_LINK_START"> - Link start + <message desc="Spoken to describe non line-through text." name="IDS_CHROMEVOX_NOT_LINETHROUGH"> + Not line through </message> - <message desc="Spoken when a user navigates to the end of a link's text." name="IDS_CHROMEVOX_LINK_END"> - Link end + <message desc="Spoken when a user navigates to text and the link state changes" name="IDS_CHROMEVOX_LINK"> + Link </message> - - <message desc="Spoken when a user navigates to the beginning of a font family's text, e.g. 'Arial start'" name="IDS_CHROMEVOX_FONT_FAMILY_START"> - <ph name="font_family">$1<ex>Arial</ex></ph> start + <message desc="Spoken to describe non-linked text." name="IDS_CHROMEVOX_NOT_LINK"> + Not link </message> - <message desc="Spoken when a user navigates to the end of a font family's text, e.g. 'Arial end'" name="IDS_CHROMEVOX_FONT_FAMILY_END"> - <ph name="font_family">$1<ex>Arial</ex></ph> end + <message desc="Spoken when a user navigates to text and the font family changes, e.g. 'Font Arial'" name="IDS_CHROMEVOX_FONT_FAMILY"> + Font <ph name="font_family">$1<ex>Arial</ex></ph> </message> - <message desc="Spoken when a user navigates to the beginning of a font size's text, e.g. 'Size 12 start'" name="IDS_CHROMEVOX_FONT_SIZE_START"> - Size <ph name="font_size">$1<ex>12</ex></ph> start + <message desc="Spoken when a user navigates to text and the font size changes, e.g. 'Size 12'" name="IDS_CHROMEVOX_FONT_SIZE"> + Size <ph name="font_size">$1<ex>12</ex></ph> </message> - <message desc="Spoken when a user navigates to the end of a font size's text, e.g. 'Size 12 end'" name="IDS_CHROMEVOX_FONT_SIZE_END"> - Size <ph name="font_size">$1<ex>12</ex></ph> end + <message desc="Spoken when a user navigates to text and the font color changes, e.g. 'Red, 100% opacity'" name="IDS_CHROMEVOX_FONT_COLOR"> + <ph name="font_color">$1<ex>Red, 100% opacity</ex></ph> </message> - <message desc="Spoken when a user navigates to the beginning of a font color's text, e.g. 'Red, 100% opacity. start'" name="IDS_CHROMEVOX_FONT_COLOR_START"> - <ph name="font_color">$1<ex>Red, 100% opacity.</ex></ph> start - </message> - <message desc="Spoken when a user navigates to the end of a font color's text, e.g. 'Red, 100% opacity. end'" name="IDS_CHROMEVOX_FONT_COLOR_END"> - <ph name="font_color">$1<ex>Red, 100% opacity.</ex></ph> end - </message> - <message desc="Shown to a user when they press a braille keyboard command that requires on screen keyboard to be enabled." name="IDS_CHROMEVOX_ENABLE_VIRTUAL_KEYBOARD"> Please enable the on screen keyboard under status tray, accessibility to use extended braille commands. </message>
diff --git a/chrome/browser/resources/chromeos/login/oobe_screen_welcome.js b/chrome/browser/resources/chromeos/login/oobe_screen_welcome.js index 324c412..00e13fe 100644 --- a/chrome/browser/resources/chromeos/login/oobe_screen_welcome.js +++ b/chrome/browser/resources/chromeos/login/oobe_screen_welcome.js
@@ -7,39 +7,37 @@ */ login.createScreen('WelcomeScreen', 'connect', function() { - var CONTEXT_KEY_LOCALE = 'locale'; - var CONTEXT_KEY_INPUT_METHOD = 'input-method'; - var CONTEXT_KEY_TIMEZONE = 'timezone'; - return { - EXTERNAL_API: [], + EXTERNAL_API: + ['onInputMethodIdSetFromBackend', 'onTimezoneIdSetFromBackend'], /** @override */ decorate: function() { var welcomeScreen = $('oobe-welcome-md'); welcomeScreen.screen = this; - this.context.addObserver( - CONTEXT_KEY_INPUT_METHOD, function(inputMethodId) { - $('oobe-welcome-md').setSelectedKeyboard(inputMethodId); - }); - this.updateLocalizedContent(); }, + onInputMethodIdSetFromBackend: function(inputMethodId) { + $('oobe-welcome-md').setSelectedKeyboard(inputMethodId); + }, + + onTimezoneIdSetFromBackend: function(timezoneId) { + // Timezone change triggers a localized content update so we don't need to + // do anything here. + }, + onLanguageSelected_: function(languageId) { - this.context.set(CONTEXT_KEY_LOCALE, languageId); - this.commitContextChanges(); + chrome.send('WelcomeScreen.setLocaleId', [languageId]); }, onKeyboardSelected_: function(inputMethodId) { - this.context.set(CONTEXT_KEY_INPUT_METHOD, inputMethodId); - this.commitContextChanges(); + chrome.send('WelcomeScreen.setInputMethodId', [inputMethodId]); }, onTimezoneSelected_: function(timezoneId) { - this.context.set(CONTEXT_KEY_TIMEZONE, timezoneId); - this.commitContextChanges(); + chrome.send('WelcomeScreen.setTimezoneId', [timezoneId]); }, onBeforeShow: function(data) { @@ -70,7 +68,8 @@ $('oobe-welcome-md').updateLocalizedContent(); }, - /** Called when OOBE configuration is loaded. + /** + * Called when OOBE configuration is loaded. * @param {!OobeTypes.OobeConfiguration} configuration */ updateOobeConfiguration: function(configuration) {
diff --git a/chrome/browser/resources/omnibox/omnibox.html b/chrome/browser/resources/omnibox/omnibox.html index fd2ba67..ed263099 100644 --- a/chrome/browser/resources/omnibox/omnibox.html +++ b/chrome/browser/resources/omnibox/omnibox.html
@@ -167,11 +167,6 @@ placeholder="Enter filter (e.g. 'google', 'is:star', 'not:del') [Alt+G]" title="Checks each cell individually; i.e. filter text should not span multiple columns. Supports fuzzyness; each character of filter text must be present in the cell, either adjacent to the previous matched character, or at the start of a new word. Words are defined as being delimited by either capital letters, groups of digits, or non alpha characters. E.g. 'abc' matches 'abc', 'a big cat', 'a-bigCat', 'a very big cat', and 'an amBer cat'; but does not match 'abigcat' or 'an amber cat'. 'green rainbow' is matched by 'gre rain', but not by 'gre bow'. One exception is the first character, which may be matched mid-word. E.g. 'een rain' can also match 'green rainbow'. Boolean properties can be searched for via the property name prefixed by 'is:' or 'not:'. Boolean property names are: 'Can Be Default', 'Starred', 'Has Tab Match', 'Del', 'Prev', and 'Done'."> <div> - <span id="copy-text" class="row button" accesskey="x" - title="Copy visible table in text format. This is affected by the visibility of ouput; i.e. toggling 'Show all details' affects what will be copied."> - <i class="icon copy-icon"></i> - <span>Copy as te<span class="accesskey">x</span>t</span> - </span> <span id="download-json" class="row button" accesskey="n" title="Download responses in JSON format. This is not affected by the visibility of output and will include responses in their entirety as well as query and display inputs."> <i class="icon copy-icon"></i>
diff --git a/chrome/browser/resources/omnibox/omnibox.js b/chrome/browser/resources/omnibox/omnibox.js index 0270eb60..e9d25ecb 100644 --- a/chrome/browser/resources/omnibox/omnibox.js +++ b/chrome/browser/resources/omnibox/omnibox.js
@@ -98,7 +98,6 @@ 'filter-input-changed', e => omniboxOutput.updateFilterText(e.detail)); omniboxInput.addEventListener( 'import-json', e => exportDelegate.importJson(e.detail)); - omniboxInput.addEventListener('copy-text', () => exportDelegate.copyText()); omniboxInput.addEventListener( 'download-json', () => exportDelegate.downloadJson()); omniboxInput.addEventListener( @@ -133,10 +132,6 @@ this.omniboxOutput_.setResponsesHistory(importData.responsesHistory); } - copyText() { - ExportDelegate.copy_(this.omniboxOutput_.visibleTableText); - } - downloadJson() { /** @type {OmniboxExport} */ const exportObj = { @@ -149,12 +144,6 @@ ExportDelegate.download_(exportObj, fileName); } - /** @private @param {string} value */ - static copy_(value) { - navigator.clipboard.writeText(value).catch( - error => console.error('unable to copy to clipboard:', error)); - } - /** * @private * @param {Object} object
diff --git a/chrome/browser/resources/omnibox/omnibox_element.js b/chrome/browser/resources/omnibox/omnibox_element.js index 2ca4b55f..ab39bbc 100644 --- a/chrome/browser/resources/omnibox/omnibox_element.js +++ b/chrome/browser/resources/omnibox/omnibox_element.js
@@ -38,9 +38,8 @@ } /** - * Get an element that's known to exist by query. We use this instead of just - * calling querySelector because this lets us satisfy the JSCompiler type - * system. + * Get an element that's known to exist by query. Unlike querySelector, this + * satisfies the JSCompiler type system. * @private * @param {string} query * @param {!Node=} context
diff --git a/chrome/browser/resources/omnibox/omnibox_input.js b/chrome/browser/resources/omnibox/omnibox_input.js index 5563171..d5fbf07 100644 --- a/chrome/browser/resources/omnibox/omnibox_input.js +++ b/chrome/browser/resources/omnibox/omnibox_input.js
@@ -76,8 +76,6 @@ this.$$('#filter-text') .addEventListener('input', this.onFilterInputsChanged_.bind(this)); - this.$$('#copy-text') - .addEventListener('click', this.onCopyText_.bind(this)); this.$$('#download-json') .addEventListener('click', this.onDownloadJson_.bind(this)); @@ -234,11 +232,6 @@ } /** @private */ - onCopyText_() { - this.dispatchEvent(new CustomEvent('copy-text')); - } - - /** @private */ onDownloadJson_() { this.dispatchEvent(new CustomEvent('download-json')); }
diff --git a/chrome/browser/resources/omnibox/omnibox_output.js b/chrome/browser/resources/omnibox/omnibox_output.js index ea91a35..7a72ca3 100644 --- a/chrome/browser/resources/omnibox/omnibox_output.js +++ b/chrome/browser/resources/omnibox/omnibox_output.js
@@ -163,13 +163,6 @@ return this.resultsGroups_.flatMap( resultsGroup => resultsGroup.autocompleteMatches); } - - /** @return {string} */ - get visibleTableText() { - return this.resultsGroups_ - .flatMap(resultsGroup => resultsGroup.visibleText) - .join('\n'); - } } /** @@ -329,12 +322,6 @@ .concat(this.individualResultsList) .flatMap(results => results.autocompleteMatches); } - - /** @return {!Array<string>} */ - get visibleText() { - return Array.from(this.shadowRoot.querySelectorAll(':host > :not(style)')) - .map(child => child.innerText); - } } class OutputResultsDetails extends OmniboxElement { @@ -581,13 +568,13 @@ constructor() { super(); - // We use margin-right on .pair-item's to separate them. To compensate, + // margin-right is used on .pair-item's to separate them. To compensate, // .pair-container has negative margin-right. This means .pair-container's // overflow their parent. Overflowing a table cell is problematic, as 1) // scroll bars overlay adjacent cell, and 2) the page receives a // horizontal scroll bar when the right most column overflows. To avoid - // this, we ensure the parent of any element with negative margins (e.g. - // .pair-container) is not a table cell; hence, we introduce + // this, the parent of any element with negative margins (e.g. + // .pair-container) must not be a table cell; hence, the use of // scrollContainer_. // Flex gutters may provide a cleaner alternative once implemented. // https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Flexible_Box_Layout/Mastering_Wrapping_of_Flex_Items#Creating_gutters_between_items @@ -691,17 +678,67 @@ /** @private @override */ render_() { - this.contents_.textContent = this.values_[1]; - this.description_.textContent = this.values_[2]; - this.answer_.textContent = this.values_[3]; - this.imageUrl_.textContent = this.values_[0]; - this.imageUrl_.href = this.values_[0]; + // TODO (manukh) Wrap this line when Clang is updated, + // https://b.corp.google.com/126708256 . + const [image, contents, description, answer, contentsClassification, descriptionClassification] = + this.values_; + OutputAnswerProperty.renderClassifiedText_( + this.contents_, /** @type {string} */ (contents), + /** @type {!Array<!mojom.ACMatchClassification>} */ + (contentsClassification)); + OutputAnswerProperty.renderClassifiedText_( + this.description_, /** @type {string} */ (description), + /** @type {!Array<!mojom.ACMatchClassification>} */ + (descriptionClassification)); + this.answer_.textContent = answer; + this.imageUrl_.textContent = image; + this.imageUrl_.href = image; } /** @override @return {string} */ get text() { return this.values_.join('.'); } + + /** + * @private + * @param {!Element} container + * @param {string} string + * @param {!Array<!mojom.ACMatchClassification>} classes + */ + static renderClassifiedText_(container, string, classes) { + clearChildren(container); + OutputAnswerProperty.classify(string + '\n', classes) + .map( + ({string, style}) => OutputJsonProperty.renderJsonWord( + string, OutputAnswerProperty.styleToClasses_(style))) + .forEach(span => container.appendChild(span)); + } + + /** + * @param {string} string + * @param {!Array<!mojom.ACMatchClassification>} classes + * @return {!Array<{string: string, style: number}>} + */ + static classify(string, classes) { + return classes.map(({offset, style}, i) => { + const end = classes[i + 1] ? classes[i + 1].offset : string.length; + return {string: string.substring(offset, end), style}; + }); + } + + /** + * @private + * @param {number} style + * @return {!Array<string>} + */ + static styleToClasses_(style) { + // Maps the bitmask enum AutocompleteMatch::ACMatchClassification::Style + // to strings. See autocomplete_match.h for more details. + // E.g., maps the style 5 to classes ['style-url', 'style-dim']. + return ['style-url', 'style-match', 'style-dim'].filter( + (_, i) => (style >> i) % 2); + } } class OutputBooleanProperty extends OutputProperty { @@ -739,7 +776,7 @@ this.text.split(/("(?:[^"\\]|\\.)*":?|\w+)/) .map(word => { return OutputJsonProperty.renderJsonWord( - word, OutputJsonProperty.classifyJsonWord(word)); + word, [OutputJsonProperty.classifyJsonWord(word)]); }) .forEach(jsonSpan => this.pre_.appendChild(jsonSpan)); } @@ -751,14 +788,12 @@ /** * @param {string} word - * @param {string|undefined} cls + * @param {!Array<string>} classes * @return {!Element} */ - static renderJsonWord(word, cls) { + static renderJsonWord(word, classes) { const span = document.createElement('span'); - if (cls) { - span.classList.add(cls); - } + span.classList.add(...classes); span.textContent = word; return span; } @@ -792,9 +827,9 @@ clearChildren(this.pre_); this.value.forEach(({key, value}) => { this.pre_.appendChild( - OutputJsonProperty.renderJsonWord(key + ': ', 'key')); + OutputJsonProperty.renderJsonWord(key + ': ', ['key'])); this.pre_.appendChild( - OutputJsonProperty.renderJsonWord(value + '\n', 'number')); + OutputJsonProperty.renderJsonWord(value + '\n', ['number'])); }); } @@ -888,7 +923,7 @@ * of digits, or non alpha characters. * E.g., `https://google.com/the-dog-ate-134pies` will be split to: * https, :, /, /, google, ., com, /, the, -, dog, -, ate, -, 134, pies - * We don't use `Array.split`, because we want to group digits, e.g. 134. + * This differs from `Array.split` in that this groups digits, e.g. 134. * @private * @param {string} text * @return {!Array<string>} @@ -959,9 +994,14 @@ new Column( ['Contents', 'Description', 'Answer'], '', 'contentsAndDescription', true, - 'Contents & Description & Answer\nThe text that is presented ' + - 'identifying the result. / The page title of the result.', - ['image', 'contents', 'description', 'answer'], OutputAnswerProperty), + 'Contents & Description & Answer\nURL classifications are styled ' + + 'blue.\nMATCH classifications are styled bold.\nDIM ' + + 'classifications are styled with a gray background.', + [ + 'image', 'contents', 'description', 'answer', 'contentsClass', + 'descriptionClass' + ], + OutputAnswerProperty), new Column( ['D'], '', 'allowedToBeDefaultMatch', true, 'Can be Default\nA green checkmark indicates that the result can be ' +
diff --git a/chrome/browser/resources/omnibox/output_results_group.css b/chrome/browser/resources/omnibox/output_results_group.css index 0fae6a1..f80ece9 100644 --- a/chrome/browser/resources/omnibox/output_results_group.css +++ b/chrome/browser/resources/omnibox/output_results_group.css
@@ -65,9 +65,9 @@ .body tr td pre.json { /* Browsers base rem font sizes on 16px, except for monospace fonts which use - a base size of 13px. Whereas we set the size to .75rem for the rest of the - table (.75 * 16px = 12px), we must set the size to 12/13rem for pre's - (12/13 * 13px = 12px) in order to have a consistent 12px across the table. */ + a base size of 13px. Whereas the rest of the table has size set to .75rem + (.75 * 16px = 12px), pre's must have size 12/13rem (12/13 * 13px = 12px) in + order to have a consistent 12px across the table. */ font-size: .9231rem; margin: 0; white-space: pre-wrap; @@ -111,10 +111,6 @@ color: green; } -.header-contents-and-description .header-container :first-child { - color: blue; -} - .header-contents-and-description .header-container :nth-child(3) { color: orange; } @@ -164,10 +160,24 @@ height: 28px; } -.cell-contents-and-description .pair-item.contents { +.cell-contents-and-description .pair-item.contents::after { + color: #555; + content: '-'; + margin-inline-start: 15px; +} + +.cell-contents-and-description .style-url { color: blue; } +.cell-contents-and-description .style-match { + font-weight: bold; +} + +.cell-contents-and-description .style-dim { + background: #eee; +} + .cell-contents-and-description .pair-item.answer { color: orange; }
diff --git a/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog.html b/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog.html index 834d691..d41c1b4 100644 --- a/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog.html +++ b/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog.html
@@ -158,8 +158,7 @@ </paper-button> <paper-button id="addPrinterButton" class="action-button" on-click="addPressed_" - disabled="[[!canAddPrinter_(newPrinter.printerName, - newPrinter.printerAddress)]]"> + disabled="[[!canAddPrinter_(newPrinter.*)]]"> $i18n{addPrinterButtonText} </paper-button> </div>
diff --git a/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog.js b/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog.js index 9b97ab7..8864868 100644 --- a/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog.js +++ b/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog.js
@@ -198,13 +198,11 @@ }, /** - * @param {string} name - * @param {string} address * @return {boolean} Whether the add printer button is enabled. * @private */ - canAddPrinter_: function(name, address) { - return settings.printing.isNameAndAddressValid(name, address); + canAddPrinter_: function() { + return settings.printing.isNameAndAddressValid(this.newPrinter); }, });
diff --git a/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog_util.js b/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog_util.js index 398b780..cf9a0b60 100644 --- a/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog_util.js +++ b/chrome/browser/resources/settings/printing_page/cups_add_printer_dialog_util.js
@@ -8,17 +8,36 @@ cr.define('settings.printing', function() { /** + * @param {string} protocol + * @return {boolean} Whether |protocol| is a network protocol + */ + function isNetworkProtocol(protocol) { + return ['ipp', 'ipps', 'http', 'https', 'socket', 'lpd'].includes(protocol); + } + + /** * Returns true if the printer's name and address is valid. This function * uses regular expressions to determine whether the provided printer name * and address are valid. Address can be either an ipv4/6 address or a * hostname followed by an optional port. * NOTE: The regular expression for hostnames will allow hostnames that are * over 255 characters. - * @param {string} name - * @param {string} address + * @param {CupsPrinterInfo} printer * @return {boolean} */ - function isNameAndAddressValid(name, address) { + function isNameAndAddressValid(printer) { + if (!printer) { + return false; + } + + const name = printer.printerName; + const address = printer.printerAddress; + + if (!isNetworkProtocol(printer.printerProtocol) && !!name) { + // We do not need to verify the address of a non-network printer. + return true; + } + if (!name || !address) { return false; } @@ -66,6 +85,7 @@ } return { + isNetworkProtocol: isNetworkProtocol, isNameAndAddressValid: isNameAndAddressValid, isPPDInfoValid: isPPDInfoValid, };
diff --git a/chrome/browser/resources/settings/printing_page/cups_edit_printer_dialog.js b/chrome/browser/resources/settings/printing_page/cups_edit_printer_dialog.js index c9c8d5a..17d358c 100644 --- a/chrome/browser/resources/settings/printing_page/cups_edit_printer_dialog.js +++ b/chrome/browser/resources/settings/printing_page/cups_edit_printer_dialog.js
@@ -39,7 +39,7 @@ ], /** @override */ - ready: function() { + attached: function() { settings.CupsPrintersBrowserProxyImpl.getInstance() .getPrinterPpdManufacturerAndModel(this.activePrinter.printerId) .then( @@ -135,7 +135,7 @@ * @private */ isNetworkProtocol_: function(protocol) { - return ['ipp', 'ipps', 'http', 'https', 'socket', 'lpd'].includes(protocol); + return settings.printing.isNetworkProtocol(protocol); }, /** @@ -143,9 +143,7 @@ * @private */ canSavePrinter_: function() { - return settings.printing.isNameAndAddressValid( - this.activePrinter.printerName, - this.activePrinter.printerAddress) && + return settings.printing.isNameAndAddressValid(this.activePrinter) && settings.printing.isPPDInfoValid( this.activePrinter.ppdManufacturer, this.activePrinter.ppdModel, this.activePrinter.printerPPDPath);
diff --git a/chrome/browser/resources/settings/printing_page/cups_set_manufacturer_model_behavior.js b/chrome/browser/resources/settings/printing_page/cups_set_manufacturer_model_behavior.js index f9bd1561..9b9355fb 100644 --- a/chrome/browser/resources/settings/printing_page/cups_set_manufacturer_model_behavior.js +++ b/chrome/browser/resources/settings/printing_page/cups_set_manufacturer_model_behavior.js
@@ -71,7 +71,7 @@ // Reset model if manufacturer is changed. this.set('activePrinter.ppdModel', ''); this.modelList = []; - if (manufacturer.length != 0) { + if (!!manufacturer && manufacturer.length != 0) { settings.CupsPrintersBrowserProxyImpl.getInstance() .getCupsPrinterModelsList(manufacturer) .then(this.modelListChanged_.bind(this));
diff --git a/chrome/browser/ssl/ssl_error_handler.cc b/chrome/browser/ssl/ssl_error_handler.cc index 183ce86a..e804016 100644 --- a/chrome/browser/ssl/ssl_error_handler.cc +++ b/chrome/browser/ssl/ssl_error_handler.cc
@@ -34,6 +34,7 @@ #include "chrome/common/pref_names.h" #include "components/network_time/network_time_tracker.h" #include "components/prefs/pref_service.h" +#include "components/security_interstitials/content/security_interstitial_page.h" #include "components/security_interstitials/core/ssl_error_ui.h" #include "components/ssl_errors/error_classification.h" #include "components/ssl_errors/error_info.h" @@ -560,9 +561,9 @@ if (blocking_page_ready_callback_.is_null()) { interstitial_page->Show(); } else { - std::move(blocking_page_ready_callback_) - .Run(std::unique_ptr<security_interstitials::SecurityInterstitialPage>( - interstitial_page)); + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::BindOnce(std::move(blocking_page_ready_callback_), + base::WrapUnique(interstitial_page))); } }
diff --git a/chrome/browser/ssl/ssl_error_handler.h b/chrome/browser/ssl/ssl_error_handler.h index 51ea1ed..1da4cd0 100644 --- a/chrome/browser/ssl/ssl_error_handler.h +++ b/chrome/browser/ssl/ssl_error_handler.h
@@ -129,6 +129,8 @@ // |blocking_page_ready_callback| is null, this function will create a // blocking page and call Show() on it. Otherwise, this function creates an // interstitial and passes it to |blocking_page_ready_callback|. + // |blocking_page_ready_callback| is guaranteed not to be called + // synchronously. static void HandleSSLError( content::WebContents* web_contents, int cert_error,
diff --git a/chrome/browser/ssl/ssl_error_navigation_throttle.cc b/chrome/browser/ssl/ssl_error_navigation_throttle.cc index 08a8587..006cc7c4 100644 --- a/chrome/browser/ssl/ssl_error_navigation_throttle.cc +++ b/chrome/browser/ssl/ssl_error_navigation_throttle.cc
@@ -108,19 +108,16 @@ const net::SSLInfo& ssl_info, const GURL& request_url, std::unique_ptr<SSLCertReporter> ssl_cert_reporter) { - // We don't know whether SSLErrorHandler will call the ShowInterstitial() - // callback synchronously, so we post a task that will run after the caller - // defers the navigation. This ensures that ShowInterstitial() can always - // safely call CancelDeferredNavigation(). - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, - base::BindOnce( - std::move(handle_ssl_error_callback), web_contents, - net::MapCertStatusToNetError(cert_status), ssl_info, request_url, - false /* expired_previous_decision */, std::move(ssl_cert_reporter), - base::Callback<void(content::CertificateRequestResultType)>(), - base::BindOnce(&SSLErrorNavigationThrottle::ShowInterstitial, - weak_ptr_factory_.GetWeakPtr()))); + // It is safe to call this without posting because SSLErrorHandler will always + // call ShowInterstitial asynchronously, giving the throttle time to defer the + // navigation. + std::move(handle_ssl_error_callback) + .Run(web_contents, net::MapCertStatusToNetError(cert_status), ssl_info, + request_url, false /* expired_previous_decision */, + std::move(ssl_cert_reporter), + base::Callback<void(content::CertificateRequestResultType)>(), + base::BindOnce(&SSLErrorNavigationThrottle::ShowInterstitial, + weak_ptr_factory_.GetWeakPtr())); } void SSLErrorNavigationThrottle::ShowInterstitial(
diff --git a/chrome/browser/sync/test/integration/two_client_passwords_sync_test.cc b/chrome/browser/sync/test/integration/two_client_passwords_sync_test.cc index e977bbd..5787e6e4 100644 --- a/chrome/browser/sync/test/integration/two_client_passwords_sync_test.cc +++ b/chrome/browser/sync/test/integration/two_client_passwords_sync_test.cc
@@ -17,6 +17,7 @@ #include "chrome/browser/sync/test/integration/profile_sync_service_harness.h" #include "chrome/browser/sync/test/integration/sync_integration_test_util.h" #include "chrome/browser/sync/test/integration/sync_test.h" +#include "chrome/browser/sync/test/integration/updated_progress_marker_checker.h" #include "components/sync/driver/sync_driver_switches.h" #include "components/sync/engine/cycle/sync_cycle_snapshot.h" #include "components/sync/engine/model_safe_worker.h" @@ -25,6 +26,7 @@ using passwords_helper::AllProfilesContainSamePasswordForms; using passwords_helper::AllProfilesContainSamePasswordFormsAsVerifier; using passwords_helper::CreateTestPasswordForm; +using passwords_helper::GetLogins; using passwords_helper::GetPasswordCount; using passwords_helper::GetPasswordStore; using passwords_helper::GetVerifierPasswordCount; @@ -126,6 +128,57 @@ // Flaky on TSAN: crbug.com/915219 #if defined(THREAD_SANITIZER) +#define MAYBE_MergeWithTheMostRecent DISABLED_MergeWithTheMostRecent +#else +#define MAYBE_MergeWithTheMostRecent MergeWithTheMostRecent +#endif +IN_PROC_BROWSER_TEST_P(TwoClientPasswordsSyncTest, + E2E_ENABLED(MAYBE_MergeWithTheMostRecent)) { + // Setup the test to have Form 0 and Form 1 added on both clients. Form 0 is + // more recent on Client 0, and Form 1 is more recent on Client 1. They should + // be merged such that recent passwords are chosen. + + base::Time now = base::Time::Now(); + base::Time yesterday = now - base::TimeDelta::FromDays(1); + + PasswordForm form0_recent = CreateTestPasswordForm(0); + form0_recent.date_created = now; + PasswordForm form0_old = CreateTestPasswordForm(0); + form0_old.date_created = yesterday; + + PasswordForm form1_recent = CreateTestPasswordForm(1); + form1_recent.date_created = now; + PasswordForm form1_old = CreateTestPasswordForm(1); + form1_old.date_created = yesterday; + + ASSERT_TRUE(SetupClients()) << "SetupClients() failed."; + + // Add the passwords to Client 0. + AddLogin(GetPasswordStore(0), form0_recent); + AddLogin(GetPasswordStore(0), form1_old); + // Enable sync on Client 0 and wait until they are committed. + ASSERT_TRUE(GetClient(0)->SetupSync()) << "GetClient(0)->SetupSync() failed."; + ASSERT_TRUE(UpdatedProgressMarkerChecker(GetSyncService(0)).Wait()); + + // Add the passwords to Client 1. + AddLogin(GetPasswordStore(1), form0_old); + AddLogin(GetPasswordStore(1), form1_recent); + + // Enable sync on Client 1 and wait until all passwords are merged. + ASSERT_TRUE(GetClient(1)->SetupSync()) << "GetClient(1)->SetupSync() failed."; + ASSERT_TRUE(SamePasswordFormsChecker().Wait()); + + // There should be only 2 passwords. + EXPECT_EQ(2, GetPasswordCount(0)); + // All passwords should be the recent ones. + for (const std::unique_ptr<PasswordForm>& form : + GetLogins(GetPasswordStore(0))) { + EXPECT_EQ(now, form->date_created); + } +} + +// Flaky on TSAN: crbug.com/915219 +#if defined(THREAD_SANITIZER) #define MAYBE_SetPassphraseAndAddPassword DISABLED_SetPassphraseAndAddPassword #else #define MAYBE_SetPassphraseAndAddPassword SetPassphraseAndAddPassword
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index 4a475c4c..eeb0938c 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -2542,7 +2542,6 @@ "views/frame/toolbar_button_provider.h", "views/frame/top_container_view.cc", "views/frame/top_container_view.h", - "views/frame/top_controls_slide_controller.cc", "views/frame/top_controls_slide_controller.h", "views/frame/web_contents_close_handler.cc", "views/frame/web_contents_close_handler.h",
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_browsertest.cc b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_browsertest.cc index 55de3a93..2fc9b9aa8 100644 --- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller_browsertest.cc +++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller_browsertest.cc
@@ -13,6 +13,7 @@ #include "ash/public/cpp/shelf_model.h" #include "ash/public/cpp/window_properties.h" #include "ash/shelf/app_list_button.h" +#include "ash/shelf/overflow_button.h" #include "ash/shelf/shelf.h" #include "ash/shelf/shelf_app_button.h" #include "ash/shelf/shelf_view.h" @@ -1628,6 +1629,7 @@ ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow(), gfx::Point()); ash::ShelfViewTestAPI test(GetPrimaryShelfView()); + const ash::ShelfView* shelf_view = GetPrimaryShelfView(); test.SetAnimationDuration(1); // Speed up animations for test. // Create a known application and check that we have 3 items in the shelf. CreateShortcut("app1"); @@ -1688,10 +1690,10 @@ // Test #6: Ripping out the application when the overflow button exists. // After ripping out, overflow button should be removed. int items_added = 0; - EXPECT_FALSE(test.IsOverflowButtonVisible()); + EXPECT_FALSE(shelf_view->GetOverflowButton()->visible()); // Create fake app shortcuts until overflow button is created. - while (!test.IsOverflowButtonVisible()) { + while (!shelf_view->GetOverflowButton()->visible()) { std::string fake_app_id = base::StringPrintf("fake_app_%d", items_added); PinFakeApp(fake_app_id); test.RunMessageLoopUntilAnimationsDone(); @@ -1713,12 +1715,12 @@ // however correctly done and the item will get removed (as well as the // overflow button). EXPECT_EQ(total_count - 1, shelf_model()->item_count()); - EXPECT_TRUE(test.IsOverflowButtonVisible()); + EXPECT_TRUE(shelf_view->GetOverflowButton()->visible()); // Rip off again and the overflow button should has disappeared. RipOffItemIndex(app_index, &generator, &test, RIP_OFF_ITEM); EXPECT_EQ(total_count - 2, shelf_model()->item_count()); - EXPECT_FALSE(test.IsOverflowButtonVisible()); + EXPECT_FALSE(shelf_view->GetOverflowButton()->visible()); } // TODO(crbug.com/759779, crbug.com/819386): add back |ClickItem|.
diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc index 0694901..9147b20 100644 --- a/chrome/browser/ui/views/frame/browser_view.cc +++ b/chrome/browser/ui/views/frame/browser_view.cc
@@ -166,6 +166,7 @@ #include "ash/public/cpp/window_pin_type.h" #include "chrome/browser/ui/ash/ash_util.h" #include "chrome/browser/ui/ash/window_properties.h" +#include "chrome/browser/ui/views/frame/top_controls_slide_controller_chromeos.h" #include "chrome/browser/ui/views/location_bar/intent_picker_view.h" #include "chrome/grit/chrome_unscaled_resources.h" #include "ui/base/ui_base_features.h" @@ -2466,10 +2467,13 @@ void BrowserView::InitViews() { // TopControlsSlideController must be initialized here in InitViews() rather // than Init() as it depends on the browser frame being ready. +#if defined(OS_CHROMEOS) if (IsBrowserTypeNormal()) { DCHECK(frame_); - top_controls_slide_controller_ = CreateTopControlsSlideController(this); + top_controls_slide_controller_ = + std::make_unique<TopControlsSlideControllerChromeOS>(this); } +#endif GetWidget()->AddObserver(this);
diff --git a/chrome/browser/ui/views/frame/top_controls_slide_controller.cc b/chrome/browser/ui/views/frame/top_controls_slide_controller.cc deleted file mode 100644 index 565774b..0000000 --- a/chrome/browser/ui/views/frame/top_controls_slide_controller.cc +++ /dev/null
@@ -1,21 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/ui/views/frame/top_controls_slide_controller.h" - -#if defined(OS_CHROMEOS) -#include "base/feature_list.h" -#include "chrome/browser/ui/views/frame/top_controls_slide_controller_chromeos.h" -#include "chrome/common/chrome_features.h" -#endif // defined(OS_CHROMEOS) - -std::unique_ptr<TopControlsSlideController> CreateTopControlsSlideController( - BrowserView* browser_view) { -#if defined(OS_CHROMEOS) - if (base::FeatureList::IsEnabled(features::kSlideTopChromeWithPageScrolls)) - return std::make_unique<TopControlsSlideControllerChromeOS>(browser_view); -#endif // defined(OS_CHROMEOS) - - return nullptr; -}
diff --git a/chrome/browser/ui/views/frame/top_controls_slide_controller.h b/chrome/browser/ui/views/frame/top_controls_slide_controller.h index e243e65..208e949 100644 --- a/chrome/browser/ui/views/frame/top_controls_slide_controller.h +++ b/chrome/browser/ui/views/frame/top_controls_slide_controller.h
@@ -9,8 +9,6 @@ #include "base/macros.h" -class BrowserView; - namespace content { class WebContents; } // namespace content @@ -59,9 +57,4 @@ DISALLOW_COPY_AND_ASSIGN(TopControlsSlideController); }; -// If the feature is enabled, returns an instance of the controller, otherwise -// returns nullptr. -std::unique_ptr<TopControlsSlideController> CreateTopControlsSlideController( - BrowserView* browser_view); - #endif // CHROME_BROWSER_UI_VIEWS_FRAME_TOP_CONTROLS_SLIDE_CONTROLLER_H_
diff --git a/chrome/browser/ui/views/frame/top_controls_slide_controller_chromeos_browsertest.cc b/chrome/browser/ui/views/frame/top_controls_slide_controller_chromeos_browsertest.cc index a7f5040..088b8b21 100644 --- a/chrome/browser/ui/views/frame/top_controls_slide_controller_chromeos_browsertest.cc +++ b/chrome/browser/ui/views/frame/top_controls_slide_controller_chromeos_browsertest.cc
@@ -17,7 +17,6 @@ #include "base/command_line.h" #include "base/path_service.h" #include "base/strings/safe_sprintf.h" -#include "base/test/scoped_feature_list.h" #include "cc/base/math_util.h" #include "chrome/browser/chromeos/accessibility/accessibility_manager.h" #include "chrome/browser/permissions/permission_request_impl.h" @@ -27,7 +26,6 @@ #include "chrome/browser/ui/views/bookmarks/bookmark_bar_view.h" #include "chrome/browser/ui/views/frame/browser_view.h" #include "chrome/browser/ui/views/frame/top_container_view.h" -#include "chrome/common/chrome_features.h" #include "chrome/common/url_constants.h" #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/ui_test_utils.h" @@ -258,13 +256,6 @@ return test_controller_; } - // InProcessBrowserTest: - void SetUp() override { - scoped_feature_list_.InitAndEnableFeature( - features::kSlideTopChromeWithPageScrolls); - InProcessBrowserTest::SetUp(); - } - void SetUpDefaultCommandLine(base::CommandLine* command_line) override { InProcessBrowserTest::SetUpDefaultCommandLine(command_line);
diff --git a/chrome/browser/ui/views/profiles/badged_profile_photo.cc b/chrome/browser/ui/views/profiles/badged_profile_photo.cc index 193a7151..a63436d 100644 --- a/chrome/browser/ui/views/profiles/badged_profile_photo.cc +++ b/chrome/browser/ui/views/profiles/badged_profile_photo.cc
@@ -10,6 +10,7 @@ #include "ui/gfx/color_palette.h" #include "ui/gfx/image/image.h" #include "ui/gfx/paint_vector_icon.h" +#include "ui/native_theme/native_theme.h" #include "ui/views/controls/image_view.h" namespace { @@ -54,22 +55,33 @@ // Helpers -------------------------------------------------------------------- gfx::ImageSkia ImageForBadgeType(BadgedProfilePhoto::BadgeType badge_type) { + ui::NativeTheme* native_theme = ui::NativeTheme::GetInstanceForNativeUi(); switch (badge_type) { case BadgedProfilePhoto::BADGE_TYPE_SUPERVISOR: - return gfx::CreateVectorIcon(kSupervisorAccountCircleIcon, kBadgeIconSize, - gfx::kChromeIconGrey); + return gfx::CreateVectorIcon( + kSupervisorAccountCircleIcon, kBadgeIconSize, + native_theme->GetSystemColor( + ui::NativeTheme::kColorId_DefaultIconColor)); case BadgedProfilePhoto::BADGE_TYPE_CHILD: - return gfx::CreateVectorIcon(kAccountChildCircleIcon, kBadgeIconSize, - gfx::kChromeIconGrey); + return gfx::CreateVectorIcon( + kAccountChildCircleIcon, kBadgeIconSize, + native_theme->GetSystemColor( + ui::NativeTheme::kColorId_DefaultIconColor)); case BadgedProfilePhoto::BADGE_TYPE_SYNC_COMPLETE: return gfx::CreateVectorIcon(kSyncCircleIcon, kBadgeIconSize, - gfx::kGoogleGreen700); + native_theme->SystemDarkModeEnabled() + ? gfx::kGoogleGreen300 + : gfx::kGoogleGreen700); case BadgedProfilePhoto::BADGE_TYPE_SYNC_ERROR: return gfx::CreateVectorIcon(kSyncErrorCircleIcon, kBadgeIconSize, - gfx::kGoogleRed700); + native_theme->SystemDarkModeEnabled() + ? gfx::kGoogleRed300 + : gfx::kGoogleRed700); case BadgedProfilePhoto::BADGE_TYPE_SYNC_PAUSED: return gfx::CreateVectorIcon(kSyncPausedCircleIcon, kBadgeIconSize, - gfx::kGoogleBlue500); + native_theme->SystemDarkModeEnabled() + ? gfx::kGoogleBlue300 + : gfx::kGoogleBlue500); case BadgedProfilePhoto::BADGE_TYPE_SYNC_DISABLED: return gfx::CreateVectorIcon(kSyncCircleIcon, kBadgeIconSize, gfx::kGoogleGrey400);
diff --git a/chrome/browser/ui/views/tabs/tab_strip.cc b/chrome/browser/ui/views/tabs/tab_strip.cc index 5bf670c..1935048 100644 --- a/chrome/browser/ui/views/tabs/tab_strip.cc +++ b/chrome/browser/ui/views/tabs/tab_strip.cc
@@ -2250,9 +2250,7 @@ const SkColor inactive_fg = GetTabForegroundColor(TAB_INACTIVE, inactive_bg); // The contrast ratio for the separator between inactive tabs. - // In the default color scheme, this corresponds to a separator opacity of - // 0.46. - constexpr float kTabSeparatorContrast = 1.84f; + constexpr float kTabSeparatorContrast = 3.0f; const SkAlpha separator_alpha = get_alpha(inactive_fg, kTabSeparatorContrast); separator_color_ = color_utils::AlphaBlend(inactive_fg, inactive_bg, separator_alpha);
diff --git a/chrome/browser/ui/views/toolbar/browser_app_menu_button.cc b/chrome/browser/ui/views/toolbar/browser_app_menu_button.cc index b90334f..0f15bf93 100644 --- a/chrome/browser/ui/views/toolbar/browser_app_menu_button.cc +++ b/chrome/browser/ui/views/toolbar/browser_app_menu_button.cc
@@ -74,10 +74,12 @@ class PulsingInkDropMask : public gfx::AnimationDelegate, public views::InkDropMask { public: - PulsingInkDropMask(const gfx::Size& layer_size, + PulsingInkDropMask(views::View* layer_container, + const gfx::Size& layer_size, float normal_corner_radius, float max_inset) : views::InkDropMask(layer_size), + layer_container_(layer_container), normal_corner_radius_(normal_corner_radius), max_inset_(max_inset), throb_animation_(this) { @@ -109,8 +111,18 @@ void AnimationProgressed(const gfx::Animation* animation) override { DCHECK_EQ(animation, &throb_animation_); layer()->SchedulePaint(gfx::Rect(layer()->size())); + + // This is a workaround for crbug.com/935808: for scale factors >1, + // invalidating the mask layer doesn't cause the whole layer to be repainted + // on screen. TODO(crbug.com/935808): remove this workaround once the bug is + // fixed. + layer_container_->SchedulePaint(); } + // The View that contains the InkDrop layer we're masking. This must outlive + // our instance. + views::View* const layer_container_; + // Normal corner radius of the ink drop without animation. This is also the // corner radius at the largest instant of the animation. const float normal_corner_radius_; @@ -382,9 +394,9 @@ #if BUILDFLAG(ENABLE_DESKTOP_IN_PRODUCT_HELP) if (promo_feature_) { const float corner_radius = height() / 2.0f; - return std::make_unique<PulsingInkDropMask>(ink_drop_container()->size(), - corner_radius, - kFeaturePromoPulseInsetDip); + return std::make_unique<PulsingInkDropMask>( + ink_drop_container(), ink_drop_container()->size(), corner_radius, + kFeaturePromoPulseInsetDip); } #endif
diff --git a/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc b/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc index 1e8e7eb..f6cec78 100644 --- a/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc +++ b/chrome/browser/ui/webui/chromeos/login/oobe_ui.cc
@@ -320,9 +320,10 @@ AddScreenHandler( std::make_unique<UpdateScreenHandler>(js_calls_container_.get())); - if (display_type_ == kOobeDisplay) + if (display_type_ == kOobeDisplay) { AddScreenHandler(std::make_unique<WelcomeScreenHandler>( js_calls_container_.get(), core_handler_)); + } AddScreenHandler(std::make_unique<NetworkScreenHandler>( js_calls_container_.get(), core_handler_));
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 cd2fb4c..7df979a 100644 --- a/chrome/browser/ui/webui/chromeos/login/welcome_screen_handler.cc +++ b/chrome/browser/ui/webui/chromeos/login/welcome_screen_handler.cc
@@ -109,6 +109,15 @@ core_oobe_view_->ReloadContent(localized_strings); } +void WelcomeScreenHandler::SetInputMethodId( + const std::string& input_method_id) { + CallJS("login.WelcomeScreen.onInputMethodIdSetFromBackend", input_method_id); +} + +void WelcomeScreenHandler::SetTimezoneId(const std::string& timezone_id) { + CallJS("login.WelcomeScreen.onTimezoneIdSetFromBackend", timezone_id); +} + // WelcomeScreenHandler, BaseScreenHandler implementation: -------------------- void WelcomeScreenHandler::DeclareLocalizedValues( @@ -156,6 +165,15 @@ builder->Add("timezoneButtonText", IDS_TIMEZONE_BUTTON_TEXT); } +void WelcomeScreenHandler::DeclareJSCallbacks() { + AddCallback("WelcomeScreen.setLocaleId", + &WelcomeScreenHandler::HandleSetLocaleId); + AddCallback("WelcomeScreen.setInputMethodId", + &WelcomeScreenHandler::HandleSetInputMethodId); + AddCallback("WelcomeScreen.setTimezoneId", + &WelcomeScreenHandler::HandleSetTimezoneId); +} + void WelcomeScreenHandler::GetAdditionalParameters( base::DictionaryValue* dict) { const std::string application_locale = @@ -221,6 +239,22 @@ ReloadLocalizedContent(); } +void WelcomeScreenHandler::HandleSetLocaleId(const std::string& locale_id) { + if (screen_) + screen_->SetApplicationLocale(locale_id); +} + +void WelcomeScreenHandler::HandleSetInputMethodId( + const std::string& input_method_id) { + if (screen_) + screen_->SetInputMethod(input_method_id); +} + +void WelcomeScreenHandler::HandleSetTimezoneId(const std::string& timezone_id) { + if (screen_) + screen_->SetTimezone(timezone_id); +} + // WelcomeScreenHandler, private: ---------------------------------------------- // static
diff --git a/chrome/browser/ui/webui/chromeos/login/welcome_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/welcome_screen_handler.h index 9e755534..de60b3c 100644 --- a/chrome/browser/ui/webui/chromeos/login/welcome_screen_handler.h +++ b/chrome/browser/ui/webui/chromeos/login/welcome_screen_handler.h
@@ -6,6 +6,7 @@ #define CHROME_BROWSER_UI_WEBUI_CHROMEOS_LOGIN_WELCOME_SCREEN_HANDLER_H_ #include <memory> +#include <string> #include "base/macros.h" #include "chrome/browser/chromeos/login/screens/welcome_view.h" @@ -35,13 +36,21 @@ void Unbind() override; void StopDemoModeDetection() override; void ReloadLocalizedContent() override; + void SetInputMethodId(const std::string& input_method_id) override; + void SetTimezoneId(const std::string& timezone_id) override; // BaseScreenHandler implementation: void DeclareLocalizedValues( ::login::LocalizedValuesBuilder* builder) override; + void DeclareJSCallbacks() override; void GetAdditionalParameters(base::DictionaryValue* dict) override; void Initialize() override; + // JS callbacks. + void HandleSetLocaleId(const std::string& locale_id); + void HandleSetInputMethodId(const std::string& input_method_id); + void HandleSetTimezoneId(const std::string& timezone_id); + // Returns available timezones. Caller gets the ownership. static std::unique_ptr<base::ListValue> GetTimezoneList();
diff --git a/chrome/browser/ui/webui/omnibox/omnibox.mojom b/chrome/browser/ui/webui/omnibox/omnibox.mojom index 09afd437..7e6f9f9 100644 --- a/chrome/browser/ui/webui/omnibox/omnibox.mojom +++ b/chrome/browser/ui/webui/omnibox/omnibox.mojom
@@ -6,6 +6,11 @@ // The structures here roughly mirror those from autocomplete. +struct ACMatchClassification { + int32 offset; + int32 style; +}; + struct AutocompleteAdditionalInfo { string key; string value; @@ -23,7 +28,9 @@ string stripped_destination_url; string image; string contents; + array<ACMatchClassification> contents_class; string description; + array<ACMatchClassification> description_class; string answer; string transition; bool allowed_to_be_default_match;
diff --git a/chrome/browser/ui/webui/omnibox/omnibox_page_handler.cc b/chrome/browser/ui/webui/omnibox/omnibox_page_handler.cc index a98f398d..f9715b337 100644 --- a/chrome/browser/ui/webui/omnibox/omnibox_page_handler.cc +++ b/chrome/browser/ui/webui/omnibox/omnibox_page_handler.cc
@@ -118,6 +118,21 @@ namespace mojo { template <> +struct TypeConverter<std::vector<mojom::ACMatchClassificationPtr>, + AutocompleteMatch::ACMatchClassifications> { + static std::vector<mojom::ACMatchClassificationPtr> Convert( + const AutocompleteMatch::ACMatchClassifications& input) { + std::vector<mojom::ACMatchClassificationPtr> array; + for (auto classification : input) { + auto item = mojom::ACMatchClassification::New(classification.offset, + classification.style); + array.push_back(std::move(item)); + } + return array; + } +}; + +template <> struct TypeConverter<std::vector<mojom::AutocompleteAdditionalInfoPtr>, AutocompleteMatch::AdditionalInfo> { static std::vector<mojom::AutocompleteAdditionalInfoPtr> Convert( @@ -152,13 +167,13 @@ result->stripped_destination_url = input.stripped_destination_url.spec(); result->image = input.ImageUrl().spec().c_str(); result->contents = base::UTF16ToUTF8(input.contents); - // At this time, we're not bothering to send along the long vector that - // represent contents classification. i.e., for each character, what - // type of text it is. + result->contents_class = + mojo::ConvertTo<std::vector<mojom::ACMatchClassificationPtr>>( + input.contents_class); result->description = base::UTF16ToUTF8(input.description); - // At this time, we're not bothering to send along the long vector that - // represents description classification. i.e., for each character, what - // type of text it is. + result->description_class = + mojo::ConvertTo<std::vector<mojom::ACMatchClassificationPtr>>( + input.description_class); if (input.answer) { result->answer = SuggestionAnswerImageLineToString(input.answer->first_line()) +
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc index 2392201..526c637 100644 --- a/chrome/common/chrome_features.cc +++ b/chrome/common/chrome_features.cc
@@ -568,11 +568,6 @@ "SupervisedUserCommittedInterstitials", base::FEATURE_ENABLED_BY_DEFAULT}; #if defined(OS_CHROMEOS) -// Enables or disables sliding (showing or hiding) the top-chrome UIs with page -// scrolls in tablet mode. -const base::Feature kSlideTopChromeWithPageScrolls{ - "SlideTopChromeWithPageScrolls", base::FEATURE_ENABLED_BY_DEFAULT}; - // Enables or disables chrome://sys-internals. const base::Feature kSysInternals{"SysInternals", base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/chrome/common/chrome_features.h b/chrome/common/chrome_features.h index d8f3ded..2d51681 100644 --- a/chrome/common/chrome_features.h +++ b/chrome/common/chrome_features.h
@@ -373,9 +373,6 @@ #if defined(OS_CHROMEOS) COMPONENT_EXPORT(CHROME_FEATURES) -extern const base::Feature kSlideTopChromeWithPageScrolls; - -COMPONENT_EXPORT(CHROME_FEATURES) extern const base::Feature kSysInternals; #endif
diff --git a/chrome/common/safe_browsing/zip_analyzer.h b/chrome/common/safe_browsing/zip_analyzer.h index 9d0ed58..2e8bf63 100644 --- a/chrome/common/safe_browsing/zip_analyzer.h +++ b/chrome/common/safe_browsing/zip_analyzer.h
@@ -9,7 +9,6 @@ #define CHROME_COMMON_SAFE_BROWSING_ZIP_ANALYZER_H_ #include "base/files/file.h" -#include "components/safe_browsing/proto/csd.pb.h" namespace safe_browsing {
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeActivityTestRule.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeActivityTestRule.java index 6ae85a7..7b6429b2 100644 --- a/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeActivityTestRule.java +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeActivityTestRule.java
@@ -145,10 +145,6 @@ try { ApplicationTestUtils.tearDown(InstrumentationRegistry.getTargetContext()); Thread.setDefaultUncaughtExceptionHandler(mDefaultUncaughtExceptionHandler); - if (mSetActivity != null) { - // This is to ensure onDestroy() is performed before starting the next test. - ApplicationTestUtils.finishActivity(mSetActivity); - } } catch (Exception e) { throw new RuntimeException("Failed to tearDown", e); }
diff --git a/chrome/test/base/browser_with_test_window_test.cc b/chrome/test/base/browser_with_test_window_test.cc index db76213..50f936f 100644 --- a/chrome/test/base/browser_with_test_window_test.cc +++ b/chrome/test/base/browser_with_test_window_test.cc
@@ -126,9 +126,10 @@ testing::Test::TearDown(); // A Task is leaked if we don't destroy everything, then run the message loop. - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::RunLoop::QuitCurrentWhenIdleClosureDeprecated()); - base::RunLoop().Run(); + base::RunLoop loop; + base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, + loop.QuitWhenIdleClosure()); + loop.Run(); } gfx::NativeWindow BrowserWithTestWindowTest::GetContext() {
diff --git a/chrome/test/base/interactive_test_utils_views.cc b/chrome/test/base/interactive_test_utils_views.cc index f62d538..03b328d 100644 --- a/chrome/test/base/interactive_test_utils_views.cc +++ b/chrome/test/base/interactive_test_utils_views.cc
@@ -31,10 +31,11 @@ views::View* view = BrowserView::GetBrowserViewForBrowser(browser)->GetViewByID(vid); DCHECK(view); - MoveMouseToCenterAndPress( - view, ui_controls::LEFT, ui_controls::DOWN | ui_controls::UP, - base::RunLoop::QuitCurrentWhenIdleClosureDeprecated()); - content::RunMessageLoop(); + base::RunLoop loop; + MoveMouseToCenterAndPress(view, ui_controls::LEFT, + ui_controls::DOWN | ui_controls::UP, + loop.QuitWhenIdleClosure()); + loop.Run(); } void FocusView(const Browser* browser, ViewID vid) {
diff --git a/chrome/test/data/webui/cr_elements/cr_radio_group_test.js b/chrome/test/data/webui/cr_elements/cr_radio_group_test.js index 8fd512d..d80a59f 100644 --- a/chrome/test/data/webui/cr_elements/cr_radio_group_test.js +++ b/chrome/test/data/webui/cr_elements/cr_radio_group_test.js
@@ -136,6 +136,31 @@ noneSelectedOneFocusable(2); }); + test('when group is disabled, button aria-disabled is updated', () => { + assertEquals('false', radioGroup.getAttribute('aria-disabled')); + assertFalse(radioGroup.disabled); + checkLength(3, '[aria-disabled="false"]'); + radioGroup.disabled = true; + assertEquals('true', radioGroup.getAttribute('aria-disabled')); + checkLength(3, '[aria-disabled="true"]'); + radioGroup.disabled = false; + assertEquals('false', radioGroup.getAttribute('aria-disabled')); + checkLength(3, '[aria-disabled="false"]'); + + // Check that if a button already disabled, it will remain disabled after + // group is re-enabled. + const firstRadio = radioGroup.querySelector('[name="1"]'); + firstRadio.disabled = true; + checkLength(2, '[aria-disabled="false"]'); + checkLength(1, '[aria-disabled="true"][disabled][name="1"]'); + radioGroup.disabled = true; + checkLength(3, '[aria-disabled="true"]'); + checkLength(1, '[aria-disabled="true"][disabled][name="1"]'); + radioGroup.disabled = false; + checkLength(2, '[aria-disabled="false"]'); + checkLength(1, '[aria-disabled="true"][disabled][name="1"]'); + }); + test('radios name change updates selection and tabindex', () => { radioGroup.selected = '1'; checkSelected(1);
diff --git a/chrome/test/data/webui/settings/cups_printer_page_tests.js b/chrome/test/data/webui/settings/cups_printer_page_tests.js index 5a0b14e..3104331 100644 --- a/chrome/test/data/webui/settings/cups_printer_page_tests.js +++ b/chrome/test/data/webui/settings/cups_printer_page_tests.js
@@ -11,6 +11,7 @@ 'getCupsPrinterManufacturersList', 'getCupsPrinterModelsList', 'getPrinterInfo', + 'getPrinterPpdManufacturerAndModel', 'startDiscoveringPrinters', 'stopDiscoveringPrinters', 'cancelPrinterSetUp', @@ -20,6 +21,7 @@ this.manufacturers = []; this.models = []; this.printerInfo = {}; + this.printerPpdMakeModel = {}; } /** @override */ @@ -65,6 +67,12 @@ cancelPrinterSetUp(newPrinter) { this.methodCalled('cancelPrinterSetUp', newPrinter); } + + /** @override */ + getPrinterPpdManufacturerAndModel(printerId) { + this.methodCalled('getPrinterPpdManufacturerAndModel', printerId); + return Promise.resolve(this.printerPpdMakeModel); + } } suite('CupsAddPrinterDialogTests', function() { @@ -97,6 +105,12 @@ cancelButton.click(); } + function canAddPrinter(dialog, name, address) { + dialog.newPrinter.printerName = name; + dialog.newPrinter.printerAddress = address; + return dialog.canAddPrinter_(); + } + let page = null; let dialog = null; @@ -147,58 +161,59 @@ test('ValidIPV4', function() { const dialog = document.createElement('add-printer-manually-dialog'); - expectTrue(dialog.canAddPrinter_('Test printer', '127.0.0.1')); + expectTrue(canAddPrinter(dialog, 'Test printer', '127.0.0.1')); }); test('ValidIPV4WithPort', function() { const dialog = document.createElement('add-printer-manually-dialog'); - expectTrue(dialog.canAddPrinter_('Test printer', '127.0.1.183:1234')); + + expectTrue(canAddPrinter(dialog, 'Test printer', '127.0.0.1:1234')); }); test('ValidIPV6', function() { const dialog = document.createElement('add-printer-manually-dialog'); // Test the full ipv6 address scheme. - expectTrue(dialog.canAddPrinter_('Test printer', '1:2:a3:ff4:5:6:7:8')); + expectTrue(canAddPrinter(dialog, 'Test printer', '1:2:a3:ff4:5:6:7:8')); // Test the shorthand prefix scheme. - expectTrue(dialog.canAddPrinter_('Test printer', '::255')); + expectTrue(canAddPrinter(dialog, 'Test printer', '::255')); // Test the shorthand suffix scheme. - expectTrue(dialog.canAddPrinter_('Test printer', '1::')); + expectTrue(canAddPrinter(dialog, 'Test printer', '1::')); }); test('ValidIPV6WithPort', function() { const dialog = document.createElement('add-printer-manually-dialog'); - expectTrue(dialog.canAddPrinter_('Test printer', '[1:2:aa2:4]:12')); - expectTrue(dialog.canAddPrinter_('Test printer', '[::255]:54')); - expectTrue(dialog.canAddPrinter_('Test printer', '[1::]:7899')); + expectTrue(canAddPrinter(dialog, 'Test printer', '[1:2:aa2:4]:12')); + expectTrue(canAddPrinter(dialog, 'Test printer', '[::255]:54')); + expectTrue(canAddPrinter(dialog, 'Test printer', '[1::]:7899')); }); test('InvalidIPV6', function() { const dialog = document.createElement('add-printer-manually-dialog'); - expectFalse(dialog.canAddPrinter_('Test printer', '1:2:3:4:5:6:7:8:9')); - expectFalse(dialog.canAddPrinter_('Test printer', '1:2:3:aa:a1245:2')); - expectFalse(dialog.canAddPrinter_('Test printer', '1:2:3:za:2')); - expectFalse(dialog.canAddPrinter_('Test printer', '1:::22')); - expectFalse(dialog.canAddPrinter_('Test printer', '1::2::3')); + expectFalse(canAddPrinter(dialog, 'Test printer', '1:2:3:4:5:6:7:8:9')); + expectFalse(canAddPrinter(dialog, 'Test printer', '1:2:3:aa:a1245:2')); + expectFalse(canAddPrinter(dialog, 'Test printer', '1:2:3:za:2')); + expectFalse(canAddPrinter(dialog, 'Test printer', '1:::22')); + expectFalse(canAddPrinter(dialog, 'Test printer', '1::2::3')); }); test('ValidHostname', function() { const dialog = document.createElement('add-printer-manually-dialog'); - expectTrue(dialog.canAddPrinter_('Test printer', 'hello-world.com')); - expectTrue(dialog.canAddPrinter_('Test printer', 'hello.world.com:12345')); + expectTrue(canAddPrinter(dialog, 'Test printer', 'hello-world.com')); + expectTrue(canAddPrinter(dialog, 'Test printer', 'hello.world.com:12345')); }); test('InvalidHostname', function() { const dialog = document.createElement('add-printer-manually-dialog'); - expectFalse(dialog.canAddPrinter_('Test printer', 'helloworld!123.com')); - expectFalse(dialog.canAddPrinter_('Test printer', 'helloworld123-.com')); - expectFalse(dialog.canAddPrinter_('Test printer', '-helloworld123.com')); + expectFalse(canAddPrinter(dialog, 'Test printer', 'helloworld!123.com')); + expectFalse(canAddPrinter(dialog, 'Test printer', 'helloworld123-.com')); + expectFalse(canAddPrinter(dialog, 'Test printer', '-helloworld123.com')); }); /** @@ -449,3 +464,95 @@ }); }); }); + +suite('EditPrinterDialog', function() { + // Sets ppdManufacturer and ppdModel since ppdManufacturer has an observer + // that erases ppdModel when ppdManufacturer changes. + function setPpdManufacturerAndPpdModel(manufacturer, model) { + dialog.activePrinter.ppdManufacturer = manufacturer; + dialog.activePrinter.ppdModel = model; + } + + /** @type {?settings.TestCupsPrintersBrowserProxy} */ + let cupsPrintersBrowserProxy = null; + + let dialog = null; + + setup(function() { + cupsPrintersBrowserProxy = new TestCupsPrintersBrowserProxy(); + settings.CupsPrintersBrowserProxyImpl.instance_ = cupsPrintersBrowserProxy; + PolymerTest.clearBody(); + + dialog = document.createElement('settings-cups-edit-printer-dialog'); + + dialog.activePrinter = { + ppdManufacturer: '', + ppdModel: '', + printerAddress: '', + printerAutoconf: false, + printerDescription: '', + printerId: '', + printerManufacturer: '', + printerModel: '', + printerMakeAndModel: '', + printerName: '', + printerPPDPath: '', + printerPpdReference: { + userSuppliedPpdUrl: '', + effectiveMakeAndModel: '', + autoconf: false, + }, + printerProtocol: '', + printerQueue: '', + printerStatus: '', + }; + + document.body.appendChild(dialog); + }); + + teardown(function() { + dialog.remove(); + dialog = null; + }); + + /** + * Test that USB printers can be editted. + */ + test('USBPrinterCanBeEdited', function() { + dialog.activePrinter = { + ppdManufacturer: '', + ppdModel: '', + printerAddress: '03f0/e414?serial=CD4234', + printerAutoconf: false, + printerDescription: '', + printerId: '', + printerManufacturer: '', + printerModel: '', + printerMakeAndModel: '', + printerName: 'Test Printer', + printerPPDPath: '', + printerPpdReference: { + userSuppliedPpdUrl: '', + effectiveMakeAndModel: '', + autoconf: false, + }, + printerProtocol: 'usb', + printerQueue: 'moreinfohere', + printerStatus: '', + }; + + // Set activePrinter.ppdManufactuer and activePrinter.ppdModel to simulate + // a printer for which we have a PPD. + setPpdManufacturerAndPpdModel('manufacturer', 'model'); + + // Edit the printer name. + const nameField = dialog.$$('.printer-name-input'); + assertTrue(!!nameField); + nameField.value = 'edited printer'; + + // Assert that the "Add" button is enabled. + const addButton = dialog.$$('.action-button'); + assertTrue(!!addButton); + assertTrue(!addButton.disabled); + }); +});
diff --git a/chrome/test/media_router/media_router_integration_browsertest.h b/chrome/test/media_router/media_router_integration_browsertest.h index 4478f74..7d1e073 100644 --- a/chrome/test/media_router/media_router_integration_browsertest.h +++ b/chrome/test/media_router/media_router_integration_browsertest.h
@@ -8,7 +8,6 @@ #include <memory> #include <string> -#include "base/debug/stack_trace.h" #include "base/files/file_path.h" #include "base/test/scoped_feature_list.h" #include "chrome/browser/ui/media_router/media_cast_mode.h"
diff --git a/chromecast/BUILD.gn b/chromecast/BUILD.gn index a05b920..e998648 100644 --- a/chromecast/BUILD.gn +++ b/chromecast/BUILD.gn
@@ -37,6 +37,9 @@ if (chromecast_branding != "public") { deps += [ "//chromecast/internal:all" ] } + if (enable_external_mojo_services) { + deps += [ "//chromecast/external_mojo/external_service_support:standalone_mojo_broker" ] + } # No other targets should depend on this target, since it's just a convenience # target for the Chromecast internal build infrastructure. @@ -580,6 +583,7 @@ "ENABLE_CAST_FRAGMENT=$enable_cast_fragment", "ENABLE_CAST_WAYLAND_SERVER=$enable_cast_wayland_server", "ENABLE_CHROMECAST_EXTENSIONS=$enable_chromecast_extensions", + "ENABLE_EXTERNAL_MOJO_SERVICES=$enable_external_mojo_services", "ENABLE_HEADLESS_MUSIC_MODE=$enable_headless_music_mode", "ENABLE_PLAYREADY=$enable_playready", "ENABLE_VIDEO_CAPTURE_SERVICE=$enable_video_capture_service",
diff --git a/chromecast/browser/BUILD.gn b/chromecast/browser/BUILD.gn index 48ff1221..672382f3 100644 --- a/chromecast/browser/BUILD.gn +++ b/chromecast/browser/BUILD.gn
@@ -244,6 +244,10 @@ ] } + if (enable_external_mojo_services) { + deps += [ "//chromecast/external_mojo/broker_service" ] + } + if (enable_chromecast_extensions) { sources += [ "cast_extension_host.cc",
diff --git a/chromecast/browser/DEPS b/chromecast/browser/DEPS index 224d06b..34e38b2 100644 --- a/chromecast/browser/DEPS +++ b/chromecast/browser/DEPS
@@ -4,6 +4,7 @@ "+chromecast/graphics", "+chromecast/app/grit/chromecast_settings.h", "+chromecast/app/resources/grit/shell_resources.h", + "+chromecast/external_mojo", "+chromecast/internal/shell/browser", "+chromecast/media", "+chromecast/net",
diff --git a/chromecast/browser/cast_content_browser_client.cc b/chromecast/browser/cast_content_browser_client.cc index 293f7b8..63be8879 100644 --- a/chromecast/browser/cast_content_browser_client.cc +++ b/chromecast/browser/cast_content_browser_client.cc
@@ -6,8 +6,6 @@ #include <stddef.h> -#include <memory> -#include <string> #include <utility> #include "base/base_switches.h" @@ -134,6 +132,10 @@ #include "extensions/common/constants.h" // nogncheck #endif +#if BUILDFLAG(ENABLE_EXTERNAL_MOJO_SERVICES) +#include "chromecast/external_mojo/broker_service/broker_service.h" +#endif + namespace chromecast { namespace shell { @@ -188,6 +190,14 @@ } #endif // defined(OS_ANDROID) && !BUILDFLAG(USE_CHROMECAST_CDMS) +#if BUILDFLAG(ENABLE_EXTERNAL_MOJO_SERVICES) +void StartExternalMojoBrokerService( + service_manager::mojom::ServiceRequest request) { + service_manager::Service::RunAsyncUntilTermination( + std::make_unique<external_mojo::BrokerService>(std::move(request))); +} +#endif // BUILDFLAG(ENABLE_EXTERNAL_MOJO_SERVICES) + } // namespace CastContentBrowserClient::CastContentBrowserClient( @@ -381,6 +391,14 @@ return true; } +std::vector<std::string> CastContentBrowserClient::GetStartupServices() { + return { +#if BUILDFLAG(ENABLE_EXTERNAL_MOJO_SERVICES) + external_mojo::BrokerService::kServiceName +#endif + }; +} + content::BrowserMainParts* CastContentBrowserClient::CreateBrowserMainParts( const content::MainFunctionParams& parameters) { DCHECK(!cast_browser_main_parts_); @@ -785,8 +803,16 @@ GetMediaTaskRunner()->PostTask( FROM_HERE, base::BindOnce(&CreateMediaService, this, std::move(request))); + return; } -#endif +#endif // BUILDFLAG(ENABLE_MOJO_MEDIA_IN_BROWSER_PROCESS) + +#if BUILDFLAG(ENABLE_EXTERNAL_MOJO_SERVICES) + if (service_name == external_mojo::BrokerService::kServiceName) { + StartExternalMojoBrokerService(std::move(request)); + return; + } +#endif // BUILDFLAG(ENABLE_EXTERNAL_MOJO_SERVICES) } base::Optional<service_manager::Manifest>
diff --git a/chromecast/browser/cast_content_browser_client.h b/chromecast/browser/cast_content_browser_client.h index aa65730b..1e1f5c26f 100644 --- a/chromecast/browser/cast_content_browser_client.h +++ b/chromecast/browser/cast_content_browser_client.h
@@ -130,6 +130,7 @@ virtual bool EnableRemoteDebuggingImmediately(); // content::ContentBrowserClient implementation: + std::vector<std::string> GetStartupServices() override; content::BrowserMainParts* CreateBrowserMainParts( const content::MainFunctionParams& parameters) override; void RenderProcessWillLaunch(
diff --git a/chromecast/browser/cast_overlay_manifests.cc b/chromecast/browser/cast_overlay_manifests.cc index 93b8d5e6..3ab7d82 100644 --- a/chromecast/browser/cast_overlay_manifests.cc +++ b/chromecast/browser/cast_overlay_manifests.cc
@@ -6,6 +6,7 @@ #include "base/no_destructor.h" #include "build/build_config.h" +#include "chromecast/chromecast_buildflags.h" #include "chromecast/common/mojom/application_media_capabilities.mojom.h" #include "chromecast/common/mojom/feature_manager.mojom.h" #include "chromecast/common/mojom/media_caps.mojom.h" @@ -14,6 +15,10 @@ #include "media/mojo/services/media_manifest.h" #include "services/service_manager/public/cpp/manifest_builder.h" +#if BUILDFLAG(ENABLE_EXTERNAL_MOJO_SERVICES) +#include "chromecast/external_mojo/broker_service/broker_service.h" +#endif + #if defined(USE_INTERNAL_OVERLAY_MANIFESTS) #include "chromecast/internal/shell/browser/cast_content_browser_internal_manifest_overlay.h" #include "chromecast/internal/shell/browser/cast_content_packaged_services_internal_manifest_overlay.h" @@ -62,6 +67,9 @@ static base::NoDestructor<service_manager::Manifest> manifest { service_manager::ManifestBuilder() .PackageService(::media::GetMediaManifest()) +#if BUILDFLAG(ENABLE_EXTERNAL_MOJO_SERVICES) + .PackageService(chromecast::external_mojo::BrokerService::GetManifest()) +#endif .Build() #if defined(USE_INTERNAL_OVERLAY_MANIFESTS) .Amend(cast_content_packaged_services_internal_manifest_overlay::
diff --git a/chromecast/chromecast.gni b/chromecast/chromecast.gni index f1063f0b..e5bf713 100644 --- a/chromecast/chromecast.gni +++ b/chromecast/chromecast.gni
@@ -112,6 +112,11 @@ # Set to true to enable video capture service for video input and output. enable_video_capture_service = false + + # Set to true to enable external Mojo services to communicate with services + # within cast_shell. Enable for desktop builds to ensure that Chromium CQ + # builds the external Mojo broker code. + enable_external_mojo_services = is_cast_desktop_build } declare_args() {
diff --git a/chromecast/external_mojo/DEPS b/chromecast/external_mojo/DEPS new file mode 100644 index 0000000..3045c041 --- /dev/null +++ b/chromecast/external_mojo/DEPS
@@ -0,0 +1,5 @@ +include_rules = [ + "+chromecast/base", + "+mojo/public", + "+services/service_manager/public", +]
diff --git a/chromecast/external_mojo/OWNERS b/chromecast/external_mojo/OWNERS new file mode 100644 index 0000000..dee6095d --- /dev/null +++ b/chromecast/external_mojo/OWNERS
@@ -0,0 +1 @@ +kmackay@chromium.org
diff --git a/chromecast/external_mojo/README.md b/chromecast/external_mojo/README.md new file mode 100644 index 0000000..4fb679b --- /dev/null +++ b/chromecast/external_mojo/README.md
@@ -0,0 +1,17 @@ +# External Mojo services + +This directory contains code that allows Mojo services in processes outside of +cast_shell to communicate with Mojo services within cast_shell. + +## broker_service +This contains the service_manager::Service that runs inside cast_shell and +brokers communication between Mojo services in external processes and services +within cast_shell. This service is automatically started when the +'enable_external_mojo_services' GN arg is true. + +## external_service_support +This directory contains utilities to ease development of Mojo services that run +in processes outside of Chromium/cast_shell. + +## common +This contains code that is shared between cast_shell and external services.
diff --git a/chromecast/external_mojo/broker_service/BUILD.gn b/chromecast/external_mojo/broker_service/BUILD.gn new file mode 100644 index 0000000..c6e84e4 --- /dev/null +++ b/chromecast/external_mojo/broker_service/BUILD.gn
@@ -0,0 +1,16 @@ +# Copyright 2019 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +source_set("broker_service") { + sources = [ + "broker_service.cc", + "broker_service.h", + ] + deps = [ + "//base", + "//chromecast/external_mojo/public/cpp:external_mojo_broker", + "//services/service_manager/public/cpp", + "//services/service_manager/public/mojom", + ] +}
diff --git a/chromecast/external_mojo/broker_service/broker_service.cc b/chromecast/external_mojo/broker_service/broker_service.cc new file mode 100644 index 0000000..425c4747 --- /dev/null +++ b/chromecast/external_mojo/broker_service/broker_service.cc
@@ -0,0 +1,103 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chromecast/external_mojo/broker_service/broker_service.h" + +#include <utility> +#include <vector> + +#include "base/bind.h" +#include "base/location.h" +#include "base/macros.h" +#include "base/no_destructor.h" +#include "base/sequenced_task_runner.h" +#include "base/threading/thread.h" +#include "chromecast/external_mojo/public/cpp/external_mojo_broker.h" +#include "services/service_manager/public/cpp/manifest_builder.h" + +namespace chromecast { +namespace external_mojo { + +namespace { + +std::vector<service_manager::Manifest>& GetExternalManifests() { + static std::vector<service_manager::Manifest> manifests; + return manifests; +} + +service_manager::Manifest MakePackagedServices( + std::vector<service_manager::Manifest> manifests) { + service_manager::Manifest packaged; + for (auto& manifest : manifests) { + // External services can only access what the external Mojo broker service + // can access, so require all services that external services require. + for (const auto& capability_entry : manifest.required_capabilities) { + const auto& service_name = capability_entry.first; + const auto& capability_names = capability_entry.second; + for (const auto& capability_name : capability_names) { + packaged.required_capabilities[service_name].insert(capability_name); + } + } + + // External services that expose capabilities have an internal proxy service + // registered with ServiceManager. + if (!manifest.exposed_capabilities.empty()) { + // The external Mojo broker service needs to require a capability from + // each external service in order to register the internal proxy service + // for it. + packaged.required_capabilities[manifest.service_name].insert( + manifest.exposed_capabilities.begin()->first); + packaged.packaged_services.emplace_back(std::move(manifest)); + } + } + return packaged; +} + +} // namespace + +BrokerService::BrokerService(service_manager::mojom::ServiceRequest request) + : service_binding_(this, std::move(request)) { + io_thread_ = std::make_unique<base::Thread>("external_mojo"); + io_thread_->StartWithOptions( + base::Thread::Options(base::MessageLoop::TYPE_IO, 0)); + + std::vector<std::string> external_services_to_proxy; + const service_manager::Manifest& manifest = GetManifest(); + for (const auto& sub_manifest : manifest.packaged_services) { + external_services_to_proxy.push_back(sub_manifest.service_name); + } + broker_ = base::SequenceBound<ExternalMojoBroker>(io_thread_->task_runner()); + broker_.Post(FROM_HERE, &ExternalMojoBroker::InitializeChromium, + service_binding_.GetConnector()->Clone(), + external_services_to_proxy); +} + +BrokerService::~BrokerService() { + broker_.Reset(); + io_thread_.reset(); +} + +// static +void BrokerService::AddExternalServiceManifest( + service_manager::Manifest manifest) { + GetExternalManifests().push_back(std::move(manifest)); +} + +// static +const service_manager::Manifest& BrokerService::GetManifest() { + static base::NoDestructor<service_manager::Manifest> manifest{ + service_manager::ManifestBuilder() + .WithServiceName(BrokerService::kServiceName) + .WithDisplayName("External Mojo Broker Service") + .WithOptions(service_manager::ManifestOptionsBuilder() + .WithSandboxType("none") + .CanRegisterOtherServiceInstances(true) + .Build()) + .Build() + .Amend(MakePackagedServices(GetExternalManifests()))}; + return *manifest; +} + +} // namespace external_mojo +} // namespace chromecast
diff --git a/chromecast/external_mojo/broker_service/broker_service.h b/chromecast/external_mojo/broker_service/broker_service.h new file mode 100644 index 0000000..563aa35 --- /dev/null +++ b/chromecast/external_mojo/broker_service/broker_service.h
@@ -0,0 +1,64 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROMECAST_EXTERNAL_MOJO_BROKER_SERVICE_BROKER_SERVICE_H_ +#define CHROMECAST_EXTERNAL_MOJO_BROKER_SERVICE_BROKER_SERVICE_H_ + +#include <memory> +#include <string> + +#include "base/macros.h" +#include "base/memory/ref_counted.h" +#include "base/threading/sequence_bound.h" +#include "services/service_manager/public/cpp/manifest.h" +#include "services/service_manager/public/cpp/service.h" +#include "services/service_manager/public/cpp/service_binding.h" +#include "services/service_manager/public/mojom/service.mojom.h" + +namespace base { +class SequencedTaskRunner; +class Thread; +} // namespace base + +namespace chromecast { +namespace external_mojo { +class ExternalMojoBroker; + +// A Mojo service (intended to run within cast_shell or some other Chromium +// ServiceManager environment) that allows Mojo services built into external +// processes to interoperate with the Mojo services within cast_shell. +class BrokerService : public ::service_manager::Service { + public: + static constexpr char const* kServiceName = "external_mojo_broker"; + + // Adds a manifest for an external Mojo service (ie, one that is running in + // a non-Chromium process). A manifest is only needed for external services + // that bind to Mojo services within cast_shell, or for external services that + // are bound to (used) by internal Mojo services. All external manifests must + // be added before GetExternalMojoBrokerManifest() is called (otherwise they + // will not be included in the broker manifest, and so the relevant + // permissions will not be set correctly). + static void AddExternalServiceManifest(service_manager::Manifest manifest); + + // Returns the manifest for this service. + static const service_manager::Manifest& GetManifest(); + + explicit BrokerService(service_manager::mojom::ServiceRequest request); + ~BrokerService() override; + + private: + service_manager::ServiceBinding service_binding_; + + std::unique_ptr<base::Thread> io_thread_; + scoped_refptr<base::SequencedTaskRunner> io_task_runner_; + + base::SequenceBound<ExternalMojoBroker> broker_; + + DISALLOW_COPY_AND_ASSIGN(BrokerService); +}; + +} // namespace external_mojo +} // namespace chromecast + +#endif // CHROMECAST_EXTERNAL_MOJO_BROKER_SERVICE_BROKER_SERVICE_H_
diff --git a/chromecast/external_mojo/external_service_support/BUILD.gn b/chromecast/external_mojo/external_service_support/BUILD.gn new file mode 100644 index 0000000..46f0562e --- /dev/null +++ b/chromecast/external_mojo/external_service_support/BUILD.gn
@@ -0,0 +1,71 @@ +# Copyright 2019 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +source_set("external_service") { + sources = [ + "external_connector.cc", + "external_connector.h", + "external_service.cc", + "external_service.h", + ] + deps = [ + "//base", + "//chromecast/external_mojo/public/mojom", + "//mojo/core/embedder", + "//mojo/public/cpp/bindings", + "//mojo/public/cpp/platform", + "//mojo/public/cpp/system", + ] +} + +source_set("process_setup") { + sources = [ + "process_setup.cc", + "process_setup.h", + ] + deps = [ + "//base", + ] +} + +source_set("standalone_service_main") { + sources = [ + "service_process.h", + "standalone_service_main.cc", + ] + deps = [ + ":external_service", + ":process_setup", + "//base", + "//chromecast/external_mojo/public/cpp:common", + "//mojo/core/embedder", + ] +} + +source_set("chromium_service") { + sources = [ + "chromium_service.cc", + "chromium_service.h", + ] + deps = [ + ":external_service", + "//base", + "//chromecast/external_mojo/public/mojom", + "//mojo/public/cpp/bindings", + "//services/service_manager/public/cpp", + "//services/service_manager/public/mojom", + ] +} + +executable("standalone_mojo_broker") { + sources = [ + "standalone_mojo_broker.cc", + ] + deps = [ + ":process_setup", + "//base", + "//chromecast/external_mojo/public/cpp:external_mojo_broker", + "//mojo/core/embedder", + ] +}
diff --git a/chromecast/external_mojo/external_service_support/DEPS b/chromecast/external_mojo/external_service_support/DEPS new file mode 100644 index 0000000..9243dcd6 --- /dev/null +++ b/chromecast/external_mojo/external_service_support/DEPS
@@ -0,0 +1,3 @@ +include_rules = [ + "+mojo/core/embedder", +]
diff --git a/chromecast/external_mojo/external_service_support/README.md b/chromecast/external_mojo/external_service_support/README.md new file mode 100644 index 0000000..e120cdd --- /dev/null +++ b/chromecast/external_mojo/external_service_support/README.md
@@ -0,0 +1,21 @@ +# External Mojo service support + +This directory contains utilities to ease development of Mojo services that run +in processes outside of Chromium/cast_shell. The simplest model is to create a +subclass of 'ServiceProcess' (and implement 'ServiceProcess::Create()' that +returns an instance of that subclass), and link with 'standalone_service_main' +to create the executable. In your 'ServiceProcess' implementation, you can bind +to Mojo interfaces using the provided 'Connector' pointer, and/or register your +own Mojo services for use by other processes. + +The 'ChromiumServiceWrapper' class is intended to allow Mojo services that were +intended to be embedded into cast_shell (or other ServiceManager embedder) to +be moved into a completely separate process. It forwards 'BindInterface()' +calls to the 'service_manager::Service' API. You can use +'CreateChromiumServiceRequest()' to create a 'service_manager::ServiceRequest' +to emulate the normal service creation flow; the +'service_manager::Service::OnStart()' method will be called automatically. + +The 'standalone_mojo_broker' is intended for use on platforms where there is no +cast_shell running; this allows Mojo services outside of cast_shell to +communicate with each other without any Chromium embedder on the system.
diff --git a/chromecast/external_mojo/external_service_support/chromium_service.cc b/chromecast/external_mojo/external_service_support/chromium_service.cc new file mode 100644 index 0000000..c7953e5 --- /dev/null +++ b/chromecast/external_mojo/external_service_support/chromium_service.cc
@@ -0,0 +1,87 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chromecast/external_mojo/external_service_support/chromium_service.h" + +#include <utility> + +#include "base/bind.h" +#include "base/logging.h" +#include "base/token.h" +#include "chromecast/external_mojo/external_service_support/external_connector.h" +#include "mojo/public/cpp/bindings/interface_request.h" +#include "services/service_manager/public/cpp/bind_source_info.h" +#include "services/service_manager/public/cpp/connector.h" +#include "services/service_manager/public/mojom/connector.mojom.h" +#include "services/service_manager/public/mojom/service_control.mojom.h" + +namespace chromecast { +namespace external_service_support { + +namespace { + +void OnStartCallback( + ExternalConnector* connector, + service_manager::mojom::ConnectorRequest connector_request, + service_manager::mojom::ServiceControlAssociatedRequest control_request) { + DCHECK(connector); + if (connector_request.is_pending()) { + connector->SendChromiumConnectorRequest( + connector_request.PassMessagePipe()); + } +} + +} // namespace + +ChromiumServiceWrapper::ChromiumServiceWrapper( + ExternalConnector* connector, + std::unique_ptr<service_manager::Service> chromium_service, + const std::string& service_name) + : chromium_service_(std::move(chromium_service)), service_binding_(this) { + DCHECK(connector); + DCHECK(chromium_service_); + + external_mojo::mojom::ExternalServicePtr ptr; + service_binding_.Bind(mojo::MakeRequest(&ptr)); + connector->RegisterService(service_name, std::move(ptr)); +} + +ChromiumServiceWrapper::~ChromiumServiceWrapper() = default; + +void ChromiumServiceWrapper::OnBindInterface( + const std::string& interface_name, + mojo::ScopedMessagePipeHandle interface_pipe) { + chromium_service_->OnBindInterface(service_manager::BindSourceInfo(), + interface_name, std::move(interface_pipe)); +} + +service_manager::mojom::ServiceRequest CreateChromiumServiceRequest( + ExternalConnector* connector, + service_manager::Identity identity) { + DCHECK(connector); + + if (identity.name().empty()) { + identity = service_manager::Identity( + "unspecified", base::Token::CreateRandom(), base::Token::CreateRandom(), + base::Token::CreateRandom()); + } + + service_manager::mojom::ServicePtr service_ptr; + auto request = mojo::MakeRequest(&service_ptr); + service_ptr->OnStart(identity, base::BindOnce(&OnStartCallback, connector)); + return request; +} + +std::unique_ptr<service_manager::Connector> CreateChromiumConnector( + ExternalConnector* connector) { + mojo::MessagePipe pipe; + connector->SendChromiumConnectorRequest(std::move(pipe.handle1)); + return std::make_unique<service_manager::Connector>( + service_manager::mojom::ConnectorPtr( + service_manager::mojom::ConnectorPtrInfo(std::move(pipe.handle0), + 0))); +} + +} // namespace external_service_support +} // namespace chromecast
diff --git a/chromecast/external_mojo/external_service_support/chromium_service.h b/chromecast/external_mojo/external_service_support/chromium_service.h new file mode 100644 index 0000000..08d568d --- /dev/null +++ b/chromecast/external_mojo/external_service_support/chromium_service.h
@@ -0,0 +1,68 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROMECAST_EXTERNAL_MOJO_EXTERNAL_SERVICE_SUPPORT_CHROMIUM_SERVICE_H_ +#define CHROMECAST_EXTERNAL_MOJO_EXTERNAL_SERVICE_SUPPORT_CHROMIUM_SERVICE_H_ + +#include <memory> +#include <string> + +#include "base/macros.h" +#include "chromecast/external_mojo/public/mojom/connector.mojom.h" +#include "mojo/public/cpp/bindings/binding.h" +#include "mojo/public/cpp/system/message_pipe.h" +#include "services/service_manager/public/cpp/identity.h" +#include "services/service_manager/public/cpp/service.h" +#include "services/service_manager/public/mojom/service.mojom.h" + +namespace service_manager { +class Connector; +class Service; +} // namespace service_manager + +namespace chromecast { +namespace external_service_support { +class ExternalConnector; + +// Provides a wrapper for a Chromium ServiceManager-based service to run in +// an external (non-Chromium) process. +class ChromiumServiceWrapper : public external_mojo::mojom::ExternalService { + public: + ChromiumServiceWrapper( + ExternalConnector* connector, + std::unique_ptr<service_manager::Service> chromium_service, + const std::string& service_name); + ~ChromiumServiceWrapper() override; + + private: + // external_mojo::mojom::ExternalService implementation: + void OnBindInterface(const std::string& interface_name, + mojo::ScopedMessagePipeHandle interface_pipe) override; + + const std::unique_ptr<service_manager::Service> chromium_service_; + + mojo::Binding<external_mojo::mojom::ExternalService> service_binding_; + + DISALLOW_COPY_AND_ASSIGN(ChromiumServiceWrapper); +}; + +// Creates a ServiceRequest (analogous to one created by Chromium +// ServiceManager) for use in creating Chromium Mojo services in an external +// process. |identity| is the desired identity of the service to be created +// (ie, what will be returned from ServiceBinding::identity() once the service +// binding is created). If you don't care about the identity, just use the +// default. +service_manager::mojom::ServiceRequest CreateChromiumServiceRequest( + ExternalConnector* connector, + service_manager::Identity identity = service_manager::Identity()); + +// Creates a service_manager::Connector instance from an external service +// ExternalConnector. +std::unique_ptr<service_manager::Connector> CreateChromiumConnector( + ExternalConnector* connector); + +} // namespace external_service_support +} // namespace chromecast + +#endif // CHROMECAST_EXTERNAL_MOJO_EXTERNAL_SERVICE_SUPPORT_CHROMIUM_SERVICE_H_
diff --git a/chromecast/external_mojo/external_service_support/external_connector.cc b/chromecast/external_mojo/external_service_support/external_connector.cc new file mode 100644 index 0000000..388d3416 --- /dev/null +++ b/chromecast/external_mojo/external_service_support/external_connector.cc
@@ -0,0 +1,142 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chromecast/external_mojo/external_service_support/external_connector.h" + +#include "base/bind.h" +#include "base/location.h" +#include "base/logging.h" +#include "base/threading/sequenced_task_runner_handle.h" +#include "base/time/time.h" +#include "chromecast/external_mojo/external_service_support/external_service.h" +#include "mojo/public/cpp/platform/named_platform_channel.h" +#include "mojo/public/cpp/platform/platform_channel_endpoint.h" +#include "mojo/public/cpp/system/invitation.h" + +namespace chromecast { +namespace external_service_support { + +namespace { +constexpr base::TimeDelta kConnectRetryDelay = + base::TimeDelta::FromMilliseconds(500); +} // namespace + +// static +void ExternalConnector::Connect( + const std::string& broker_path, + base::OnceCallback<void(std::unique_ptr<ExternalConnector>)> callback) { + DCHECK(callback); + + mojo::PlatformChannelEndpoint endpoint = + mojo::NamedPlatformChannel::ConnectToServer(broker_path); + if (!endpoint.is_valid()) { + base::SequencedTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, + base::BindOnce(&ExternalConnector::Connect, broker_path, + std::move(callback)), + kConnectRetryDelay); + return; + } + + auto invitation = mojo::IncomingInvitation::Accept(std::move(endpoint)); + auto pipe = invitation.ExtractMessagePipe(0); + if (!pipe) { + LOG(ERROR) << "Invalid message pipe"; + base::SequencedTaskRunnerHandle::Get()->PostDelayedTask( + FROM_HERE, + base::BindOnce(&ExternalConnector::Connect, broker_path, + std::move(callback)), + kConnectRetryDelay); + return; + } + external_mojo::mojom::ExternalConnectorPtr connector( + external_mojo::mojom::ExternalConnectorPtrInfo(std::move(pipe), 0)); + std::move(callback).Run( + std::make_unique<ExternalConnector>(std::move(connector))); +} + +ExternalConnector::ExternalConnector( + external_mojo::mojom::ExternalConnectorPtr connector) + : connector_(std::move(connector)) { + connector_.set_connection_error_handler(base::BindOnce( + &ExternalConnector::OnConnectionError, base::Unretained(this))); +} + +ExternalConnector::ExternalConnector( + external_mojo::mojom::ExternalConnectorPtrInfo unbound_state) + : unbound_state_(std::move(unbound_state)) { + DETACH_FROM_SEQUENCE(sequence_checker_); +} + +ExternalConnector::~ExternalConnector() = default; + +void ExternalConnector::RegisterService(const std::string& service_name, + ExternalService* service) { + RegisterService(service_name, service->GetBinding()); +} + +void ExternalConnector::RegisterService( + const std::string& service_name, + external_mojo::mojom::ExternalServicePtr service_ptr) { + if (BindConnectorIfNecessary()) { + connector_->RegisterServiceInstance(service_name, std::move(service_ptr)); + } +} + +void ExternalConnector::BindInterface( + const std::string& service_name, + const std::string& interface_name, + mojo::ScopedMessagePipeHandle interface_pipe) { + if (BindConnectorIfNecessary()) { + connector_->BindInterface(service_name, interface_name, + std::move(interface_pipe)); + } +} + +std::unique_ptr<ExternalConnector> ExternalConnector::Clone() { + external_mojo::mojom::ExternalConnectorPtrInfo connector_info; + auto request = mojo::MakeRequest(&connector_info); + if (BindConnectorIfNecessary()) { + connector_->Clone(std::move(request)); + } + return std::make_unique<ExternalConnector>(std::move(connector_info)); +} + +void ExternalConnector::SendChromiumConnectorRequest( + mojo::ScopedMessagePipeHandle request) { + if (BindConnectorIfNecessary()) { + connector_->BindChromiumConnector(std::move(request)); + } +} + +void ExternalConnector::OnConnectionError() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + connector_.reset(); + if (connection_error_callback_) { + std::move(connection_error_callback_).Run(); + } +} + +bool ExternalConnector::BindConnectorIfNecessary() { + // Bind the message pipe and SequenceChecker to the current thread the first + // time it is used to connect. + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + if (connector_.is_bound()) { + return true; + } + + if (!unbound_state_.is_valid()) { + // OnConnectionError was already called, but |this| was not destroyed. + return false; + } + + connector_.Bind(std::move(unbound_state_)); + connector_.set_connection_error_handler(base::BindOnce( + &ExternalConnector::OnConnectionError, base::Unretained(this))); + + return true; +} + +} // namespace external_service_support +} // namespace chromecast
diff --git a/chromecast/external_mojo/external_service_support/external_connector.h b/chromecast/external_mojo/external_service_support/external_connector.h new file mode 100644 index 0000000..e5f0f77 --- /dev/null +++ b/chromecast/external_mojo/external_service_support/external_connector.h
@@ -0,0 +1,97 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROMECAST_EXTERNAL_MOJO_EXTERNAL_SERVICE_SUPPORT_EXTERNAL_CONNECTOR_H_ +#define CHROMECAST_EXTERNAL_MOJO_EXTERNAL_SERVICE_SUPPORT_EXTERNAL_CONNECTOR_H_ + +#include <memory> +#include <string> +#include <utility> + +#include "base/callback.h" +#include "base/macros.h" +#include "base/sequence_checker.h" +#include "chromecast/external_mojo/public/mojom/connector.mojom.h" +#include "mojo/public/cpp/bindings/interface_ptr.h" +#include "mojo/public/cpp/bindings/interface_request.h" +#include "mojo/public/cpp/system/message_pipe.h" + +namespace chromecast { +namespace external_service_support { +class ExternalService; + +// Interface to the Mojo broker, allowing services to be registered and other +// processes to bind to registered services. Once any public methods are called +// on an instance of this class, that instance is bound to the calling thread. +// +// To use the same interface on another thread, call Clone() and pass the new +// instance to the desired thread before calling any public methods on it. +class ExternalConnector { + public: + static void Connect( + const std::string& broker_path, + base::OnceCallback<void(std::unique_ptr<ExternalConnector>)> callback); + + explicit ExternalConnector( + external_mojo::mojom::ExternalConnectorPtr connector); + explicit ExternalConnector( + external_mojo::mojom::ExternalConnectorPtrInfo unbound_state); + ~ExternalConnector(); + + // Sets the callback that will be called if this class loses its connection to + // the Mojo broker. Note that once the connection is lost, this instance + // becomes nonfunctional (all public methods are no-ops); a new connection + // must be made instead. + void set_connection_error_callback(base::OnceClosure callback) { + connection_error_callback_ = std::move(callback); + } + + // Registers a service that other Mojo processes/services can bind to. Others + // can call BindInterface(|service_name|, interface_name) to bind to this + // |service|. + void RegisterService(const std::string& service_name, + ExternalService* service); + void RegisterService(const std::string& service_name, + external_mojo::mojom::ExternalServicePtr service_ptr); + + // Asks the Mojo broker to bind to a matching interface on the service with + // the given |service_name|. If the service does not yet exist, the binding + // will remain in progress until the service is registered. + template <typename Interface> + void BindInterface(const std::string& service_name, + mojo::InterfacePtr<Interface>* ptr) { + BindInterface(service_name, Interface::Name_, + mojo::MakeRequest(ptr).PassMessagePipe()); + } + + void BindInterface(const std::string& service_name, + const std::string& interface_name, + mojo::ScopedMessagePipeHandle interface_pipe); + + // Creates a new instance of this class which may be passed to another thread. + // The returned object may be passed across sequences until any of its public + // methods are called, at which point it becomes bound to the calling + // sequence. + std::unique_ptr<ExternalConnector> Clone(); + + // Sends a request for a Chromium ServiceManager connector. + void SendChromiumConnectorRequest(mojo::ScopedMessagePipeHandle request); + + private: + void OnConnectionError(); + bool BindConnectorIfNecessary(); + + external_mojo::mojom::ExternalConnectorPtr connector_; + external_mojo::mojom::ExternalConnectorPtrInfo unbound_state_; + base::OnceClosure connection_error_callback_; + + SEQUENCE_CHECKER(sequence_checker_); + + DISALLOW_COPY_AND_ASSIGN(ExternalConnector); +}; + +} // namespace external_service_support +} // namespace chromecast + +#endif // CHROMECAST_EXTERNAL_MOJO_EXTERNAL_SERVICE_SUPPORT_EXTERNAL_CONNECTOR_H_
diff --git a/chromecast/external_mojo/external_service_support/external_service.cc b/chromecast/external_mojo/external_service_support/external_service.cc new file mode 100644 index 0000000..74e7900 --- /dev/null +++ b/chromecast/external_mojo/external_service_support/external_service.cc
@@ -0,0 +1,51 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chromecast/external_mojo/external_service_support/external_service.h" + +#include "base/logging.h" + +namespace chromecast { +namespace external_service_support { + +ExternalService::ExternalService() : service_binding_(this) {} + +ExternalService::~ExternalService() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); +} + +external_mojo::mojom::ExternalServicePtr ExternalService::GetBinding() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + service_binding_.Close(); + external_mojo::mojom::ExternalServicePtr ptr; + service_binding_.Bind(mojo::MakeRequest(&ptr)); + return ptr; +} + +void ExternalService::AddInterface(const std::string& interface_name, + std::unique_ptr<Binder> binder) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + RemoveInterface(interface_name); + binders_.emplace(interface_name, std::move(binder)); +} + +void ExternalService::RemoveInterface(const std::string& interface_name) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + binders_.erase(interface_name); +} + +void ExternalService::OnBindInterface( + const std::string& interface_name, + mojo::ScopedMessagePipeHandle interface_pipe) { + auto it = binders_.find(interface_name); + if (it == binders_.end()) { + LOG(ERROR) << interface_name << " cannot be bound (not found)"; + return; + } + + it->second->BindInterface(interface_name, std::move(interface_pipe)); +} + +} // namespace external_service_support +} // namespace chromecast
diff --git a/chromecast/external_mojo/external_service_support/external_service.h b/chromecast/external_mojo/external_service_support/external_service.h new file mode 100644 index 0000000..4a9aabd --- /dev/null +++ b/chromecast/external_mojo/external_service_support/external_service.h
@@ -0,0 +1,107 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROMECAST_EXTERNAL_MOJO_EXTERNAL_SERVICE_SUPPORT_EXTERNAL_SERVICE_H_ +#define CHROMECAST_EXTERNAL_MOJO_EXTERNAL_SERVICE_SUPPORT_EXTERNAL_SERVICE_H_ + +#include <map> +#include <memory> +#include <string> +#include <utility> + +#include "base/callback.h" +#include "base/macros.h" +#include "base/sequence_checker.h" +#include "chromecast/external_mojo/public/mojom/connector.mojom.h" +#include "mojo/public/cpp/bindings/binding.h" +#include "mojo/public/cpp/bindings/interface_request.h" +#include "mojo/public/cpp/system/message_pipe.h" + +namespace chromecast { +namespace external_service_support { + +// API for external (non-Chromium process) Mojo services. +class ExternalService : public external_mojo::mojom::ExternalService { + public: + ExternalService(); + ~ExternalService() override; + + // Returns the Mojo binding for this service. + external_mojo::mojom::ExternalServicePtr GetBinding(); + + // Adds an interface that users of this service may bind to. To avoid races + // where the service is registered but interfaces cannot be bound by other + // processes/services, add all interfaces before registering this service. + // The |bind_callback| will be called once for each bind attempt. The callback + // will not be called after this ExternalService instance is destroyed. + template <typename Interface> + void AddInterface( + base::RepeatingCallback<void(mojo::InterfaceRequest<Interface>)> + bind_callback) { + RemoveInterface<Interface>(); + AddInterface(Interface::Name_, std::make_unique<CallbackBinder<Interface>>( + std::move(bind_callback))); + } + + // Removes an interface, preventing new bindings from being created. Does not + // affect existing bindings. + template <typename Interface> + void RemoveInterface() { + RemoveInterface(Interface::Name_); + } + + private: + class Binder { + public: + virtual ~Binder() = default; + + // Provides an abstract interface to the templated callback-based binder + // below. + virtual void BindInterface( + const std::string& interface_name, + mojo::ScopedMessagePipeHandle interface_pipe) = 0; + }; + + template <typename Interface> + class CallbackBinder : public Binder { + public: + CallbackBinder( + base::RepeatingCallback<void(mojo::InterfaceRequest<Interface>)> + bind_callback) + : bind_callback_(bind_callback) {} + + private: + // Binder implementation: + void BindInterface(const std::string& interface_name, + mojo::ScopedMessagePipeHandle interface_pipe) override { + mojo::InterfaceRequest<Interface> request(std::move(interface_pipe)); + bind_callback_.Run(std::move(request)); + } + + base::RepeatingCallback<void(mojo::InterfaceRequest<Interface>)> + bind_callback_; + + DISALLOW_COPY_AND_ASSIGN(CallbackBinder); + }; + + void AddInterface(const std::string& interface_name, + std::unique_ptr<Binder> binder); + void RemoveInterface(const std::string& interface_name); + + // external_mojo::mojom::ExternalService implementation: + void OnBindInterface(const std::string& interface_name, + mojo::ScopedMessagePipeHandle interface_pipe) override; + + std::map<std::string, std::unique_ptr<Binder>> binders_; + mojo::Binding<external_mojo::mojom::ExternalService> service_binding_; + + SEQUENCE_CHECKER(sequence_checker_); + + DISALLOW_COPY_AND_ASSIGN(ExternalService); +}; + +} // namespace external_service_support +} // namespace chromecast + +#endif // CHROMECAST_EXTERNAL_MOJO_EXTERNAL_SERVICE_SUPPORT_EXTERNAL_SERVICE_H_
diff --git a/chromecast/external_mojo/external_service_support/process_setup.cc b/chromecast/external_mojo/external_service_support/process_setup.cc new file mode 100644 index 0000000..98f4435 --- /dev/null +++ b/chromecast/external_mojo/external_service_support/process_setup.cc
@@ -0,0 +1,34 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chromecast/external_mojo/external_service_support/process_setup.h" + +#include <locale.h> +#include <signal.h> + +#include "base/command_line.h" +#include "base/logging.h" +#include "build/build_config.h" + +namespace chromecast { +namespace external_service_support { + +void CommonProcessInitialization(int argc, char** argv) { +#if !defined(OS_ANDROID) + // Set C library locale to make sure CommandLine can parse argument values + // in the correct encoding. + setlocale(LC_ALL, ""); + setlocale(LC_NUMERIC, "C"); +#endif + + base::CommandLine::Init(argc, argv); + logging::LoggingSettings settings; + settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG; + logging::InitLogging(settings); + + CHECK_NE(SIG_ERR, signal(SIGPIPE, SIG_IGN)); +} + +} // namespace external_service_support +} // namespace chromecast
diff --git a/chromecast/external_mojo/external_service_support/process_setup.h b/chromecast/external_mojo/external_service_support/process_setup.h new file mode 100644 index 0000000..d1e4580 --- /dev/null +++ b/chromecast/external_mojo/external_service_support/process_setup.h
@@ -0,0 +1,20 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROMECAST_EXTERNAL_MOJO_EXTERNAL_SERVICE_SUPPORT_PROCESS_SETUP_H_ +#define CHROMECAST_EXTERNAL_MOJO_EXTERNAL_SERVICE_SUPPORT_PROCESS_SETUP_H_ + +#include <string> + +namespace chromecast { +namespace external_service_support { + +// Common initialization code for external Mojo processes. Should be called +// early in main(). +void CommonProcessInitialization(int argc, char** argv); + +} // namespace external_service_support +} // namespace chromecast + +#endif // CHROMECAST_EXTERNAL_MOJO_EXTERNAL_SERVICE_SUPPORT_PROCESS_SETUP_H_
diff --git a/chromecast/external_mojo/external_service_support/service_process.h b/chromecast/external_mojo/external_service_support/service_process.h new file mode 100644 index 0000000..1369849 --- /dev/null +++ b/chromecast/external_mojo/external_service_support/service_process.h
@@ -0,0 +1,28 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROMECAST_EXTERNAL_MOJO_EXTERNAL_SERVICE_SUPPORT_SERVICE_PROCESS_H_ +#define CHROMECAST_EXTERNAL_MOJO_EXTERNAL_SERVICE_SUPPORT_SERVICE_PROCESS_H_ + +#include <memory> + +namespace chromecast { +namespace external_service_support { + +class ExternalConnector; + +// Provides an entrypoint for external processes that are using Mojo with +// standalone_service_main.cc. +class ServiceProcess { + public: + virtual ~ServiceProcess() = default; + + // Entrypoint from standalone_service_main.cc. + static std::unique_ptr<ServiceProcess> Create(ExternalConnector* connector); +}; + +} // namespace external_service_support +} // namespace chromecast + +#endif // CHROMECAST_EXTERNAL_MOJO_EXTERNAL_SERVICE_SUPPORT_SERVICE_PROCESS_H_
diff --git a/chromecast/external_mojo/external_service_support/standalone_mojo_broker.cc b/chromecast/external_mojo/external_service_support/standalone_mojo_broker.cc new file mode 100644 index 0000000..1bc8111 --- /dev/null +++ b/chromecast/external_mojo/external_service_support/standalone_mojo_broker.cc
@@ -0,0 +1,39 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <string> +#include <vector> + +#include "base/at_exit.h" +#include "base/message_loop/message_loop.h" +#include "base/message_loop/message_pump_for_io.h" +#include "base/run_loop.h" +#include "chromecast/external_mojo/external_service_support/process_setup.h" +#include "chromecast/external_mojo/public/cpp/external_mojo_broker.h" +#include "mojo/core/embedder/embedder.h" +#include "mojo/core/embedder/scoped_ipc_support.h" + +// Standalone Mojo broker process. + +int main(int argc, char** argv) { + base::AtExitManager exit_manager; + chromecast::external_service_support::CommonProcessInitialization(argc, argv); + + base::MessageLoopForIO main_loop; + base::RunLoop run_loop; + + mojo::core::Configuration mojo_config; + mojo_config.is_broker_process = true; + mojo::core::Init(mojo_config); + + mojo::core::ScopedIPCSupport ipc_support( + main_loop.task_runner(), + mojo::core::ScopedIPCSupport::ShutdownPolicy::CLEAN); + + chromecast::external_mojo::ExternalMojoBroker broker; + + run_loop.Run(); + + return 0; +}
diff --git a/chromecast/external_mojo/external_service_support/standalone_service_main.cc b/chromecast/external_mojo/external_service_support/standalone_service_main.cc new file mode 100644 index 0000000..d29b11a --- /dev/null +++ b/chromecast/external_mojo/external_service_support/standalone_service_main.cc
@@ -0,0 +1,58 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <memory> +#include <utility> + +#include "base/at_exit.h" +#include "base/bind.h" +#include "base/message_loop/message_loop.h" +#include "base/message_loop/message_pump_for_io.h" +#include "chromecast/external_mojo/external_service_support/external_connector.h" +#include "chromecast/external_mojo/external_service_support/process_setup.h" +#include "chromecast/external_mojo/external_service_support/service_process.h" +#include "chromecast/external_mojo/public/cpp/common.h" +#include "mojo/core/embedder/embedder.h" +#include "mojo/core/embedder/scoped_ipc_support.h" + +// Simple process entrypoint for standalone Mojo services. + +struct GlobalState { + std::unique_ptr<chromecast::external_service_support::ServiceProcess> + service_process; + std::unique_ptr<chromecast::external_service_support::ExternalConnector> + connector; +}; + +void OnConnected( + GlobalState* state, + std::unique_ptr<chromecast::external_service_support::ExternalConnector> + connector) { + state->connector = std::move(connector); + state->service_process = + chromecast::external_service_support::ServiceProcess::Create( + state->connector.get()); +} + +int main(int argc, char** argv) { + base::AtExitManager exit_manager; + chromecast::external_service_support::CommonProcessInitialization(argc, argv); + + base::MessageLoopForIO main_loop; + base::RunLoop run_loop; + + mojo::core::Init(); + + mojo::core::ScopedIPCSupport ipc_support( + main_loop.task_runner(), + mojo::core::ScopedIPCSupport::ShutdownPolicy::CLEAN); + + GlobalState state; + chromecast::external_service_support::ExternalConnector::Connect( + chromecast::external_mojo::GetBrokerPath(), + base::BindOnce(&OnConnected, &state)); + run_loop.Run(); + + return 0; +}
diff --git a/chromecast/external_mojo/public/cpp/BUILD.gn b/chromecast/external_mojo/public/cpp/BUILD.gn new file mode 100644 index 0000000..ca1fca0 --- /dev/null +++ b/chromecast/external_mojo/public/cpp/BUILD.gn
@@ -0,0 +1,30 @@ +# Copyright 2019 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +source_set("common") { + sources = [ + "common.cc", + "common.h", + ] + deps = [ + "//base", + ] +} + +source_set("external_mojo_broker") { + sources = [ + "external_mojo_broker.cc", + "external_mojo_broker.h", + ] + deps = [ + ":common", + "//base", + "//chromecast/external_mojo/public/mojom", + "//mojo/public/cpp/bindings", + "//mojo/public/cpp/platform", + "//mojo/public/cpp/system", + "//services/service_manager/public/cpp", + "//services/service_manager/public/mojom", + ] +}
diff --git a/chromecast/external_mojo/public/cpp/common.cc b/chromecast/external_mojo/public/cpp/common.cc new file mode 100644 index 0000000..a407f783 --- /dev/null +++ b/chromecast/external_mojo/public/cpp/common.cc
@@ -0,0 +1,35 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chromecast/external_mojo/public/cpp/common.h" + +#include "base/command_line.h" +#include "base/strings/string_piece.h" + +namespace chromecast { +namespace external_mojo { + +namespace { +// Default path for Unix domain socket used by external Mojo services to connect +// to Mojo services within cast_shell. +constexpr base::StringPiece kDefaultBrokerPath("/tmp/cast_mojo_broker"); + +// Command-line arg to change the Unix domain socket path to connect to the +// Cast Mojo broker. +constexpr base::StringPiece kCastMojoBrokerPathSwitch("cast-mojo-broker-path"); +} // namespace + +std::string GetBrokerPath() { + std::string broker_path; + base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); + if (command_line->HasSwitch(kCastMojoBrokerPathSwitch)) { + broker_path = command_line->GetSwitchValueASCII(kCastMojoBrokerPathSwitch); + } else { + broker_path = std::string(kDefaultBrokerPath); + } + return broker_path; +} + +} // namespace external_mojo +} // namespace chromecast
diff --git a/chromecast/external_mojo/public/cpp/common.h b/chromecast/external_mojo/public/cpp/common.h new file mode 100644 index 0000000..3f263f7a --- /dev/null +++ b/chromecast/external_mojo/public/cpp/common.h
@@ -0,0 +1,20 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROMECAST_EXTERNAL_MOJO_PUBLIC_CPP_COMMON_H_ +#define CHROMECAST_EXTERNAL_MOJO_PUBLIC_CPP_COMMON_H_ + +#include <string> + +namespace chromecast { +namespace external_mojo { + +// Returns the Unix domain socket path to use to connect to the Mojo broker. +// You can set the path on the command line with --mojo_broker_path=<path>. +std::string GetBrokerPath(); + +} // namespace external_mojo +} // namespace chromecast + +#endif // CHROMECAST_EXTERNAL_MOJO_PUBLIC_CPP_COMMON_H_
diff --git a/chromecast/external_mojo/public/cpp/external_mojo_broker.cc b/chromecast/external_mojo/public/cpp/external_mojo_broker.cc new file mode 100644 index 0000000..a5a51db --- /dev/null +++ b/chromecast/external_mojo/public/cpp/external_mojo_broker.cc
@@ -0,0 +1,321 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chromecast/external_mojo/public/cpp/external_mojo_broker.h" + +#include <map> +#include <utility> + +#include "base/bind.h" +#include "base/bind_helpers.h" +#include "base/location.h" +#include "base/logging.h" +#include "base/macros.h" +#include "base/message_loop/message_loop_current.h" +#include "base/message_loop/message_pump_for_io.h" +#include "base/optional.h" +#include "base/token.h" +#include "chromecast/external_mojo/public/cpp/common.h" +#include "chromecast/external_mojo/public/mojom/connector.mojom.h" +#include "mojo/public/cpp/bindings/binding_set.h" +#include "mojo/public/cpp/platform/named_platform_channel.h" +#include "mojo/public/cpp/platform/platform_channel_endpoint.h" +#include "mojo/public/cpp/platform/platform_handle.h" +#include "mojo/public/cpp/platform/socket_utils_posix.h" +#include "mojo/public/cpp/system/invitation.h" +#include "services/service_manager/public/cpp/connector.h" +#include "services/service_manager/public/cpp/constants.h" +#include "services/service_manager/public/cpp/identity.h" +#include "services/service_manager/public/cpp/service.h" +#include "services/service_manager/public/cpp/service_binding.h" +#include "services/service_manager/public/cpp/service_filter.h" +#include "services/service_manager/public/mojom/connector.mojom.h" +#include "services/service_manager/public/mojom/service.mojom.h" + +namespace chromecast { +namespace external_mojo { + +namespace { + +void OnRegisterServiceResult(const std::string& service_name, + service_manager::mojom::ConnectResult result) { + // RegisterServiceInstance() currently returns INVALID_ARGUMENT on success. + if (result == service_manager::mojom::ConnectResult::ACCESS_DENIED) { + LOG(WARNING) << "Failed to register external service proxy for " + << service_name; + } +} + +void OnInternalBindResult( + const std::string& service_name, + const std::string& interface_name, + service_manager::mojom::ConnectResult result, + const base::Optional<service_manager::Identity>& identity) { + if (result != service_manager::mojom::ConnectResult::SUCCEEDED) { + LOG(ERROR) << "Failed to bind " << service_name << ":" << interface_name + << ", result = " << result; + } +} + +} // namespace + +class ExternalMojoBroker::ConnectorImpl : public mojom::ExternalConnector { + public: + ConnectorImpl() = default; + + void InitializeChromium( + std::unique_ptr<service_manager::Connector> connector, + const std::vector<std::string>& external_services_to_proxy) { + DCHECK(connector); + connector_ = std::move(connector); + RegisterExternalServices(external_services_to_proxy); + } + + void AddBinding(mojom::ExternalConnectorRequest request) { + bindings_.AddBinding(this, std::move(request)); + } + + private: + class ExternalServiceProxy : public ::service_manager::Service { + public: + ExternalServiceProxy(ConnectorImpl* connector, + std::string service_name, + ::service_manager::mojom::ServiceRequest request) + : connector_(connector), + service_name_(std::move(service_name)), + service_binding_(this, std::move(request)) { + DCHECK(connector_); + } + + private: + void OnBindInterface( + const service_manager::BindSourceInfo& source, + const std::string& interface_name, + mojo::ScopedMessagePipeHandle interface_pipe) override { + connector_->BindExternalInterface(service_name_, interface_name, + std::move(interface_pipe)); + } + + ConnectorImpl* const connector_; + const std::string service_name_; + service_manager::ServiceBinding service_binding_; + + DISALLOW_COPY_AND_ASSIGN(ExternalServiceProxy); + }; + + struct PendingBindRequest { + PendingBindRequest(const std::string& interface_name, + mojo::ScopedMessagePipeHandle interface_pipe) + : interface_name(interface_name), + interface_pipe(std::move(interface_pipe)) {} + + const std::string interface_name; + mojo::ScopedMessagePipeHandle interface_pipe; + }; + + void RegisterExternalServices( + const std::vector<std::string>& external_services_to_proxy) { + if (external_services_to_proxy.empty()) { + return; + } + + for (const auto& service_name : external_services_to_proxy) { + LOG(INFO) << "Register proxy for external " << service_name; + service_manager::mojom::ServicePtr service_ptr; + registered_external_services_[service_name] = + std::make_unique<ExternalServiceProxy>( + this, service_name, mojo::MakeRequest(&service_ptr)); + + service_manager::mojom::PIDReceiverPtr pid_receiver; + connector_->RegisterServiceInstance( + service_manager::Identity(service_name, + service_manager::kSystemInstanceGroup, + base::Token{}, base::Token::CreateRandom()), + std::move(service_ptr), mojo::MakeRequest(&pid_receiver), + base::BindOnce(&OnRegisterServiceResult, service_name)); + } + } + + // Helper for ExternalServiceProxy. + void BindExternalInterface(const std::string& service_name, + const std::string& interface_name, + mojo::ScopedMessagePipeHandle interface_pipe) { + LOG(INFO) << "Internal request for " << service_name << ":" + << interface_name; + auto it = services_.find(service_name); + if (it != services_.end()) { + it->second->OnBindInterface(interface_name, std::move(interface_pipe)); + return; + } + + ServiceNotFound(service_name, interface_name, std::move(interface_pipe)); + } + + // standalone::mojom::Connector implementation: + void RegisterServiceInstance(const std::string& service_name, + mojom::ExternalServicePtr service) override { + if (services_.find(service_name) != services_.end()) { + LOG(ERROR) << "Duplicate service " << service_name; + return; + } + LOG(INFO) << "Register service " << service_name; + service.set_connection_error_handler(base::BindOnce( + &ConnectorImpl::OnServiceLost, base::Unretained(this), service_name)); + auto it = services_.emplace(service_name, std::move(service)).first; + + auto p = pending_bind_requests_.find(service_name); + if (p != pending_bind_requests_.end()) { + for (auto& request : p->second) { + it->second->OnBindInterface(request.interface_name, + std::move(request.interface_pipe)); + } + pending_bind_requests_.erase(p); + } + } + + void BindInterface(const std::string& service_name, + const std::string& interface_name, + mojo::ScopedMessagePipeHandle interface_pipe) override { + LOG(INFO) << "Request for " << service_name << ":" << interface_name; + auto it = services_.find(service_name); + if (it != services_.end()) { + LOG(INFO) << "Found externally-registered " << service_name; + it->second->OnBindInterface(interface_name, std::move(interface_pipe)); + return; + } + + if (!connector_) { + ServiceNotFound(service_name, interface_name, std::move(interface_pipe)); + return; + } + + connector_->QueryService( + service_name, + base::BindOnce(&ConnectorImpl::OnQueryResult, base::Unretained(this), + service_name, interface_name, + std::move(interface_pipe))); + } + + void Clone(mojom::ExternalConnectorRequest request) override { + AddBinding(std::move(request)); + } + + void BindChromiumConnector( + mojo::ScopedMessagePipeHandle interface_pipe) override { + if (!connector_) { + // TODO(kmackay) Provide a simulated ServiceManager instead. + return; + } + + connector_->BindConnectorRequest( + service_manager::mojom::ConnectorRequest(std::move(interface_pipe))); + } + + void OnQueryResult(const std::string& service_name, + const std::string& interface_name, + mojo::ScopedMessagePipeHandle interface_pipe, + service_manager::mojom::ServiceInfoPtr info) { + if (!info) { + ServiceNotFound(service_name, interface_name, std::move(interface_pipe)); + return; + } + + LOG(INFO) << "Found internal " << service_name; + connector_->BindInterface( + service_manager::ServiceFilter::ByName(service_name), interface_name, + std::move(interface_pipe), + service_manager::mojom::BindInterfacePriority::kImportant, + base::BindOnce(&OnInternalBindResult, service_name, interface_name)); + } + + void ServiceNotFound(const std::string& service_name, + const std::string& interface_name, + mojo::ScopedMessagePipeHandle interface_pipe) { + LOG(INFO) << service_name << " not found"; + // Assume the service will be registered later, and wait until then. + pending_bind_requests_[service_name].emplace_back( + interface_name, std::move(interface_pipe)); + } + + void OnServiceLost(const std::string& service_name) { + LOG(INFO) << service_name << " disconnected"; + services_.erase(service_name); + } + + std::unique_ptr<service_manager::Connector> connector_; + + mojo::BindingSet<mojom::ExternalConnector> bindings_; + std::map<std::string, std::unique_ptr<ExternalServiceProxy>> + registered_external_services_; + + std::map<std::string, mojom::ExternalServicePtr> services_; + std::map<std::string, std::vector<PendingBindRequest>> pending_bind_requests_; + + DISALLOW_COPY_AND_ASSIGN(ConnectorImpl); +}; + +class ExternalMojoBroker::ReadWatcher + : public base::MessagePumpForIO::FdWatcher { + public: + ReadWatcher(ConnectorImpl* connector, mojo::PlatformHandle listen_handle) + : connector_(connector), + listen_handle_(std::move(listen_handle)), + watch_controller_(FROM_HERE) { + DCHECK(listen_handle_.is_valid()); + base::MessageLoopCurrentForIO::Get().WatchFileDescriptor( + listen_handle_.GetFD().get(), true /* persistent */, + base::MessagePumpForIO::WATCH_READ, &watch_controller_, this); + } + + // base::MessagePumpForIO::FdWatcher implementation: + void OnFileCanReadWithoutBlocking(int fd) override { + base::ScopedFD accepted_fd; + if (mojo::AcceptSocketConnection(fd, &accepted_fd, + false /* check_peer_user */) && + accepted_fd.is_valid()) { + mojo::OutgoingInvitation invitation; + auto pipe = invitation.AttachMessagePipe(0); + mojo::OutgoingInvitation::Send( + std::move(invitation), base::kNullProcessHandle, + mojo::PlatformChannelEndpoint( + mojo::PlatformHandle(std::move(accepted_fd)))); + connector_->AddBinding(mojom::ExternalConnectorRequest(std::move(pipe))); + } + } + + void OnFileCanWriteWithoutBlocking(int /* fd */) override {} + + private: + ConnectorImpl* const connector_; + const mojo::PlatformHandle listen_handle_; + base::MessagePumpForIO::FdWatchController watch_controller_; + + DISALLOW_COPY_AND_ASSIGN(ReadWatcher); +}; + +ExternalMojoBroker::ExternalMojoBroker() { + connector_ = std::make_unique<ConnectorImpl>(); + + mojo::NamedPlatformChannel::Options channel_options; + channel_options.server_name = GetBrokerPath(); + mojo::NamedPlatformChannel named_channel(channel_options); + + mojo::PlatformChannelServerEndpoint server_endpoint = + named_channel.TakeServerEndpoint(); + DCHECK(server_endpoint.is_valid()); + read_watcher_ = std::make_unique<ReadWatcher>( + connector_.get(), server_endpoint.TakePlatformHandle()); +} + +void ExternalMojoBroker::InitializeChromium( + std::unique_ptr<service_manager::Connector> connector, + const std::vector<std::string>& external_services_to_proxy) { + connector_->InitializeChromium(std::move(connector), + external_services_to_proxy); +} + +ExternalMojoBroker::~ExternalMojoBroker() = default; + +} // namespace external_mojo +} // namespace chromecast
diff --git a/chromecast/external_mojo/public/cpp/external_mojo_broker.h b/chromecast/external_mojo/public/cpp/external_mojo_broker.h new file mode 100644 index 0000000..eb302ef7 --- /dev/null +++ b/chromecast/external_mojo/public/cpp/external_mojo_broker.h
@@ -0,0 +1,49 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROMECAST_EXTERNAL_MOJO_PUBLIC_CPP_EXTERNAL_MOJO_BROKER_H_ +#define CHROMECAST_EXTERNAL_MOJO_PUBLIC_CPP_EXTERNAL_MOJO_BROKER_H_ + +#include <memory> +#include <string> +#include <vector> + +#include "base/macros.h" + +namespace service_manager { +class Connector; +} // namespace service_manager + +namespace chromecast { +namespace external_mojo { + +// Manages connections from Mojo services in external processes. May be used +// either in a standalone broker process, or embedded into a Chromium process. +class ExternalMojoBroker { + public: + ExternalMojoBroker(); + ~ExternalMojoBroker(); + + // Initializes the embedded into a Chromium process (eg in cast_shell). + // |connector| is the ServiceManager connector within the Chromium process. + // |external_services_to_proxy| is a list of the names of external services + // that should be made accessible to Mojo services running within Chromium. + void InitializeChromium( + std::unique_ptr<service_manager::Connector> connector, + const std::vector<std::string>& external_services_to_proxy); + + private: + class ConnectorImpl; + class ReadWatcher; + + std::unique_ptr<ConnectorImpl> connector_; + std::unique_ptr<ReadWatcher> read_watcher_; + + DISALLOW_COPY_AND_ASSIGN(ExternalMojoBroker); +}; + +} // namespace external_mojo +} // namespace chromecast + +#endif // CHROMECAST_EXTERNAL_MOJO_PUBLIC_CPP_EXTERNAL_MOJO_BROKER_H_
diff --git a/chromecast/external_mojo/public/mojom/BUILD.gn b/chromecast/external_mojo/public/mojom/BUILD.gn new file mode 100644 index 0000000..0e60fb8 --- /dev/null +++ b/chromecast/external_mojo/public/mojom/BUILD.gn
@@ -0,0 +1,11 @@ +# Copyright 2019 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//mojo/public/tools/bindings/mojom.gni") + +mojom("mojom") { + sources = [ + "connector.mojom", + ] +}
diff --git a/chromecast/external_mojo/public/mojom/OWNERS b/chromecast/external_mojo/public/mojom/OWNERS new file mode 100644 index 0000000..08850f4 --- /dev/null +++ b/chromecast/external_mojo/public/mojom/OWNERS
@@ -0,0 +1,2 @@ +per-file *.mojom=set noparent +per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/chromecast/external_mojo/public/mojom/connector.mojom b/chromecast/external_mojo/public/mojom/connector.mojom new file mode 100644 index 0000000..9939a4b --- /dev/null +++ b/chromecast/external_mojo/public/mojom/connector.mojom
@@ -0,0 +1,39 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +module chromecast.external_mojo.mojom; + +// Interface for external (non-Chromium process) Mojo services to receive Mojo +// binding requests from other processes/services. +interface ExternalService { + // Called when another service/process wants to bind to the interface with the + // given |interface_name| on this service. + OnBindInterface(string interface_name, + handle<message_pipe> interface_pipe); +}; + +// Interface to register external Mojo services to the broker, and bind to +// registered Mojo services. This provides functionality similar to Chromium's +// service manager, but avoids any dependency on the service manager since this +// is intended for use by code outside of the Chrome repository. +interface ExternalConnector { + // Registers a service with the broker. + RegisterServiceInstance(string service_name, + ExternalService service); + + // Asks the broker to pass the |interface_pipe| to the registered service with + // the given |service_name| to be bound to the appropriate interface. If the + // |service_name| is not registered yet, the request will remain pending until + // the service is registered. + BindInterface(string service_name, + string interface_name, + handle<message_pipe> interface_pipe); + + // Creates a new binding to the Connector implementation, to allow clients to + // clone Connector pointers for use on other threads. + Clone(ExternalConnector& request); + + // Binds to a Chromium service_manager::Connector instance, if possible. + BindChromiumConnector(handle<message_pipe> interface_pipe); +};
diff --git a/chromeos/network/network_state_handler.cc b/chromeos/network/network_state_handler.cc index 4a2e1d2..98167d34 100644 --- a/chromeos/network/network_state_handler.cc +++ b/chromeos/network/network_state_handler.cc
@@ -1012,15 +1012,21 @@ void NetworkStateHandler::RequestScan(const NetworkTypePattern& type) { NET_LOG_USER("RequestScan", type.ToDebugString()); - - if (type.MatchesType(shill::kTypeWifi)) { - shill_property_handler_->RequestScanByType(shill::kTypeWifi); + if (type.MatchesPattern(NetworkTypePattern::WiFi())) { + if (IsTechnologyEnabled(NetworkTypePattern::WiFi())) + shill_property_handler_->RequestScanByType(shill::kTypeWifi); + else if (type.Equals(NetworkTypePattern::WiFi())) + return; // Skip notify if disabled and wifi only requested. } - if (type.Equals(NetworkTypePattern::Primitive(shill::kTypeCellular))) { + if (type.Equals(NetworkTypePattern::Cellular())) { // Only request a Cellular scan if Cellular is requested explicitly. - shill_property_handler_->RequestScanByType(shill::kTypeCellular); + if (IsTechnologyEnabled(NetworkTypePattern::Cellular())) + shill_property_handler_->RequestScanByType(shill::kTypeCellular); + else + return; // Skip notify if disabled and cellular only requested. } + // Note: for Tether we initiate the scan in the observer. NotifyScanRequested(type); }
diff --git a/chromeos/network/network_state_handler_unittest.cc b/chromeos/network/network_state_handler_unittest.cc index 263ee59..02e900ba 100644 --- a/chromeos/network/network_state_handler_unittest.cc +++ b/chromeos/network/network_state_handler_unittest.cc
@@ -1821,6 +1821,15 @@ NetworkTypePattern::WiFi().Equals(test_observer_->scan_requests()[0])); EXPECT_TRUE( NetworkTypePattern::Tether().Equals(test_observer_->scan_requests()[1])); + + // Disable wifi, scan request for wifi only should not send a notification. + test_observer_->reset_change_counts(); + network_state_handler_->SetTechnologyEnabled( + NetworkTypePattern::WiFi(), false, network_handler::ErrorCallback()); + network_state_handler_->RequestScan(NetworkTypePattern::WiFi()); + EXPECT_EQ(0u, test_observer_->scan_requested_count()); + network_state_handler_->RequestScan(NetworkTypePattern::Default()); + EXPECT_EQ(1u, test_observer_->scan_requested_count()); } TEST_F(NetworkStateHandlerTest, NetworkGuidInProfile) {
diff --git a/chromeos/services/assistant/BUILD.gn b/chromeos/services/assistant/BUILD.gn index d5b58c6..1de270d 100644 --- a/chromeos/services/assistant/BUILD.gn +++ b/chromeos/services/assistant/BUILD.gn
@@ -68,6 +68,8 @@ "default_url_request_context_getter.h", "media_session/assistant_media_session.cc", "media_session/assistant_media_session.h", + "platform/audio_device_owner.cc", + "platform/audio_device_owner.h", "platform/audio_input_impl.cc", "platform/audio_input_impl.h", "platform/audio_input_provider_impl.cc", @@ -86,6 +88,8 @@ "platform/power_manager_provider_impl.h", "platform/system_provider_impl.cc", "platform/system_provider_impl.h", + "platform/volume_control_impl.cc", + "platform/volume_control_impl.h", "platform_api_impl.cc", "platform_api_impl.h", "utils.cc",
diff --git a/chromeos/services/assistant/chromium_http_connection.cc b/chromeos/services/assistant/chromium_http_connection.cc index 2e2f91a..36afbed 100644 --- a/chromeos/services/assistant/chromium_http_connection.cc +++ b/chromeos/services/assistant/chromium_http_connection.cc
@@ -20,6 +20,14 @@ using network::SharedURLLoaderFactory; using network::SharedURLLoaderFactoryInfo; +// A macro which ensures we are running on the main thread. +#define ENSURE_MAIN_THREAD(method, ...) \ + if (!task_runner_->RunsTasksInCurrentSequence()) { \ + task_runner_->PostTask(FROM_HERE, \ + base::BindOnce(method, this, ##__VA_ARGS__)); \ + return; \ + } + namespace chromeos { namespace assistant { @@ -138,7 +146,8 @@ } void ChromiumHttpConnection::EnableHeaderResponse() { - NOTIMPLEMENTED(); + ENSURE_MAIN_THREAD(&ChromiumHttpConnection::EnableHeaderResponse) + enable_header_response_ = true; } void ChromiumHttpConnection::EnablePartialResults() { @@ -274,7 +283,13 @@ void ChromiumHttpConnection::OnDataReceived(base::StringPiece string_piece, base::OnceClosure resume) { DCHECK(handle_partial_response_); - delegate_->OnPartialResponse(string_piece.as_string()); + if (enable_header_response_) { + // Cache the partial responses, we need to send the headers back before + // any |OnPartialResposne| to honor the API contract. + partial_response_cache_.emplace_back(string_piece.as_string()); + } else { + delegate_->OnPartialResponse(string_piece.as_string()); + } std::move(resume).Run(); } @@ -293,6 +308,12 @@ response_code = url_loader_->ResponseInfo()->headers->response_code(); } + if (enable_header_response_) { + delegate_->OnHeaderResponse(raw_headers); + for (auto& partial_response : partial_response_cache_) + delegate_->OnPartialResponse(partial_response); + } + if (success) { DCHECK_NE(response_code, kResponseCodeInvalid); delegate_->OnCompleteResponse(response_code, raw_headers, "");
diff --git a/chromeos/services/assistant/chromium_http_connection.h b/chromeos/services/assistant/chromium_http_connection.h index 4344860..d0d06f7d 100644 --- a/chromeos/services/assistant/chromium_http_connection.h +++ b/chromeos/services/assistant/chromium_http_connection.h
@@ -9,6 +9,7 @@ #include <memory> #include <string> +#include <vector> #include "base/macros.h" #include "base/memory/ref_counted.h" @@ -122,6 +123,8 @@ std::string upload_content_type_; std::string chunked_upload_content_type_; bool handle_partial_response_ = false; + bool enable_header_response_ = false; + std::vector<std::string> partial_response_cache_; DISALLOW_COPY_AND_ASSIGN(ChromiumHttpConnection); };
diff --git a/chromeos/services/assistant/platform/audio_device_owner.cc b/chromeos/services/assistant/platform/audio_device_owner.cc new file mode 100644 index 0000000..114535a8 --- /dev/null +++ b/chromeos/services/assistant/platform/audio_device_owner.cc
@@ -0,0 +1,223 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chromeos/services/assistant/platform/audio_device_owner.h" + +#include <algorithm> +#include <utility> + +#include "media/audio/audio_device_description.h" +#include "media/base/limits.h" +#include "services/media_session/public/mojom/media_session.mojom.h" + +namespace chromeos { +namespace assistant { + +namespace { + +constexpr int kNumberOfBuffersPerSec = 10; + +int32_t GetBytesPerSample(const assistant_client::OutputStreamFormat& format) { + switch (format.encoding) { + case assistant_client::OutputStreamEncoding::STREAM_PCM_S16: + return 2; + case assistant_client::OutputStreamEncoding::STREAM_PCM_S32: + case assistant_client::OutputStreamEncoding::STREAM_PCM_F32: + return 4; + default: + break; + } + NOTREACHED(); + return 1; +} + +int32_t GetBytesPerFrame(const assistant_client::OutputStreamFormat& format) { + return GetBytesPerSample(format) * format.pcm_num_channels; +} + +void FillAudioFifoWithDataOfBufferFormat( + media::AudioBlockFifo* fifo, + const std::vector<uint8_t>& data, + const assistant_client::OutputStreamFormat& output_format, + int num_bytes) { + int bytes_per_frame = GetBytesPerFrame(output_format); + int bytes_per_sample = GetBytesPerSample(output_format); + int frames = num_bytes / bytes_per_frame; + fifo->Push(data.data(), frames, bytes_per_sample); +} + +int32_t GetBufferSizeInBytesFromBufferFormat( + const assistant_client::OutputStreamFormat& format) { + return GetBytesPerFrame(format) * format.pcm_sample_rate / + kNumberOfBuffersPerSec; +} + +media::AudioParameters GetAudioParametersFromBufferFormat( + const assistant_client::OutputStreamFormat& output_format) { + DCHECK(output_format.pcm_num_channels <= 2 && + output_format.pcm_num_channels > 0); + + return media::AudioParameters( + media::AudioParameters::AUDIO_PCM_LOW_LATENCY, + media::GuessChannelLayout(output_format.pcm_num_channels), + output_format.pcm_sample_rate, + output_format.pcm_sample_rate / kNumberOfBuffersPerSec); +} + +} // namespace + +AudioDeviceOwner::AudioDeviceOwner( + scoped_refptr<base::SequencedTaskRunner> task_runner, + scoped_refptr<base::SequencedTaskRunner> background_task_runner, + const std::string& device_id) + : main_task_runner_(task_runner), + background_task_runner_(background_task_runner), + device_id_(device_id) {} + +AudioDeviceOwner::~AudioDeviceOwner() { + DCHECK(background_task_runner_->RunsTasksInCurrentSequence()); +} + +void AudioDeviceOwner::StartOnMainThread( + assistant_client::AudioOutput::Delegate* delegate, + service_manager::Connector* connector, + const assistant_client::OutputStreamFormat& format) { + DCHECK(!output_device_); + DCHECK(main_task_runner_->RunsTasksInCurrentSequence()); + + delegate_ = delegate; + format_ = format; + // TODO(wutao): There is a bug LibAssistant sends wrong format. Do not run + // in this case. + if (format_.pcm_num_channels > + static_cast<int>(media::limits::kMaxChannels)) { + delegate_->OnEndOfStream(); + return; + } + + audio_param_ = GetAudioParametersFromBufferFormat(format_); + + // |audio_fifo_| contains 8x the number of frames to render. + audio_fifo_ = std::make_unique<media::AudioBlockFifo>( + format.pcm_num_channels, audio_param_.frames_per_buffer(), 8); + audio_data_.resize(GetBufferSizeInBytesFromBufferFormat(format_)); + + { + base::AutoLock lock(lock_); + ScheduleFillLocked(base::TimeTicks::Now()); + } + + // |connector| is null in unittest. + if (connector) { + // |AudioDeviceOwner| is destroyed on background thread. Thus, it's safe to + // use base::Unretained. + background_task_runner_->PostTask( + FROM_HERE, + base::BindOnce(&AudioDeviceOwner::StartDeviceOnBackgroundThread, + base::Unretained(this), connector->Clone())); + } +} + +void AudioDeviceOwner::StopOnBackgroundThread() { + DCHECK(background_task_runner_->RunsTasksInCurrentSequence()); + base::AutoLock lock(lock_); + output_device_.reset(); + if (delegate_) { + delegate_->OnStopped(); + delegate_ = nullptr; + } +} + +void AudioDeviceOwner::StartDeviceOnBackgroundThread( + std::unique_ptr<service_manager::Connector> connector) { + DCHECK(background_task_runner_->RunsTasksInCurrentSequence()); + output_device_ = std::make_unique<audio::OutputDevice>( + std::move(connector), audio_param_, this, device_id_); + output_device_->Play(); +} + +int AudioDeviceOwner::Render(base::TimeDelta delay, + base::TimeTicks delay_timestamp, + int prior_frames_skipped, + media::AudioBus* dest) { + base::AutoLock lock(lock_); + + if (!is_filling_ && audio_fifo_->GetAvailableFrames() <= 0) { + if (delegate_) + delegate_->OnEndOfStream(); + return 0; + } + if (audio_fifo_->GetAvailableFrames() <= 0) { + // Wait for the next round of filling. This should only happen at the + // very beginning. + return 0; + } + + int available_frames = audio_fifo_->GetAvailableFrames(); + if (available_frames < dest->frames()) { + // In our setting, dest->frames() == frames per block in |audio_fifo_|. + DCHECK_EQ(audio_fifo_->available_blocks(), 0); + + int frames_to_fill = audio_param_.frames_per_buffer() - available_frames; + + DCHECK_GE(frames_to_fill, 0); + + // Fill up to one block with zero data so that |audio_fifo_| has 1 block + // to consume. This avoids DCHECK in audio_fifo_->Consume() and also + // prevents garbage data being copied to |dest| in production. + audio_fifo_->PushSilence(frames_to_fill); + } + + audio_fifo_->Consume()->CopyTo(dest); + + ScheduleFillLocked(base::TimeTicks::Now() - delay); + return dest->frames(); +} + +void AudioDeviceOwner::OnRenderError() { + DVLOG(1) << "OnRenderError()"; + base::AutoLock lock(lock_); + if (delegate_) + delegate_->OnError(assistant_client::AudioOutput::Error::FATAL_ERROR); +} + +void AudioDeviceOwner::SetDelegate( + assistant_client::AudioOutput::Delegate* delegate) { + base::AutoLock lock(lock_); + delegate_ = delegate; +} + +void AudioDeviceOwner::ScheduleFillLocked(const base::TimeTicks& time) { + lock_.AssertAcquired(); + if (is_filling_) + return; + is_filling_ = true; + // FillBuffer will not be called after delegate_->OnEndOfStream, after which + // AudioDeviceOwner will be destroyed. Thus |this| is valid for capture + // here. + + if (!delegate_) + return; + + delegate_->FillBuffer( + audio_data_.data(), + std::min(static_cast<int>(audio_data_.size()), + GetBytesPerFrame(format_) * audio_fifo_->GetUnfilledFrames()), + time.since_origin().InMicroseconds(), + [this](int num) { this->BufferFillDone(num); }); +} + +void AudioDeviceOwner::BufferFillDone(int num_bytes) { + base::AutoLock lock(lock_); + is_filling_ = false; + if (num_bytes == 0) + return; + FillAudioFifoWithDataOfBufferFormat(audio_fifo_.get(), audio_data_, format_, + num_bytes); + if (audio_fifo_->GetUnfilledFrames() > 0) + ScheduleFillLocked(base::TimeTicks::Now()); +} + +} // namespace assistant +} // namespace chromeos
diff --git a/chromeos/services/assistant/platform/audio_device_owner.h b/chromeos/services/assistant/platform/audio_device_owner.h new file mode 100644 index 0000000..c169c51 --- /dev/null +++ b/chromeos/services/assistant/platform/audio_device_owner.h
@@ -0,0 +1,85 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROMEOS_SERVICES_ASSISTANT_PLATFORM_AUDIO_DEVICE_OWNER_H_ +#define CHROMEOS_SERVICES_ASSISTANT_PLATFORM_AUDIO_DEVICE_OWNER_H_ + +#include <memory> +#include <string> +#include <vector> + +#include "base/component_export.h" +#include "base/macros.h" +#include "libassistant/shared/public/platform_audio_output.h" +#include "media/base/audio_block_fifo.h" +#include "media/base/audio_parameters.h" +#include "media/base/audio_renderer_sink.h" +#include "services/audio/public/cpp/output_device.h" +#include "services/service_manager/public/cpp/connector.h" + +namespace chromeos { +namespace assistant { + +class COMPONENT_EXPORT(ASSISTANT_SERVICE) AudioDeviceOwner + : public media::AudioRendererSink::RenderCallback { + public: + AudioDeviceOwner( + scoped_refptr<base::SequencedTaskRunner> task_runner, + scoped_refptr<base::SequencedTaskRunner> background_task_runner, + const std::string& device_id); + ~AudioDeviceOwner() override; + + void StartOnMainThread(assistant_client::AudioOutput::Delegate* delegate, + service_manager::Connector* connector, + const assistant_client::OutputStreamFormat& format); + + void StopOnBackgroundThread(); + + // media::AudioRenderSink::RenderCallback overrides: + int Render(base::TimeDelta delay, + base::TimeTicks delay_timestamp, + int prior_frames_skipped, + media::AudioBus* dest) override; + + void OnRenderError() override; + + void SetDelegate(assistant_client::AudioOutput::Delegate* delegate); + + private: + void StartDeviceOnBackgroundThread( + std::unique_ptr<service_manager::Connector> connector); + + // Requests assistant to fill buffer with more data. + void ScheduleFillLocked(const base::TimeTicks& time); + + // Callback for assistant to notify that it completes the filling. + void BufferFillDone(int num_bytes); + + scoped_refptr<base::SequencedTaskRunner> main_task_runner_; + scoped_refptr<base::SequencedTaskRunner> background_task_runner_; + + base::Lock lock_; + std::unique_ptr<media::AudioBlockFifo> audio_fifo_; // guarded by lock_. + // Whether assistant is filling the buffer -- delegate_->FillBuffer is called + // and BufferFillDone() is not called yet. + // guarded by lock_. + bool is_filling_ = false; + + assistant_client::AudioOutput::Delegate* delegate_; + + // Audio output device id used for output. + std::string device_id_; + std::unique_ptr<audio::OutputDevice> output_device_; + // Stores audio frames generated by assistant. + std::vector<uint8_t> audio_data_; + assistant_client::OutputStreamFormat format_; + media::AudioParameters audio_param_; + + DISALLOW_COPY_AND_ASSIGN(AudioDeviceOwner); +}; + +} // namespace assistant +} // namespace chromeos + +#endif // CHROMEOS_SERVICES_ASSISTANT_PLATFORM_AUDIO_DEVICE_OWNER_H_
diff --git a/chromeos/services/assistant/platform/audio_input_impl.cc b/chromeos/services/assistant/platform/audio_input_impl.cc index 86fec80..88f10e5 100644 --- a/chromeos/services/assistant/platform/audio_input_impl.cc +++ b/chromeos/services/assistant/platform/audio_input_impl.cc
@@ -49,7 +49,9 @@ public: DspHotwordStateManager(scoped_refptr<base::SequencedTaskRunner> task_runner, AudioInputImpl* input) - : task_runner_(task_runner), input_(input), weak_factory_(this) { + : AudioInputImpl::HotwordStateManager(input), + task_runner_(task_runner), + weak_factory_(this) { DCHECK(task_runner_->RunsTasksInCurrentSequence()); } @@ -60,11 +62,11 @@ if (second_phase_timer_.IsRunning()) { DCHECK(stream_state_ == StreamState::HOTWORD); second_phase_timer_.Stop(); - stream_state_ = StreamState::NORMAL; } else { // Handles user click on mic button. input_->RecreateAudioInputStream(false /* use_dsp */); } + stream_state_ = StreamState::NORMAL; } // Runs on main thread. @@ -83,6 +85,11 @@ weak_factory_.GetWeakPtr())); } + void RecreateAudioInputStream() override { + DCHECK(task_runner_->RunsTasksInCurrentSequence()); + input_->RecreateAudioInputStream(stream_state_ == StreamState::HOTWORD); + } + // Runs on main thread. void OnCaptureDataArrivedMainThread() { DCHECK(task_runner_->RunsTasksInCurrentSequence()); @@ -108,7 +115,6 @@ StreamState stream_state_ = StreamState::HOTWORD; scoped_refptr<base::SequencedTaskRunner> task_runner_; base::OneShotTimer second_phase_timer_; - AudioInputImpl* input_; base::WeakPtrFactory<DspHotwordStateManager> weak_factory_; DISALLOW_COPY_AND_ASSIGN(DspHotwordStateManager); @@ -139,19 +145,25 @@ } // namespace -AudioInputImpl::AudioInputImpl(service_manager::Connector* connector) +AudioInputImpl::HotwordStateManager::HotwordStateManager( + AudioInputImpl* audio_input) + : input_(audio_input) {} + +void AudioInputImpl::HotwordStateManager::RecreateAudioInputStream() { + input_->RecreateAudioInputStream(/*use_dsp=*/false); +} + +AudioInputImpl::AudioInputImpl(service_manager::Connector* connector, + const std::string& device_id, + const std::string& hotword_device_id) : connector_(connector), task_runner_(base::SequencedTaskRunnerHandle::Get()), + device_id_(device_id), + hotword_device_id_(hotword_device_id), weak_factory_(this) { DETACH_FROM_SEQUENCE(observer_sequence_checker_); - if (features::IsDspHotwordEnabled()) { - state_manager_ = - std::make_unique<DspHotwordStateManager>(task_runner_, this); - } else { - state_manager_ = std::make_unique<HotwordStateManager>(); - } - + RecreateStateManager(); if (features::IsStereoAudioInputEnabled()) g_current_format = kFormatStereo; else @@ -163,6 +175,15 @@ StopRecording(); } +void AudioInputImpl::RecreateStateManager() { + if (IsHotwordAvailable()) { + state_manager_ = + std::make_unique<DspHotwordStateManager>(task_runner_, this); + } else { + state_manager_ = std::make_unique<HotwordStateManager>(this); + } +} + // Runs on audio service thread. void AudioInputImpl::Capture(const media::AudioBus* audio_source, int audio_delay_milliseconds, @@ -286,30 +307,55 @@ UpdateRecordingState(); } +void AudioInputImpl::SetDeviceId(const std::string& device_id) { + if (device_id_ == device_id) + return; + + device_id_ = device_id; + if (source_) + state_manager_->RecreateAudioInputStream(); +} + +void AudioInputImpl::SetHotwordDeviceId(const std::string& device_id) { + if (hotword_device_id_ == device_id) + return; + + hotword_device_id_ = device_id; + RecreateStateManager(); + if (source_) + state_manager_->RecreateAudioInputStream(); +} + void AudioInputImpl::RecreateAudioInputStream(bool use_dsp) { DCHECK(task_runner_->RunsTasksInCurrentSequence()); StopRecording(); - source_ = audio::CreateInputDevice( - connector_->Clone(), media::AudioDeviceDescription::kDefaultDeviceId); // AUDIO_PCM_LINEAR and AUDIO_PCM_LOW_LATENCY are the same on CRAS. auto param = media::AudioParameters( media::AudioParameters::AUDIO_PCM_LOW_LATENCY, GetChannelLayout(g_current_format), g_current_format.sample_rate, g_current_format.sample_rate / 10 /* buffer size for 100 ms */); - if (use_dsp) + std::string* device_id = &device_id_; + if (use_dsp && !hotword_device_id_.empty()) { param.set_effects(media::AudioParameters::PlatformEffectsMask::HOTWORD); + device_id = &hotword_device_id_; + } + source_ = audio::CreateInputDevice(connector_->Clone(), *device_id); source_->Initialize(param, this); source_->Start(); VLOG(1) << "Start recording"; } +bool AudioInputImpl::IsHotwordAvailable() { + return features::IsDspHotwordEnabled() && !hotword_device_id_.empty(); +} + void AudioInputImpl::StartRecording() { DCHECK(task_runner_->RunsTasksInCurrentSequence()); DCHECK(!source_); - RecreateAudioInputStream(features::IsDspHotwordEnabled()); + RecreateAudioInputStream(IsHotwordAvailable()); } void AudioInputImpl::StopRecording() {
diff --git a/chromeos/services/assistant/platform/audio_input_impl.h b/chromeos/services/assistant/platform/audio_input_impl.h index 0f71d874..ed70da3 100644 --- a/chromeos/services/assistant/platform/audio_input_impl.h +++ b/chromeos/services/assistant/platform/audio_input_impl.h
@@ -29,21 +29,29 @@ class AudioInputImpl : public assistant_client::AudioInput, public media::AudioCapturerSource::CaptureCallback { public: - explicit AudioInputImpl(service_manager::Connector* connector); + AudioInputImpl(service_manager::Connector* connector, + const std::string& device_id, + const std::string& hotword_device_id); ~AudioInputImpl() override; class HotwordStateManager { public: - HotwordStateManager() = default; + explicit HotwordStateManager(AudioInputImpl* audio_input_); virtual ~HotwordStateManager() = default; virtual void OnConversationTurnStarted() {} virtual void OnConversationTurnFinished() {} virtual void OnCaptureDataArrived() {} + virtual void RecreateAudioInputStream(); + + protected: + AudioInputImpl* input_; private: DISALLOW_COPY_AND_ASSIGN(HotwordStateManager); }; + void RecreateStateManager(); + // media::AudioCapturerSource::CaptureCallback overrides: void Capture(const media::AudioBus* audio_source, int audio_delay_milliseconds, @@ -68,8 +76,13 @@ // Called when hotword enabled status changed. void OnHotwordEnabled(bool enable); + void SetDeviceId(const std::string& device_id); + void SetHotwordDeviceId(const std::string& device_id); + void RecreateAudioInputStream(bool use_dsp); + bool IsHotwordAvailable(); + private: void StartRecording(); void StopRecording(); @@ -104,6 +117,11 @@ std::unique_ptr<HotwordStateManager> state_manager_; + // Audio input device which will be used for capture. + std::string device_id_; + // Hotword input device used for hardware based hotword detection. + std::string hotword_device_id_; + base::WeakPtrFactory<AudioInputImpl> weak_factory_; DISALLOW_COPY_AND_ASSIGN(AudioInputImpl); };
diff --git a/chromeos/services/assistant/platform/audio_input_provider_impl.cc b/chromeos/services/assistant/platform/audio_input_provider_impl.cc index dce1e7e..3c70135f 100644 --- a/chromeos/services/assistant/platform/audio_input_provider_impl.cc +++ b/chromeos/services/assistant/platform/audio_input_provider_impl.cc
@@ -8,8 +8,10 @@ namespace assistant { AudioInputProviderImpl::AudioInputProviderImpl( - service_manager::Connector* connector) - : audio_input_(connector) {} + service_manager::Connector* connector, + const std::string& input_device_id, + const std::string& hotword_device_id) + : audio_input_(connector, input_device_id, hotword_device_id) {} AudioInputProviderImpl::~AudioInputProviderImpl() = default; @@ -30,5 +32,13 @@ audio_input_.OnHotwordEnabled(enable); } +void AudioInputProviderImpl::SetDeviceId(const std::string& device_id) { + audio_input_.SetDeviceId(device_id); +} + +void AudioInputProviderImpl::SetHotwordDeviceId(const std::string& device_id) { + audio_input_.SetHotwordDeviceId(device_id); +} + } // namespace assistant } // namespace chromeos
diff --git a/chromeos/services/assistant/platform/audio_input_provider_impl.h b/chromeos/services/assistant/platform/audio_input_provider_impl.h index 9e211c58..bc978ab 100644 --- a/chromeos/services/assistant/platform/audio_input_provider_impl.h +++ b/chromeos/services/assistant/platform/audio_input_provider_impl.h
@@ -22,7 +22,9 @@ class AudioInputProviderImpl : public assistant_client::AudioInputProvider { public: - explicit AudioInputProviderImpl(service_manager::Connector* connector); + AudioInputProviderImpl(service_manager::Connector* connector, + const std::string& input_device_id, + const std::string& hotword_device_id); ~AudioInputProviderImpl() override; // assistant_client::AudioInputProvider overrides: @@ -35,6 +37,12 @@ // Called when hotword enabled status changed. void OnHotwordEnabled(bool enable); + // Setting the input device to use for audio capture. + void SetDeviceId(const std::string& device_id); + + // Setting the hotword input device with hardware based hotword detection. + void SetHotwordDeviceId(const std::string& device_id); + private: AudioInputImpl audio_input_;
diff --git a/chromeos/services/assistant/platform/audio_output_provider_impl.cc b/chromeos/services/assistant/platform/audio_output_provider_impl.cc index b59c1da9b..5fae1867 100644 --- a/chromeos/services/assistant/platform/audio_output_provider_impl.cc +++ b/chromeos/services/assistant/platform/audio_output_provider_impl.cc
@@ -14,9 +14,6 @@ #include "chromeos/services/assistant/public/mojom/assistant_audio_decoder.mojom.h" #include "chromeos/services/assistant/public/mojom/constants.mojom.h" #include "libassistant/shared/public/platform_audio_buffer.h" -#include "media/audio/audio_device_description.h" -#include "media/base/limits.h" -#include "services/media_session/public/mojom/media_session.mojom.h" #include "services/service_manager/public/cpp/connector.h" namespace chromeos { @@ -24,55 +21,6 @@ namespace { -constexpr int kNumberOfBuffersPerSec = 10; - -int32_t GetBytesPerSample(const assistant_client::OutputStreamFormat& format) { - switch (format.encoding) { - case assistant_client::OutputStreamEncoding::STREAM_PCM_S16: - return 2; - case assistant_client::OutputStreamEncoding::STREAM_PCM_S32: - case assistant_client::OutputStreamEncoding::STREAM_PCM_F32: - return 4; - default: - break; - } - NOTREACHED(); - return 1; -} - -int32_t GetBytesPerFrame(const assistant_client::OutputStreamFormat& format) { - return GetBytesPerSample(format) * format.pcm_num_channels; -} - -int32_t GetBufferSizeInBytesFromBufferFormat( - const assistant_client::OutputStreamFormat& format) { - return GetBytesPerFrame(format) * format.pcm_sample_rate / - kNumberOfBuffersPerSec; -} - -media::AudioParameters GetAudioParametersFromBufferFormat( - const assistant_client::OutputStreamFormat& output_format) { - DCHECK(output_format.pcm_num_channels <= 2 && - output_format.pcm_num_channels > 0); - - return media::AudioParameters( - media::AudioParameters::AUDIO_PCM_LOW_LATENCY, - media::GuessChannelLayout(output_format.pcm_num_channels), - output_format.pcm_sample_rate, - output_format.pcm_sample_rate / kNumberOfBuffersPerSec); -} - -void FillAudioFifoWithDataOfBufferFormat( - media::AudioBlockFifo* fifo, - const std::vector<uint8_t>& data, - const assistant_client::OutputStreamFormat& output_format, - int num_bytes) { - int bytes_per_frame = GetBytesPerFrame(output_format); - int bytes_per_sample = GetBytesPerSample(output_format); - int frames = num_bytes / bytes_per_frame; - fifo->Push(data.data(), frames, bytes_per_sample); -} - bool IsEncodedFormat(const assistant_client::OutputStreamFormat& format) { return format.encoding == assistant_client::OutputStreamEncoding::STREAM_MP3 || @@ -88,7 +36,8 @@ scoped_refptr<base::SequencedTaskRunner> background_task_runner, mojom::AssistantAudioDecoderFactory* audio_decoder_factory, assistant_client::OutputStreamType type, - assistant_client::OutputStreamFormat format) + assistant_client::OutputStreamFormat format, + const std::string& device_id) : connector_(connector), main_task_runner_(task_runner), background_thread_task_runner_(background_task_runner), @@ -97,9 +46,9 @@ format_(format), audio_stream_handler_( std::make_unique<AudioStreamHandler>(task_runner)), - device_owner_( - std::make_unique<AudioDeviceOwner>(task_runner, - background_task_runner)) {} + device_owner_(std::make_unique<AudioDeviceOwner>(task_runner, + background_task_runner, + device_id)) {} ~AudioOutputImpl() override { // This ensures that it will be executed after StartOnMainThread. @@ -169,106 +118,16 @@ } // namespace -VolumeControlImpl::VolumeControlImpl(service_manager::Connector* connector, - AssistantMediaSession* media_session) - : media_session_(media_session), - binding_(this), - main_task_runner_(base::SequencedTaskRunnerHandle::Get()), - weak_factory_(this) { - connector->BindInterface(ash::mojom::kServiceName, &volume_control_ptr_); - ash::mojom::VolumeObserverPtr observer; - binding_.Bind(mojo::MakeRequest(&observer)); - volume_control_ptr_->AddVolumeObserver(std::move(observer)); -} - -VolumeControlImpl::~VolumeControlImpl() = default; - -void VolumeControlImpl::SetAudioFocus( - assistant_client::OutputStreamType focused_stream) { - main_task_runner_->PostTask( - FROM_HERE, base::BindOnce(&VolumeControlImpl::SetAudioFocusOnMainThread, - weak_factory_.GetWeakPtr(), focused_stream)); -} - -float VolumeControlImpl::GetSystemVolume() { - return volume_ * 1.0 / 100.0; -} - -void VolumeControlImpl::SetSystemVolume(float new_volume, bool user_initiated) { - main_task_runner_->PostTask( - FROM_HERE, - base::BindOnce(&VolumeControlImpl::SetSystemVolumeOnMainThread, - weak_factory_.GetWeakPtr(), new_volume, user_initiated)); -} - -float VolumeControlImpl::GetAlarmVolume() { - // TODO(muyuanli): implement. - return 1.0f; -} - -void VolumeControlImpl::SetAlarmVolume(float new_volume, bool user_initiated) { - // TODO(muyuanli): implement. -} - -bool VolumeControlImpl::IsSystemMuted() { - return mute_; -} - -void VolumeControlImpl::SetSystemMuted(bool muted) { - main_task_runner_->PostTask( - FROM_HERE, base::BindOnce(&VolumeControlImpl::SetSystemMutedOnMainThread, - weak_factory_.GetWeakPtr(), muted)); -} - -void VolumeControlImpl::OnVolumeChanged(int volume) { - volume_ = volume; -} - -void VolumeControlImpl::OnMuteStateChanged(bool mute) { - mute_ = mute; -} - -void VolumeControlImpl::SetAudioFocusOnMainThread( - assistant_client::OutputStreamType focused_stream) { - DCHECK(main_task_runner_->RunsTasksInCurrentSequence()); - // TODO(wutao): Fix the libassistant behavior. - // Currently this is called with |STREAM_TTS| and |STREAM_ALARM| when - // requesting focus. When releasing focus it calls with |STREAM_MEDIA|. - // libassistant media code path does not request focus. - switch (focused_stream) { - case assistant_client::OutputStreamType::STREAM_ALARM: - media_session_->RequestAudioFocus( - media_session::mojom::AudioFocusType::kGainTransientMayDuck); - break; - case assistant_client::OutputStreamType::STREAM_TTS: - media_session_->RequestAudioFocus( - media_session::mojom::AudioFocusType::kGainTransient); - break; - case assistant_client::OutputStreamType::STREAM_MEDIA: - media_session_->AbandonAudioFocusIfNeeded(); - break; - } -} - -void VolumeControlImpl::SetSystemVolumeOnMainThread(float new_volume, - bool user_initiated) { - DCHECK(main_task_runner_->RunsTasksInCurrentSequence()); - volume_control_ptr_->SetVolume(new_volume * 100.0, user_initiated); -} - -void VolumeControlImpl::SetSystemMutedOnMainThread(bool muted) { - DCHECK(main_task_runner_->RunsTasksInCurrentSequence()); - volume_control_ptr_->SetMuted(muted); -} - AudioOutputProviderImpl::AudioOutputProviderImpl( service_manager::Connector* connector, AssistantMediaSession* media_session, - scoped_refptr<base::SequencedTaskRunner> background_task_runner) + scoped_refptr<base::SequencedTaskRunner> background_task_runner, + const std::string& device_id) : volume_control_impl_(connector, media_session), connector_(connector), main_task_runner_(base::SequencedTaskRunnerHandle::Get()), - background_task_runner_(background_task_runner) { + background_task_runner_(background_task_runner), + device_id_(device_id) { connector_->BindInterface(mojom::kAudioDecoderServiceName, mojo::MakeRequest(&audio_decoder_factory_ptr_)); audio_decoder_factory_ = audio_decoder_factory_ptr_.get(); @@ -283,7 +142,7 @@ // once assistant_client::AudioOutput::Delegate::OnStopped() is called. return new AudioOutputImpl(connector_, main_task_runner_, background_task_runner_, audio_decoder_factory_, - type, stream_format); + type, stream_format, device_id_); } std::vector<assistant_client::OutputStreamEncoding> @@ -316,156 +175,5 @@ // TODO(muyuanli): implement. } -AudioDeviceOwner::AudioDeviceOwner( - scoped_refptr<base::SequencedTaskRunner> task_runner, - scoped_refptr<base::SequencedTaskRunner> background_task_runner) - : main_task_runner_(task_runner), - background_task_runner_(background_task_runner) {} - -AudioDeviceOwner::~AudioDeviceOwner() { - DCHECK(background_task_runner_->RunsTasksInCurrentSequence()); -} - -void AudioDeviceOwner::StartOnMainThread( - assistant_client::AudioOutput::Delegate* delegate, - service_manager::Connector* connector, - const assistant_client::OutputStreamFormat& format) { - DCHECK(!output_device_); - DCHECK(main_task_runner_->RunsTasksInCurrentSequence()); - - delegate_ = delegate; - format_ = format; - // TODO(wutao): There is a bug LibAssistant sends wrong format. Do not run - // in this case. - if (format_.pcm_num_channels > - static_cast<int>(media::limits::kMaxChannels)) { - delegate_->OnEndOfStream(); - return; - } - - audio_param_ = GetAudioParametersFromBufferFormat(format_); - - // |audio_fifo_| contains 8x the number of frames to render. - audio_fifo_ = std::make_unique<media::AudioBlockFifo>( - format.pcm_num_channels, audio_param_.frames_per_buffer(), 8); - audio_data_.resize(GetBufferSizeInBytesFromBufferFormat(format_)); - - { - base::AutoLock lock(lock_); - ScheduleFillLocked(base::TimeTicks::Now()); - } - - // |connector| is null in unittest. - if (connector) { - // |AudioDeviceOwner| is destroyed on background thread. Thus, it's safe to - // use base::Unretained. - background_task_runner_->PostTask( - FROM_HERE, - base::BindOnce(&AudioDeviceOwner::StartDeviceOnBackgroundThread, - base::Unretained(this), connector->Clone())); - } -} - -void AudioDeviceOwner::StopOnBackgroundThread() { - DCHECK(background_task_runner_->RunsTasksInCurrentSequence()); - base::AutoLock lock(lock_); - output_device_.reset(); - if (delegate_) { - delegate_->OnStopped(); - delegate_ = nullptr; - } -} - -void AudioDeviceOwner::StartDeviceOnBackgroundThread( - std::unique_ptr<service_manager::Connector> connector) { - DCHECK(background_task_runner_->RunsTasksInCurrentSequence()); - output_device_ = std::make_unique<audio::OutputDevice>( - std::move(connector), audio_param_, this, - media::AudioDeviceDescription::kDefaultDeviceId); - output_device_->Play(); -} - -int AudioDeviceOwner::Render(base::TimeDelta delay, - base::TimeTicks delay_timestamp, - int prior_frames_skipped, - media::AudioBus* dest) { - base::AutoLock lock(lock_); - - if (!is_filling_ && audio_fifo_->GetAvailableFrames() <= 0) { - if (delegate_) - delegate_->OnEndOfStream(); - return 0; - } - if (audio_fifo_->GetAvailableFrames() <= 0) { - // Wait for the next round of filling. This should only happen at the - // very beginning. - return 0; - } - - int available_frames = audio_fifo_->GetAvailableFrames(); - if (available_frames < dest->frames()) { - // In our setting, dest->frames() == frames per block in |audio_fifo_|. - DCHECK_EQ(audio_fifo_->available_blocks(), 0); - - int frames_to_fill = audio_param_.frames_per_buffer() - available_frames; - - DCHECK_GE(frames_to_fill, 0); - - // Fill up to one block with zero data so that |audio_fifo_| has 1 block - // to consume. This avoids DCHECK in audio_fifo_->Consume() and also - // prevents garbage data being copied to |dest| in production. - audio_fifo_->PushSilence(frames_to_fill); - } - - audio_fifo_->Consume()->CopyTo(dest); - - ScheduleFillLocked(base::TimeTicks::Now() - delay); - return dest->frames(); -} - -void AudioDeviceOwner::OnRenderError() { - DVLOG(1) << "OnRenderError()"; - base::AutoLock lock(lock_); - if (delegate_) - delegate_->OnError(assistant_client::AudioOutput::Error::FATAL_ERROR); -} - -void AudioDeviceOwner::SetDelegate( - assistant_client::AudioOutput::Delegate* delegate) { - base::AutoLock lock(lock_); - delegate_ = delegate; -} - -void AudioDeviceOwner::ScheduleFillLocked(const base::TimeTicks& time) { - lock_.AssertAcquired(); - if (is_filling_) - return; - is_filling_ = true; - // FillBuffer will not be called after delegate_->OnEndOfStream, after which - // AudioDeviceOwner will be destroyed. Thus |this| is valid for capture - // here. - - if (!delegate_) - return; - - delegate_->FillBuffer( - audio_data_.data(), - std::min(static_cast<int>(audio_data_.size()), - GetBytesPerFrame(format_) * audio_fifo_->GetUnfilledFrames()), - time.since_origin().InMicroseconds(), - [this](int num) { this->BufferFillDone(num); }); -} - -void AudioDeviceOwner::BufferFillDone(int num_bytes) { - base::AutoLock lock(lock_); - is_filling_ = false; - if (num_bytes == 0) - return; - FillAudioFifoWithDataOfBufferFormat(audio_fifo_.get(), audio_data_, format_, - num_bytes); - if (audio_fifo_->GetUnfilledFrames() > 0) - ScheduleFillLocked(base::TimeTicks::Now()); -} - } // namespace assistant } // namespace chromeos
diff --git a/chromeos/services/assistant/platform/audio_output_provider_impl.h b/chromeos/services/assistant/platform/audio_output_provider_impl.h index 0d966b4..287e44b 100644 --- a/chromeos/services/assistant/platform/audio_output_provider_impl.h +++ b/chromeos/services/assistant/platform/audio_output_provider_impl.h
@@ -6,19 +6,17 @@ #define CHROMEOS_SERVICES_ASSISTANT_PLATFORM_AUDIO_OUTPUT_PROVIDER_IMPL_H_ #include <memory> +#include <string> #include <vector> -#include "ash/public/interfaces/assistant_volume_control.mojom.h" #include "base/component_export.h" #include "base/macros.h" #include "base/single_thread_task_runner.h" +#include "chromeos/services/assistant/platform/audio_device_owner.h" +#include "chromeos/services/assistant/platform/volume_control_impl.h" #include "chromeos/services/assistant/public/mojom/assistant_audio_decoder.mojom.h" #include "libassistant/shared/public/platform_audio_output.h" -#include "media/base/audio_block_fifo.h" -#include "media/base/audio_parameters.h" -#include "media/base/audio_renderer_sink.h" #include "mojo/public/cpp/bindings/binding.h" -#include "services/audio/public/cpp/output_device.h" namespace service_manager { class Connector; @@ -29,52 +27,13 @@ class AssistantMediaSession; -class VolumeControlImpl : public assistant_client::VolumeControl, - public ash::mojom::VolumeObserver { - public: - explicit VolumeControlImpl(service_manager::Connector* connector, - AssistantMediaSession* media_session); - ~VolumeControlImpl() override; - - // assistant_client::VolumeControl overrides: - void SetAudioFocus( - assistant_client::OutputStreamType focused_stream) override; - float GetSystemVolume() override; - void SetSystemVolume(float new_volume, bool user_initiated) override; - float GetAlarmVolume() override; - void SetAlarmVolume(float new_volume, bool user_initiated) override; - bool IsSystemMuted() override; - void SetSystemMuted(bool muted) override; - - // ash::mojom::VolumeObserver overrides: - void OnVolumeChanged(int volume) override; - void OnMuteStateChanged(bool mute) override; - - private: - void SetAudioFocusOnMainThread( - assistant_client::OutputStreamType focused_stream); - void SetSystemVolumeOnMainThread(float new_volume, bool user_initiated); - void SetSystemMutedOnMainThread(bool muted); - - AssistantMediaSession* media_session_; - ash::mojom::AssistantVolumeControlPtr volume_control_ptr_; - mojo::Binding<ash::mojom::VolumeObserver> binding_; - scoped_refptr<base::SequencedTaskRunner> main_task_runner_; - - int volume_ = 100; - bool mute_ = false; - - base::WeakPtrFactory<VolumeControlImpl> weak_factory_; - - DISALLOW_COPY_AND_ASSIGN(VolumeControlImpl); -}; - class AudioOutputProviderImpl : public assistant_client::AudioOutputProvider { public: - explicit AudioOutputProviderImpl( + AudioOutputProviderImpl( service_manager::Connector* connector, AssistantMediaSession* media_session, - scoped_refptr<base::SequencedTaskRunner> background_task_runner); + scoped_refptr<base::SequencedTaskRunner> background_task_runner, + const std::string& device_id); ~AudioOutputProviderImpl() override; // assistant_client::AudioOutputProvider overrides: @@ -101,64 +60,11 @@ scoped_refptr<base::SequencedTaskRunner> background_task_runner_; mojom::AssistantAudioDecoderFactoryPtr audio_decoder_factory_ptr_; mojom::AssistantAudioDecoderFactory* audio_decoder_factory_; + std::string device_id_; DISALLOW_COPY_AND_ASSIGN(AudioOutputProviderImpl); }; -class COMPONENT_EXPORT(ASSISTANT_SERVICE) AudioDeviceOwner - : public media::AudioRendererSink::RenderCallback { - public: - AudioDeviceOwner( - scoped_refptr<base::SequencedTaskRunner> task_runner, - scoped_refptr<base::SequencedTaskRunner> background_task_runner); - ~AudioDeviceOwner() override; - - void StartOnMainThread(assistant_client::AudioOutput::Delegate* delegate, - service_manager::Connector* connector, - const assistant_client::OutputStreamFormat& format); - - void StopOnBackgroundThread(); - - // media::AudioRenderSink::RenderCallback overrides: - int Render(base::TimeDelta delay, - base::TimeTicks delay_timestamp, - int prior_frames_skipped, - media::AudioBus* dest) override; - - void OnRenderError() override; - - void SetDelegate(assistant_client::AudioOutput::Delegate* delegate); - - private: - void StartDeviceOnBackgroundThread( - std::unique_ptr<service_manager::Connector> connector); - - // Requests assistant to fill buffer with more data. - void ScheduleFillLocked(const base::TimeTicks& time); - - // Callback for assistant to notify that it completes the filling. - void BufferFillDone(int num_bytes); - - scoped_refptr<base::SequencedTaskRunner> main_task_runner_; - scoped_refptr<base::SequencedTaskRunner> background_task_runner_; - - base::Lock lock_; - std::unique_ptr<media::AudioBlockFifo> audio_fifo_; // guarded by lock_. - // Whether assistant is filling the buffer -- delegate_->FillBuffer is called - // and BufferFillDone() is not called yet. - // guarded by lock_. - bool is_filling_ = false; - - assistant_client::AudioOutput::Delegate* delegate_; - std::unique_ptr<audio::OutputDevice> output_device_; - // Stores audio frames generated by assistant. - std::vector<uint8_t> audio_data_; - assistant_client::OutputStreamFormat format_; - media::AudioParameters audio_param_; - - DISALLOW_COPY_AND_ASSIGN(AudioDeviceOwner); -}; - } // namespace assistant } // namespace chromeos
diff --git a/chromeos/services/assistant/platform/volume_control_impl.cc b/chromeos/services/assistant/platform/volume_control_impl.cc new file mode 100644 index 0000000..e7727d82 --- /dev/null +++ b/chromeos/services/assistant/platform/volume_control_impl.cc
@@ -0,0 +1,108 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chromeos/services/assistant/platform/volume_control_impl.h" + +#include <utility> + +#include "ash/public/interfaces/constants.mojom.h" +#include "chromeos/services/assistant/media_session/assistant_media_session.h" + +namespace chromeos { +namespace assistant { + +VolumeControlImpl::VolumeControlImpl(service_manager::Connector* connector, + AssistantMediaSession* media_session) + : media_session_(media_session), + binding_(this), + main_task_runner_(base::SequencedTaskRunnerHandle::Get()), + weak_factory_(this) { + connector->BindInterface(ash::mojom::kServiceName, &volume_control_ptr_); + ash::mojom::VolumeObserverPtr observer; + binding_.Bind(mojo::MakeRequest(&observer)); + volume_control_ptr_->AddVolumeObserver(std::move(observer)); +} + +VolumeControlImpl::~VolumeControlImpl() = default; + +void VolumeControlImpl::SetAudioFocus( + assistant_client::OutputStreamType focused_stream) { + main_task_runner_->PostTask( + FROM_HERE, base::BindOnce(&VolumeControlImpl::SetAudioFocusOnMainThread, + weak_factory_.GetWeakPtr(), focused_stream)); +} + +float VolumeControlImpl::GetSystemVolume() { + return volume_ * 1.0 / 100.0; +} + +void VolumeControlImpl::SetSystemVolume(float new_volume, bool user_initiated) { + main_task_runner_->PostTask( + FROM_HERE, + base::BindOnce(&VolumeControlImpl::SetSystemVolumeOnMainThread, + weak_factory_.GetWeakPtr(), new_volume, user_initiated)); +} + +float VolumeControlImpl::GetAlarmVolume() { + // TODO(muyuanli): implement. + return 1.0f; +} + +void VolumeControlImpl::SetAlarmVolume(float new_volume, bool user_initiated) { + // TODO(muyuanli): implement. +} + +bool VolumeControlImpl::IsSystemMuted() { + return mute_; +} + +void VolumeControlImpl::SetSystemMuted(bool muted) { + main_task_runner_->PostTask( + FROM_HERE, base::BindOnce(&VolumeControlImpl::SetSystemMutedOnMainThread, + weak_factory_.GetWeakPtr(), muted)); +} + +void VolumeControlImpl::OnVolumeChanged(int volume) { + volume_ = volume; +} + +void VolumeControlImpl::OnMuteStateChanged(bool mute) { + mute_ = mute; +} + +void VolumeControlImpl::SetAudioFocusOnMainThread( + assistant_client::OutputStreamType focused_stream) { + DCHECK(main_task_runner_->RunsTasksInCurrentSequence()); + // TODO(wutao): Fix the libassistant behavior. + // Currently this is called with |STREAM_TTS| and |STREAM_ALARM| when + // requesting focus. When releasing focus it calls with |STREAM_MEDIA|. + // libassistant media code path does not request focus. + switch (focused_stream) { + case assistant_client::OutputStreamType::STREAM_ALARM: + media_session_->RequestAudioFocus( + media_session::mojom::AudioFocusType::kGainTransientMayDuck); + break; + case assistant_client::OutputStreamType::STREAM_TTS: + media_session_->RequestAudioFocus( + media_session::mojom::AudioFocusType::kGainTransient); + break; + case assistant_client::OutputStreamType::STREAM_MEDIA: + media_session_->AbandonAudioFocusIfNeeded(); + break; + } +} + +void VolumeControlImpl::SetSystemVolumeOnMainThread(float new_volume, + bool user_initiated) { + DCHECK(main_task_runner_->RunsTasksInCurrentSequence()); + volume_control_ptr_->SetVolume(new_volume * 100.0, user_initiated); +} + +void VolumeControlImpl::SetSystemMutedOnMainThread(bool muted) { + DCHECK(main_task_runner_->RunsTasksInCurrentSequence()); + volume_control_ptr_->SetMuted(muted); +} + +} // namespace assistant +} // namespace chromeos
diff --git a/chromeos/services/assistant/platform/volume_control_impl.h b/chromeos/services/assistant/platform/volume_control_impl.h new file mode 100644 index 0000000..dcd24a3e --- /dev/null +++ b/chromeos/services/assistant/platform/volume_control_impl.h
@@ -0,0 +1,62 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROMEOS_SERVICES_ASSISTANT_PLATFORM_VOLUME_CONTROL_IMPL_H_ +#define CHROMEOS_SERVICES_ASSISTANT_PLATFORM_VOLUME_CONTROL_IMPL_H_ + +#include "ash/public/interfaces/assistant_volume_control.mojom.h" +#include "base/macros.h" +#include "libassistant/shared/public/platform_audio_output.h" +#include "mojo/public/cpp/bindings/binding.h" +#include "services/service_manager/public/cpp/connector.h" + +namespace chromeos { +namespace assistant { + +class AssistantMediaSession; + +class VolumeControlImpl : public assistant_client::VolumeControl, + public ash::mojom::VolumeObserver { + public: + VolumeControlImpl(service_manager::Connector* connector, + AssistantMediaSession* media_session); + ~VolumeControlImpl() override; + + // assistant_client::VolumeControl overrides: + void SetAudioFocus( + assistant_client::OutputStreamType focused_stream) override; + float GetSystemVolume() override; + void SetSystemVolume(float new_volume, bool user_initiated) override; + float GetAlarmVolume() override; + void SetAlarmVolume(float new_volume, bool user_initiated) override; + bool IsSystemMuted() override; + void SetSystemMuted(bool muted) override; + + // ash::mojom::VolumeObserver overrides: + void OnVolumeChanged(int volume) override; + void OnMuteStateChanged(bool mute) override; + + private: + void SetAudioFocusOnMainThread( + assistant_client::OutputStreamType focused_stream); + void SetSystemVolumeOnMainThread(float new_volume, bool user_initiated); + void SetSystemMutedOnMainThread(bool muted); + + AssistantMediaSession* media_session_; + ash::mojom::AssistantVolumeControlPtr volume_control_ptr_; + mojo::Binding<ash::mojom::VolumeObserver> binding_; + scoped_refptr<base::SequencedTaskRunner> main_task_runner_; + + int volume_ = 100; + bool mute_ = false; + + base::WeakPtrFactory<VolumeControlImpl> weak_factory_; + + DISALLOW_COPY_AND_ASSIGN(VolumeControlImpl); +}; + +} // namespace assistant +} // namespace chromeos + +#endif // CHROMEOS_SERVICES_ASSISTANT_PLATFORM_VOLUME_CONTROL_IMPL_H_
diff --git a/chromeos/services/assistant/platform_api_impl.cc b/chromeos/services/assistant/platform_api_impl.cc index 7ea06ad..d64d8f83 100644 --- a/chromeos/services/assistant/platform_api_impl.cc +++ b/chromeos/services/assistant/platform_api_impl.cc
@@ -8,6 +8,7 @@ #include <utility> #include <vector> +#include "base/system/sys_info.h" #include "chromeos/services/assistant/media_session/assistant_media_session.h" #include "chromeos/services/assistant/platform/power_manager_provider_impl.h" #include "chromeos/services/assistant/public/features.h" @@ -15,6 +16,7 @@ #include "libassistant/shared/public/assistant_export.h" #include "libassistant/shared/public/platform_api.h" #include "libassistant/shared/public/platform_factory.h" +#include "media/audio/audio_device_description.h" using assistant_client::AudioInputProvider; using assistant_client::AudioOutputProvider; @@ -81,8 +83,13 @@ scoped_refptr<base::SequencedTaskRunner> main_thread_task_runner, scoped_refptr<base::SingleThreadTaskRunner> background_task_runner, network::NetworkConnectionTracker* network_connection_tracker) - : audio_input_provider_(connector), - audio_output_provider_(connector, media_session, background_task_runner), + : audio_input_provider_(connector, + media::AudioDeviceDescription::kDefaultDeviceId, + /*hotword_device_id=*/std::string()), + audio_output_provider_(connector, + media_session, + background_task_runner, + media::AudioDeviceDescription::kDefaultDeviceId), network_provider_(network_connection_tracker) { // Only enable native power features if they are supported by the UI. std::unique_ptr<PowerManagerProviderImpl> provider; @@ -92,9 +99,14 @@ } system_provider_ = std::make_unique<SystemProviderImpl>( std::move(provider), std::move(battery_monitor)); + + chromeos::CrasAudioHandler::Get()->AddAudioObserver(this); + OnAudioNodesChanged(); } -PlatformApiImpl::~PlatformApiImpl() = default; +PlatformApiImpl::~PlatformApiImpl() { + chromeos::CrasAudioHandler::Get()->RemoveAudioObserver(this); +} AudioInputProviderImpl& PlatformApiImpl::GetAudioInputProvider() { return audio_input_provider_; @@ -120,6 +132,45 @@ return *system_provider_; } +void PlatformApiImpl::OnAudioNodesChanged() { + if (!base::SysInfo::IsRunningOnChromeOS()) + return; + auto* cras = chromeos::CrasAudioHandler::Get(); + + chromeos::AudioDeviceList devices; + cras->GetAudioDevices(&devices); + + const chromeos::AudioDevice* input_device = nullptr; + const chromeos::AudioDevice* hotword_device = nullptr; + + for (const chromeos::AudioDevice& device : devices) { + if (!device.is_input) + continue; + + switch (device.type) { + case chromeos::AUDIO_TYPE_USB: + case chromeos::AUDIO_TYPE_HEADPHONE: + case chromeos::AUDIO_TYPE_INTERNAL_MIC: + if (!input_device || input_device->priority < device.priority) + input_device = &device; + break; + case chromeos::AUDIO_TYPE_HOTWORD: + if (!hotword_device || hotword_device->priority < device.priority) + hotword_device = &device; + break; + default: + // ignore other devices + break; + } + } + if (input_device) + audio_input_provider_.SetDeviceId(base::NumberToString(input_device->id)); + if (hotword_device) { + audio_input_provider_.SetHotwordDeviceId( + base::NumberToString(hotword_device->id)); + } +} + void PlatformApiImpl::SetMicState(bool mic_open) { audio_input_provider_.SetMicState(mic_open); }
diff --git a/chromeos/services/assistant/platform_api_impl.h b/chromeos/services/assistant/platform_api_impl.h index 5fb3589..1937b3cf 100644 --- a/chromeos/services/assistant/platform_api_impl.h +++ b/chromeos/services/assistant/platform_api_impl.h
@@ -10,6 +10,7 @@ #include <utility> #include <vector> +#include "chromeos/audio/cras_audio_handler.h" #include "chromeos/services/assistant/platform/audio_input_provider_impl.h" #include "chromeos/services/assistant/platform/audio_output_provider_impl.h" #include "chromeos/services/assistant/platform/file_provider_impl.h" @@ -30,7 +31,8 @@ class AssistantMediaSession; // Platform API required by the voice assistant. -class PlatformApiImpl : public assistant_client::PlatformApi { +class PlatformApiImpl : public assistant_client::PlatformApi, + chromeos::CrasAudioHandler::AudioObserver { public: PlatformApiImpl( service_manager::Connector* connector, @@ -49,6 +51,9 @@ assistant_client::NetworkProvider& GetNetworkProvider() override; assistant_client::SystemProvider& GetSystemProvider() override; + // chromeos::CrasAudioHandler::AudioObserver overrides + void OnAudioNodesChanged() override; + // Called when the mic state associated with the interaction is changed. void SetMicState(bool mic_open);
diff --git a/chromeos/services/device_sync/cryptauth_enrollment_result.cc b/chromeos/services/device_sync/cryptauth_enrollment_result.cc index f05773c..dfcc7f9f 100644 --- a/chromeos/services/device_sync/cryptauth_enrollment_result.cc +++ b/chromeos/services/device_sync/cryptauth_enrollment_result.cc
@@ -122,15 +122,15 @@ stream << "[Error: Cannot create symmetric key; missing server " << "Diffie-Hellman key]"; break; + case ResultCode::kErrorKeyProofComputationFailed: + stream << "[Error: Failed to compute valid key proof]"; + break; case ResultCode::kErrorTimeoutWaitingForSyncKeysResponse: stream << "[Error: Timeout waiting for SyncKeys response]"; break; case ResultCode::kErrorTimeoutWaitingForKeyCreation: stream << "[Error: Timeout waiting for key creation]"; break; - case ResultCode::kErrorTimeoutWaitingForKeyProofComputation: - stream << "[Error: Timeout waiting for key proof computation]"; - break; case ResultCode::kErrorTimeoutWaitingForEnrollKeysResponse: stream << "[Error: Timeout waiting for EnrollKeys response]"; break;
diff --git a/chromeos/services/device_sync/cryptauth_enrollment_result.h b/chromeos/services/device_sync/cryptauth_enrollment_result.h index 83b0909..f093af12 100644 --- a/chromeos/services/device_sync/cryptauth_enrollment_result.h +++ b/chromeos/services/device_sync/cryptauth_enrollment_result.h
@@ -81,13 +81,13 @@ kErrorKeyCreationKeyTypeNotSupported, // Cannot create a symmetric key without the server's Diffie-Hellman key. kErrorSymmetricKeyCreationMissingServerDiffieHellman, + // Failed to compute at least one key proof. + kErrorKeyProofComputationFailed, // The enroller timed out waiting for response from the SyncKeys API call. kErrorTimeoutWaitingForSyncKeysResponse, // The enroller timed out waiting for new keys to be created. kErrorTimeoutWaitingForKeyCreation, // The enroller timed out waiting for key proofs to be computed. - kErrorTimeoutWaitingForKeyProofComputation, - // The enroller timed out waiting for response from the EnrollKeys API call. kErrorTimeoutWaitingForEnrollKeysResponse, // Failed to register local device with GCM. This registration is required // in order for CryptAuth to send GCM messages to the local device,
diff --git a/chromeos/services/device_sync/cryptauth_key_proof_computer.h b/chromeos/services/device_sync/cryptauth_key_proof_computer.h index 48008ff2..456570a0e 100644 --- a/chromeos/services/device_sync/cryptauth_key_proof_computer.h +++ b/chromeos/services/device_sync/cryptauth_key_proof_computer.h
@@ -6,45 +6,39 @@ #define CHROMEOS_SERVICES_DEVICE_SYNC_CRYPTAUTH_KEY_PROOF_COMPUTER_H_ #include <string> -#include <utility> -#include <vector> -#include "base/callback.h" #include "base/macros.h" -#include "chromeos/services/device_sync/cryptauth_key.h" +#include "base/optional.h" namespace chromeos { namespace device_sync { -// The lone method ComputeKeyProofs() takes a list of key-payload pairs and -// returns a list of key proof strings, ordered consistent with the -// input list. The key proofs are used by CryptAuth to verify that the client -// has the appropriate key material. +class CryptAuthKey; + +// The lone method ComputeKeyProof() takes a CryptAuthKey, a payload, and salt +// and returns the key proof as a string. The key proofs are used by CryptAuth +// to verify that the client has the appropriate key material. // -// The CryptAuth v2 Enrollment protocol requires the following key proof -// formats: -// - Symmetric keys: The HMAC-SHA256 of the payload, using a key derived from -// the symmetric key. Specifically, -// HMAC(HKDF(|key|, salt="CryptAuth Key Proof", info=|key_handle|), -// |payload|) +// The CryptAuth v2 Enrollment protocol requires the following key proofs: // -// - Asymmetric keys: A signed, unencrypted, and serialized SecureMessage -// proto, with the following parameters: -// - signature_scheme = ECDSA_P256_SHA256, -// - encryption_scheme = NONE, -// - verification_key_id = |key_handle|, -// - body = |payload|, -// signed with the private key material. +// Symmetric keys: The HMAC-SHA256 of the payload, using a key derived from +// the input symmetric key. Schematically, // -// The protocol also demands that the |random_session_id|, sent by the CryptAuth -// server via the SyncKeysResponse, be used as the payload for key proofs. In -// the future, key crossproofs might be employed, where the payload will -// consist of other key proofs. +// HMAC(HKDF(|symmetric_key|, |salt|, info=|key_handle|), |payload|) +// +// Asymmetric keys: A DER-encoded ECDSA signature (RFC 3279) of the +// concatenation of the salt and payload strings. +// Schematically, +// +// Sign(|private_key|, |salt| + |payload|) +// +// The CryptAuth v2 Enrollment protocol states that the +// SyncKeysResponse::random_session_id, sent by the CryptAuth server, be used as +// the payload for key proofs. In the future, key crossproofs might be employed, +// where the payload will consist of other key proofs. // // Requirements: -// - An instance of this class should only be used once. -// - The input list, |key_payload_pairs|, cannot be empty. // - Currently, the only supported key types are RAW128 and RAW256 for // symmetric keys and P256 for asymmetric keys. class CryptAuthKeyProofComputer { @@ -52,12 +46,11 @@ CryptAuthKeyProofComputer() = default; virtual ~CryptAuthKeyProofComputer() = default; - using ComputeKeyProofsCallback = - base::OnceCallback<void(const std::vector<std::string>& /* key_proofs*/)>; - virtual void ComputeKeyProofs( - const std::vector<std::pair<CryptAuthKey, std::string>>& - key_payload_pairs, - ComputeKeyProofsCallback compute_key_proofs_callback) = 0; + // Returns null if key proof computation failed. + virtual base::Optional<std::string> ComputeKeyProof( + const CryptAuthKey& key, + const std::string& payload, + const std::string& salt) = 0; DISALLOW_COPY_AND_ASSIGN(CryptAuthKeyProofComputer); };
diff --git a/chromeos/services/device_sync/cryptauth_key_proof_computer_impl.cc b/chromeos/services/device_sync/cryptauth_key_proof_computer_impl.cc index 296e867..275a9219 100644 --- a/chromeos/services/device_sync/cryptauth_key_proof_computer_impl.cc +++ b/chromeos/services/device_sync/cryptauth_key_proof_computer_impl.cc
@@ -4,18 +4,15 @@ #include "chromeos/services/device_sync/cryptauth_key_proof_computer_impl.h" -#include <memory> -#include <string> -#include <utility> #include <vector> -#include "base/bind.h" #include "base/memory/ptr_util.h" #include "base/no_destructor.h" -#include "chromeos/components/multidevice/secure_message_delegate.h" -#include "chromeos/components/multidevice/secure_message_delegate_impl.h" +#include "chromeos/components/multidevice/logging/logging.h" #include "chromeos/services/device_sync/cryptauth_key.h" #include "chromeos/services/device_sync/proto/cryptauth_common.pb.h" +#include "crypto/ec_private_key.h" +#include "crypto/ec_signature_creator.h" #include "crypto/hkdf.h" #include "crypto/hmac.h" @@ -25,10 +22,6 @@ namespace { -// The salt used for HKDF in symmetric key proofs. This value is part of the -// CryptAuth v2 Enrollment specifications. -const char kSymmetricKeyProofSalt[] = "CryptAuth Key Proof"; - size_t NumBytesForSymmetricKeyType(cryptauthv2::KeyType key_type) { switch (key_type) { case (cryptauthv2::KeyType::RAW128): @@ -46,6 +39,14 @@ key.type() == cryptauthv2::KeyType::P256; } +std::string ByteVectorToString(const std::vector<uint8_t>& byte_array) { + return std::string(byte_array.begin(), byte_array.end()); +} + +std::vector<uint8_t> StringToByteVector(const std::string& str) { + return std::vector<uint8_t>(str.begin(), str.end()); +} + } // namespace // static @@ -75,82 +76,86 @@ return base::WrapUnique(new CryptAuthKeyProofComputerImpl()); } -CryptAuthKeyProofComputerImpl::CryptAuthKeyProofComputerImpl() - : secure_message_delegate_( - multidevice::SecureMessageDelegateImpl::Factory::NewInstance()) {} +CryptAuthKeyProofComputerImpl::CryptAuthKeyProofComputerImpl() = default; CryptAuthKeyProofComputerImpl::~CryptAuthKeyProofComputerImpl() = default; -void CryptAuthKeyProofComputerImpl::ComputeKeyProofs( - const std::vector<std::pair<CryptAuthKey, std::string>>& key_payload_pairs, - ComputeKeyProofsCallback compute_key_proofs_callback) { - DCHECK(!key_payload_pairs.empty()); +base::Optional<std::string> CryptAuthKeyProofComputerImpl::ComputeKeyProof( + const CryptAuthKey& key, + const std::string& payload, + const std::string& salt) { + if (key.IsSymmetricKey()) + return ComputeSymmetricKeyProof(key, payload, salt); - // Fail if ComputeKeyProofs() has already been called. - DCHECK(num_key_proofs_to_compute_ == 0 && key_payload_pairs_.empty() && - output_key_proofs_.empty() && !compute_key_proofs_callback_); - - num_key_proofs_to_compute_ = key_payload_pairs.size(); - key_payload_pairs_ = key_payload_pairs; - output_key_proofs_.resize(num_key_proofs_to_compute_); - compute_key_proofs_callback_ = std::move(compute_key_proofs_callback); - - for (size_t i = 0; i < key_payload_pairs_.size(); ++i) { - if (key_payload_pairs_[i].first.IsSymmetricKey()) { - ComputeSymmetricKeyProof(i, key_payload_pairs_[i].first, - key_payload_pairs_[i].second); - } else { - DCHECK(IsValidAsymmetricKey(key_payload_pairs_[i].first)); - ComputeAsymmetricKeyProof(i, key_payload_pairs_[i].first, - key_payload_pairs_[i].second); - } - } + return ComputeAsymmetricKeyProof(key, payload, salt); } -void CryptAuthKeyProofComputerImpl::ComputeSymmetricKeyProof( - const size_t index, +base::Optional<std::string> +CryptAuthKeyProofComputerImpl::ComputeSymmetricKeyProof( const CryptAuthKey& symmetric_key, - const std::string& payload) { - std::string derived_symmetric_key_material = - crypto::HkdfSha256(symmetric_key.symmetric_key(), kSymmetricKeyProofSalt, - symmetric_key.handle(), - NumBytesForSymmetricKeyType(symmetric_key.type())); + const std::string& payload, + const std::string& salt) { + std::string derived_symmetric_key_material = crypto::HkdfSha256( + symmetric_key.symmetric_key(), salt, symmetric_key.handle(), + NumBytesForSymmetricKeyType(symmetric_key.type())); crypto::HMAC hmac(crypto::HMAC::HashAlgorithm::SHA256); std::vector<unsigned char> signed_payload(hmac.DigestLength()); bool success = hmac.Init(derived_symmetric_key_material) && hmac.Sign(payload, signed_payload.data(), signed_payload.size()); - DCHECK(success); - OnKeyProofComputed(index, - std::string(signed_payload.begin(), signed_payload.end())); + if (!success) { + PA_LOG(ERROR) << "Failed to compute symmetric key proof for key handle " + << symmetric_key.handle(); + return base::nullopt; + } + + return std::string(signed_payload.begin(), signed_payload.end()); } -void CryptAuthKeyProofComputerImpl::ComputeAsymmetricKeyProof( - const size_t index, +base::Optional<std::string> +CryptAuthKeyProofComputerImpl::ComputeAsymmetricKeyProof( const CryptAuthKey& asymmetric_key, - const std::string& payload) { - multidevice::SecureMessageDelegate::CreateOptions options; - options.encryption_scheme = securemessage::EncScheme::NONE; - options.signature_scheme = securemessage::SigScheme::ECDSA_P256_SHA256; - options.verification_key_id = asymmetric_key.handle(); + const std::string& payload, + const std::string& salt) { + if (!IsValidAsymmetricKey(asymmetric_key)) { + PA_LOG(ERROR) << "Failed to compute asymmetric key proof for key handle " + << asymmetric_key.handle() + << ". Invalid key type: " << asymmetric_key.type(); + return base::nullopt; + } - secure_message_delegate_->CreateSecureMessage( - payload, asymmetric_key.private_key(), options, - base::Bind(&CryptAuthKeyProofComputerImpl::OnKeyProofComputed, - base::Unretained(this), index)); -} + std::unique_ptr<crypto::ECPrivateKey> ec_private_key = + crypto::ECPrivateKey::CreateFromPrivateKeyInfo( + StringToByteVector(asymmetric_key.private_key())); + if (!ec_private_key) { + PA_LOG(ERROR) << "Failed to compute asymmetric key proof for key handle " + << asymmetric_key.handle() << ". " + << "Invalid private key material; expect DER-encoded PKCS #8 " + << "PrivateKeyInfo format (RFC 5208)."; + return base::nullopt; + } -void CryptAuthKeyProofComputerImpl::OnKeyProofComputed( - const size_t index, - const std::string& key_proof) { - DCHECK(index < output_key_proofs_.size()); - output_key_proofs_[index] = key_proof; + std::unique_ptr<crypto::ECSignatureCreator> ec_signature_creator = + crypto::ECSignatureCreator::Create(ec_private_key.get()); + if (!ec_signature_creator) { + PA_LOG(ERROR) << "Failed to compute asymmetric key proof for key handle " + << asymmetric_key.handle(); + return base::nullopt; + } - --num_key_proofs_to_compute_; - if (!num_key_proofs_to_compute_) - std::move(compute_key_proofs_callback_).Run(output_key_proofs_); + std::string to_sign = salt + payload; + std::vector<uint8_t> key_proof; + bool success = ec_signature_creator->Sign( + StringToByteVector(salt + payload).data(), to_sign.size(), &key_proof); + if (!success) { + PA_LOG(ERROR) << "Failed to compute asymmetric key proof for key handle " + << asymmetric_key.handle(); + return base::nullopt; + } + + return ByteVectorToString(key_proof); } } // namespace device_sync
diff --git a/chromeos/services/device_sync/cryptauth_key_proof_computer_impl.h b/chromeos/services/device_sync/cryptauth_key_proof_computer_impl.h index fa84495..710b0f62 100644 --- a/chromeos/services/device_sync/cryptauth_key_proof_computer_impl.h +++ b/chromeos/services/device_sync/cryptauth_key_proof_computer_impl.h
@@ -5,26 +5,19 @@ #ifndef CHROMEOS_SERVICES_DEVICE_SYNC_CRYPTAUTH_KEY_PROOF_COMPUTER_IMPL_H_ #define CHROMEOS_SERVICES_DEVICE_SYNC_CRYPTAUTH_KEY_PROOF_COMPUTER_IMPL_H_ -#include "chromeos/services/device_sync/cryptauth_key_proof_computer.h" - #include <memory> #include <string> -#include <utility> -#include <vector> -#include "base/callback.h" #include "base/macros.h" -#include "chromeos/services/device_sync/cryptauth_key.h" -#include "chromeos/services/device_sync/proto/cryptauth_common.pb.h" +#include "base/optional.h" +#include "chromeos/services/device_sync/cryptauth_key_proof_computer.h" namespace chromeos { -namespace multidevice { -class SecureMessageDelegate; -} // namespace multidevice - namespace device_sync { +class CryptAuthKey; + class CryptAuthKeyProofComputerImpl : public CryptAuthKeyProofComputer { public: class Factory { @@ -41,29 +34,21 @@ ~CryptAuthKeyProofComputerImpl() override; // CryptAuthKeyProofComputer: - void ComputeKeyProofs( - const std::vector<std::pair<CryptAuthKey, std::string>>& - key_payload_pairs, - ComputeKeyProofsCallback compute_key_proofs_callback) override; + base::Optional<std::string> ComputeKeyProof(const CryptAuthKey& key, + const std::string& payload, + const std::string& salt) override; private: CryptAuthKeyProofComputerImpl(); - void ComputeSymmetricKeyProof(const size_t index, - const CryptAuthKey& symmetric_key, - const std::string& payload); - void ComputeAsymmetricKeyProof(const size_t index, - const CryptAuthKey& asymmetric_key, - const std::string& payload); - void OnKeyProofComputed(const size_t index, - const std::string& single_key_proof); - - size_t num_key_proofs_to_compute_ = 0; - std::vector<std::pair<CryptAuthKey, std::string>> key_payload_pairs_; - std::vector<std::string> output_key_proofs_; - ComputeKeyProofsCallback compute_key_proofs_callback_; - - std::unique_ptr<multidevice::SecureMessageDelegate> secure_message_delegate_; + base::Optional<std::string> ComputeSymmetricKeyProof( + const CryptAuthKey& symmetric_key, + const std::string& payload, + const std::string& salt); + base::Optional<std::string> ComputeAsymmetricKeyProof( + const CryptAuthKey& asymmetric_key, + const std::string& payload, + const std::string& salt); DISALLOW_COPY_AND_ASSIGN(CryptAuthKeyProofComputerImpl); };
diff --git a/chromeos/services/device_sync/cryptauth_key_proof_computer_impl_unittest.cc b/chromeos/services/device_sync/cryptauth_key_proof_computer_impl_unittest.cc index 246ddd1..02519a6 100644 --- a/chromeos/services/device_sync/cryptauth_key_proof_computer_impl_unittest.cc +++ b/chromeos/services/device_sync/cryptauth_key_proof_computer_impl_unittest.cc
@@ -2,22 +2,20 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chromeos/services/device_sync/cryptauth_key_proof_computer_impl.h" - #include <memory> #include <string> -#include <utility> #include <vector> -#include "base/bind.h" #include "base/macros.h" -#include "chromeos/components/multidevice/fake_secure_message_delegate.h" -#include "chromeos/components/multidevice/secure_message_delegate_impl.h" +#include "base/optional.h" #include "chromeos/services/device_sync/cryptauth_key.h" #include "chromeos/services/device_sync/cryptauth_key_proof_computer.h" +#include "chromeos/services/device_sync/cryptauth_key_proof_computer_impl.h" #include "chromeos/services/device_sync/proto/cryptauth_common.pb.h" -#include "crypto/hkdf.h" +#include "crypto/ec_private_key.h" +#include "crypto/ec_signature_creator.h" #include "crypto/hmac.h" +#include "crypto/signature_verifier.h" #include "testing/gtest/include/gtest/gtest.h" namespace chromeos { @@ -25,151 +23,157 @@ namespace device_sync { namespace { +// Sample P-256 public and private keys from RFC 6979 A.2.5 in the respective +// ASN.1 formats: SubjectPublicKeyInfo (RFC 5280) and PKCS #8 PrivateKeyInfo +// (RFC 5208). Note: SecureMessage returns private keys (but not public keys) in +// this formatting. +const std::vector<uint8_t> kTestPublicKeyBytes = { + 0x30, 0x59, + // Begin AlgorithmIdentifier: ecPublicKey, prime256v1 + 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, + 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, + // End AlgorithmIdentifier + 0x03, 0x42, 0x00, 0x04, + // Public key bytes (Ux): + 0x60, 0xfe, 0xd4, 0xba, 0x25, 0x5a, 0x9d, 0x31, 0xc9, 0x61, 0xeb, 0x74, + 0xc6, 0x35, 0x6d, 0x68, 0xc0, 0x49, 0xb8, 0x92, 0x3b, 0x61, 0xfa, 0x6c, + 0xe6, 0x69, 0x62, 0x2e, 0x60, 0xf2, 0x9f, 0xb6, + // Public key bytes (Uy): + 0x79, 0x03, 0xfe, 0x10, 0x08, 0xb8, 0xbc, 0x99, 0xa4, 0x1a, 0xe9, 0xe9, + 0x56, 0x28, 0xbc, 0x64, 0xf2, 0xf1, 0xb2, 0x0c, 0x2d, 0x7e, 0x9f, 0x51, + 0x77, 0xa3, 0xc2, 0x94, 0xd4, 0x46, 0x22, 0x99}; +const std::vector<uint8_t> kTestPrivateKeyBytes = { + 0x30, 0x81, 0x87, 0x02, 0x01, 0x00, + // Begin AlgorithmIdentifier: ecPublicKey, prime256v1 + 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, + 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, + // End AlgorithmIdentifier + 0x04, 0x6d, 0x30, 0x6b, 0x02, 0x01, 0x01, 0x04, 0x20, + // Begin private key bytes + 0xc9, 0xaf, 0xa9, 0xd8, 0x45, 0xba, 0x75, 0x16, 0x6b, 0x5c, 0x21, 0x57, + 0x67, 0xb1, 0xd6, 0x93, 0x4e, 0x50, 0xc3, 0xdb, 0x36, 0xe8, 0x9b, 0x12, + 0x7b, 0x8a, 0x62, 0x2b, 0x12, 0x0f, 0x67, 0x21, + // End private key bytes + 0xa1, 0x44, 0x03, 0x42, 0x00, 0x04, + // Public key: + 0x60, 0xfe, 0xd4, 0xba, 0x25, 0x5a, 0x9d, 0x31, 0xc9, 0x61, 0xeb, 0x74, + 0xc6, 0x35, 0x6d, 0x68, 0xc0, 0x49, 0xb8, 0x92, 0x3b, 0x61, 0xfa, 0x6c, + 0xe6, 0x69, 0x62, 0x2e, 0x60, 0xf2, 0x9f, 0xb6, 0x79, 0x03, 0xfe, 0x10, + 0x08, 0xb8, 0xbc, 0x99, 0xa4, 0x1a, 0xe9, 0xe9, 0x56, 0x28, 0xbc, 0x64, + 0xf2, 0xf1, 0xb2, 0x0c, 0x2d, 0x7e, 0x9f, 0x51, 0x77, 0xa3, 0xc2, 0x94, + 0xd4, 0x46, 0x22, 0x99}; +const std::string kAsymmetricTestSalt = "salt"; -// The salt used for HKDF in symmetric key proofs. This value is part of the -// CryptAuth v2 Enrollment specifications. -const char kSymmetricKeyProofSalt[] = "CryptAuth Key Proof"; +// For generating symmetric key proofs, we internally derive a key before +// signing. Here, we use the first HKDF test case from RFC 5869 so we have a +// known derived key to verify the HMAC signature with. +// Input key material (IKM): +const std::vector<uint8_t> kTestSymmetricKeyBytes(22, 0x0b); +// salt: +const std::vector<uint8_t> kSymmetricTestSaltBytes = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, + 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c}; +// info: +const std::vector<uint8_t> kSymmetricTestInfoBytes = { + 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9}; +// The first 16 bytes of output key material (OKM): +const std::vector<uint8_t> kExpectedDerivedSymmetricKey16Bytes = { + 0x3c, 0xb2, 0x5f, 0x25, 0xfa, 0xac, 0xd5, 0x7a, + 0x90, 0x43, 0x4f, 0x64, 0xd0, 0x36, 0x2f, 0x2a}; +// The first 32 bytes of output key material (OKM): +const std::vector<uint8_t> kExpectedDerivedSymmetricKey32Bytes = { + 0x3c, 0xb2, 0x5f, 0x25, 0xfa, 0xac, 0xd5, 0x7a, 0x90, 0x43, 0x4f, + 0x64, 0xd0, 0x36, 0x2f, 0x2a, 0x2d, 0x2d, 0x0a, 0x90, 0xcf, 0x1a, + 0x5a, 0x4c, 0x5d, 0xb0, 0x2d, 0x56, 0xec, 0xc4, 0xc5, 0xbf}; -const char kFakePublicKeyMaterial[] = "public_key"; -const char kFakePrivateKeyMaterial[] = "private_key"; -const char kFakePayloadAsymmetricKey[] = "payload_asymmetric_key"; +const std::string kTestPayload = "sample"; -const char kFakeSymmetricKey256Material[] = "symmetric_key_256"; -const char kFakePayloadSymmetricKey256[] = "payload_symmetric_key_256"; - -const char kFakeSymmetricKey128Material[] = "symmetric_key_128"; -const char kFakePayloadSymmetricKey128[] = "payload_symmetric_key_128"; - -void VerifyKeyProofComputationCallback( - const std::vector<std::string>& expected_key_proofs, - const std::vector<std::string>& key_proofs) { - EXPECT_EQ(expected_key_proofs, key_proofs); +std::string ByteVectorToString(const std::vector<uint8_t>& byte_array) { + return std::string(byte_array.begin(), byte_array.end()); } -class FakeSecureMessageDelegateFactory - : public multidevice::SecureMessageDelegateImpl::Factory { - public: - FakeSecureMessageDelegateFactory() = default; - - ~FakeSecureMessageDelegateFactory() override = default; - - multidevice::FakeSecureMessageDelegate* instance() { return instance_; } - - private: - // multidevice::SecureMessageDelegateImpl::Factory: - std::unique_ptr<multidevice::SecureMessageDelegate> BuildInstance() override { - auto instance = std::make_unique<multidevice::FakeSecureMessageDelegate>(); - instance_ = instance.get(); - - return instance; - } - - multidevice::FakeSecureMessageDelegate* instance_ = nullptr; - - DISALLOW_COPY_AND_ASSIGN(FakeSecureMessageDelegateFactory); -}; +std::vector<uint8_t> StringToByteVector(const std::string& str) { + return std::vector<uint8_t>(str.begin(), str.end()); +} } // namespace -class DeviceSyncCryptAuthKeyProofComputerImplTest : public testing::Test { - protected: - DeviceSyncCryptAuthKeyProofComputerImplTest() = default; - ~DeviceSyncCryptAuthKeyProofComputerImplTest() override = default; +TEST(DeviceSyncCryptAuthKeyProofComputerImplTest, + AsymmetricKeyProofComputation_Success) { + CryptAuthKey key(ByteVectorToString(kTestPublicKeyBytes), + ByteVectorToString(kTestPrivateKeyBytes), + CryptAuthKey::Status::kActive, cryptauthv2::KeyType::P256); - void SetUp() override { - fake_secure_message_delegate_factory_ = - std::make_unique<FakeSecureMessageDelegateFactory>(); - multidevice::SecureMessageDelegateImpl::Factory::SetInstanceForTesting( - fake_secure_message_delegate_factory_.get()); + base::Optional<std::string> key_proof = + CryptAuthKeyProofComputerImpl::Factory::Get() + ->BuildInstance() + ->ComputeKeyProof(key, kTestPayload, kAsymmetricTestSalt); + EXPECT_TRUE(key_proof); - key_proof_computer_ = - CryptAuthKeyProofComputerImpl::Factory::Get()->BuildInstance(); - } + // Verify the key proof which should be of the form: + // Sign(|private_key|, |salt| + |payload|) + // + // Note: The signature is random, i.e., we have no way of setting "k" from RFC + // 6979 A.2.5. So, we can only verify the signature using the public key. + crypto::SignatureVerifier verifier; + EXPECT_TRUE(verifier.VerifyInit( + crypto::SignatureVerifier::SignatureAlgorithm::ECDSA_SHA256, + StringToByteVector(*key_proof), kTestPublicKeyBytes)); + verifier.VerifyUpdate(StringToByteVector(kAsymmetricTestSalt + kTestPayload)); + EXPECT_TRUE(verifier.VerifyFinal()); +} - void TearDown() override { - multidevice::SecureMessageDelegateImpl::Factory::SetInstanceForTesting( - nullptr); - } +TEST(DeviceSyncCryptAuthKeyProofComputerImplTest, + Symmetric256KeyProofComputation_Success) { + CryptAuthKey key(ByteVectorToString(kTestSymmetricKeyBytes), + CryptAuthKey::Status::kActive, cryptauthv2::KeyType::RAW256, + ByteVectorToString(kSymmetricTestInfoBytes)); - std::string ComputeSymmetricKeyProof(const CryptAuthKey& symmetric_key, - const std::string& payload) { - size_t num_bytes = - symmetric_key.type() == cryptauthv2::KeyType::RAW256 ? 32u : 16u; - std::string derived_symmetric_key_material = crypto::HkdfSha256( - symmetric_key.symmetric_key(), kSymmetricKeyProofSalt, - symmetric_key.handle(), num_bytes); + base::Optional<std::string> key_proof = + CryptAuthKeyProofComputerImpl::Factory::Get() + ->BuildInstance() + ->ComputeKeyProof(key, kTestPayload, + ByteVectorToString(kSymmetricTestSaltBytes)); + EXPECT_TRUE(key_proof); - crypto::HMAC hmac(crypto::HMAC::HashAlgorithm::SHA256); - std::vector<unsigned char> signed_payload(hmac.DigestLength()); - bool success = - hmac.Init(derived_symmetric_key_material) && - hmac.Sign(payload, signed_payload.data(), signed_payload.size()); - if (!success) - return ""; + // Verify the key proof which should be of the form: + // HMAC(HKDF(|key|, |salt|, info=<key handle>), |payload|) + crypto::HMAC hmac(crypto::HMAC::HashAlgorithm::SHA256); + EXPECT_TRUE( + hmac.Init(ByteVectorToString(kExpectedDerivedSymmetricKey32Bytes))); + EXPECT_TRUE(hmac.Verify(kTestPayload, *key_proof)); +} - return std::string(signed_payload.begin(), signed_payload.end()); - } +TEST(DeviceSyncCryptAuthKeyProofComputerImplTest, + Symmetric128KeyProofComputation_Success) { + CryptAuthKey key(ByteVectorToString(kTestSymmetricKeyBytes), + CryptAuthKey::Status::kActive, cryptauthv2::KeyType::RAW128, + ByteVectorToString(kSymmetricTestInfoBytes)); - std::string ComputeAsymmetricKeyProof(const CryptAuthKey& asymmetric_key, - const std::string& payload) { - multidevice::SecureMessageDelegate::CreateOptions options; - options.encryption_scheme = securemessage::EncScheme::NONE; - options.signature_scheme = securemessage::SigScheme::ECDSA_P256_SHA256; - options.verification_key_id = asymmetric_key.handle(); + base::Optional<std::string> key_proof = + CryptAuthKeyProofComputerImpl::Factory::Get() + ->BuildInstance() + ->ComputeKeyProof(key, kTestPayload, + ByteVectorToString(kSymmetricTestSaltBytes)); + EXPECT_TRUE(key_proof); - std::string key_proof; - fake_secure_message_delegate()->CreateSecureMessage( - payload, asymmetric_key.private_key(), options, - base::Bind( - [](std::string* key_proof, const std::string& secure_message) { - *key_proof = secure_message; - }, - &key_proof)); + crypto::HMAC hmac(crypto::HMAC::HashAlgorithm::SHA256); + EXPECT_TRUE( + hmac.Init(ByteVectorToString(kExpectedDerivedSymmetricKey16Bytes))); + EXPECT_TRUE(hmac.Verify(kTestPayload, *key_proof)); +} - return key_proof; - } +TEST(DeviceSyncCryptAuthKeyProofComputerImplTest, + AsymmetricKeyProofComputation_InvalidPrivateKeyFormat) { + CryptAuthKey key("public_key", "non_pkcs8_private_key", + CryptAuthKey::Status::kActive, cryptauthv2::KeyType::P256); - CryptAuthKeyProofComputer* key_proof_computer() { - return key_proof_computer_.get(); - } + base::Optional<std::string> key_proof = + CryptAuthKeyProofComputerImpl::Factory::Get() + ->BuildInstance() + ->ComputeKeyProof(key, kTestPayload, kAsymmetricTestSalt); - multidevice::FakeSecureMessageDelegate* fake_secure_message_delegate() { - return fake_secure_message_delegate_factory_->instance(); - } - - private: - std::unique_ptr<FakeSecureMessageDelegateFactory> - fake_secure_message_delegate_factory_; - - std::unique_ptr<CryptAuthKeyProofComputer> key_proof_computer_; - - DISALLOW_COPY_AND_ASSIGN(DeviceSyncCryptAuthKeyProofComputerImplTest); -}; - -TEST_F(DeviceSyncCryptAuthKeyProofComputerImplTest, - SuccessfulKeyProofComputation) { - std::vector<std::pair<CryptAuthKey, std::string>> key_payload_pairs = { - {CryptAuthKey(kFakePublicKeyMaterial, kFakePrivateKeyMaterial, - CryptAuthKey::Status::kActive, cryptauthv2::KeyType::P256), - kFakePayloadAsymmetricKey}, - {CryptAuthKey(kFakeSymmetricKey256Material, CryptAuthKey::Status::kActive, - cryptauthv2::KeyType::RAW256), - kFakePayloadSymmetricKey256}, - {CryptAuthKey(kFakeSymmetricKey128Material, CryptAuthKey::Status::kActive, - cryptauthv2::KeyType::RAW128), - kFakePayloadSymmetricKey128}}; - - std::vector<std::string> expected_key_proofs = { - ComputeAsymmetricKeyProof(key_payload_pairs[0].first, - key_payload_pairs[0].second), - ComputeSymmetricKeyProof(key_payload_pairs[1].first, - key_payload_pairs[1].second), - ComputeSymmetricKeyProof(key_payload_pairs[2].first, - key_payload_pairs[2].second)}; - - key_proof_computer()->ComputeKeyProofs( - key_payload_pairs, - base::BindOnce(&VerifyKeyProofComputationCallback, expected_key_proofs)); + EXPECT_FALSE(key_proof); } } // namespace device_sync
diff --git a/chromeos/services/device_sync/cryptauth_v2_enroller_impl.cc b/chromeos/services/device_sync/cryptauth_v2_enroller_impl.cc index 5ab35af..f5a0d38 100644 --- a/chromeos/services/device_sync/cryptauth_v2_enroller_impl.cc +++ b/chromeos/services/device_sync/cryptauth_v2_enroller_impl.cc
@@ -50,14 +50,18 @@ // for backward compatibility reasons. const char kFixedUserKeyPairHandle[] = "device_key"; +// The salt used in HKDF for symmetric key proofs. Also, for asymmetric key +// proofs, the salt is prepended to the payload before being signed by the +// private key. This value is part of the CryptAuth v2 Enrollment +// specifications. +const char kKeyProofSalt[] = "CryptAuth Key Proof"; + // Timeout values for asynchronous operations. // TODO(https://crbug.com/933656): Tune these values. constexpr base::TimeDelta kWaitingForSyncKeysResponseTimeout = base::TimeDelta::FromSeconds(10); constexpr base::TimeDelta kWaitingForKeyCreationTimeout = base::TimeDelta::FromSeconds(10); -constexpr base::TimeDelta kWaitingForKeyProofComputationTimeout = - base::TimeDelta::FromSeconds(10); constexpr base::TimeDelta kWaitingForEnrollKeysResponseTimeout = base::TimeDelta::FromSeconds(10); @@ -360,8 +364,6 @@ return kWaitingForSyncKeysResponseTimeout; case State::kWaitingForKeyCreation: return kWaitingForKeyCreationTimeout; - case State::kWaitingForKeyProofComputation: - return kWaitingForKeyProofComputationTimeout; case State::kWaitingForEnrollKeysResponse: return kWaitingForEnrollKeysResponseTimeout; default: @@ -380,9 +382,6 @@ case State::kWaitingForKeyCreation: return CryptAuthEnrollmentResult::ResultCode:: kErrorTimeoutWaitingForKeyCreation; - case State::kWaitingForKeyProofComputation: - return CryptAuthEnrollmentResult::ResultCode:: - kErrorTimeoutWaitingForKeyProofComputation; case State::kWaitingForEnrollKeysResponse: return CryptAuthEnrollmentResult::ResultCode:: kErrorTimeoutWaitingForEnrollKeysResponse; @@ -519,8 +518,8 @@ new_client_directive_ = response.client_directive(); - // Note: The server's Diffie-Hellman public key is only required if - // symmetric keys need to be created. + // Note: The server's Diffie-Hellman public key is only required if symmetric + // keys need to be created. base::Optional<CryptAuthKey> server_ephemeral_dh; if (!response.server_ephemeral_dh().empty()) { server_ephemeral_dh = CryptAuthKey( @@ -621,6 +620,10 @@ return error_code; } +void CryptAuthV2EnrollerImpl::OnSyncKeysFailure(NetworkRequestError error) { + FinishAttempt(SyncKeysNetworkRequestErrorToResultCode(error)); +} + void CryptAuthV2EnrollerImpl::OnKeysCreated( const std::string& session_id, const base::flat_map<CryptAuthKeyBundle::Name, cryptauthv2::KeyDirective>& @@ -629,62 +632,39 @@ const base::Optional<CryptAuthKey>& client_ephemeral_dh) { DCHECK(state_ == State::kWaitingForKeyCreation); - // Compute key proofs for the new keys, using the random_session_id from the - // SyncKeysResponse as the payload, per the v2 Enrollment specifications. - std::vector<std::pair<CryptAuthKey, std::string>> key_payload_pairs; - std::vector<CryptAuthKeyBundle::Name> key_bundle_order_for_proofs; - for (const std::pair<CryptAuthKeyBundle::Name, CryptAuthKey>& new_key : - new_keys) { - key_bundle_order_for_proofs.emplace_back(new_key.first); - key_payload_pairs.emplace_back(new_key.second, session_id); - } - - SetState(State::kWaitingForKeyProofComputation); - - key_proof_computer_ = - CryptAuthKeyProofComputerImpl::Factory::Get()->BuildInstance(); - key_proof_computer_->ComputeKeyProofs( - key_payload_pairs, - base::BindOnce(&CryptAuthV2EnrollerImpl::OnKeyProofsComputed, - base::Unretained(this), session_id, new_key_directives, - new_keys, client_ephemeral_dh, - key_bundle_order_for_proofs)); -} - -void CryptAuthV2EnrollerImpl::OnSyncKeysFailure(NetworkRequestError error) { - FinishAttempt(SyncKeysNetworkRequestErrorToResultCode(error)); -} - -void CryptAuthV2EnrollerImpl::OnKeyProofsComputed( - const std::string& session_id, - const base::flat_map<CryptAuthKeyBundle::Name, cryptauthv2::KeyDirective>& - new_key_directives, - const base::flat_map<CryptAuthKeyBundle::Name, CryptAuthKey>& new_keys, - const base::Optional<CryptAuthKey>& client_ephemeral_dh, - const std::vector<CryptAuthKeyBundle::Name>& key_bundle_order_for_proofs, - const std::vector<std::string>& key_proofs) { - DCHECK(state_ == State::kWaitingForKeyProofComputation); - EnrollKeysRequest request; request.set_random_session_id(session_id); if (client_ephemeral_dh) request.set_client_ephemeral_dh(client_ephemeral_dh->public_key()); - DCHECK(key_proofs.size() == key_bundle_order_for_proofs.size()); - for (size_t i = 0; i < key_bundle_order_for_proofs.size(); ++i) { - auto it = new_keys.find(key_bundle_order_for_proofs[i]); - DCHECK(it != new_keys.end()); - const CryptAuthKeyBundle::Name& bundle_name = it->first; - const CryptAuthKey& new_key = it->second; + std::unique_ptr<CryptAuthKeyProofComputer> key_proof_computer = + CryptAuthKeyProofComputerImpl::Factory::Get()->BuildInstance(); + + for (const std::pair<CryptAuthKeyBundle::Name, CryptAuthKey>& name_key_pair : + new_keys) { + const CryptAuthKeyBundle::Name& bundle_name = name_key_pair.first; + const CryptAuthKey& new_key = name_key_pair.second; EnrollSingleKeyRequest* single_key_request = request.add_enroll_single_key_requests(); single_key_request->set_key_name( CryptAuthKeyBundle::KeyBundleNameEnumToString(bundle_name)); single_key_request->set_new_key_handle(new_key.handle()); - single_key_request->set_key_proof(key_proofs[i]); if (new_key.IsAsymmetricKey()) single_key_request->set_key_material(new_key.public_key()); + + // Compute key proofs for the new keys using the random_session_id from the + // SyncKeysResponse as the payload and the particular salt specified by the + // v2 Enrollment protocol. + base::Optional<std::string> key_proof = + key_proof_computer->ComputeKeyProof(new_key, session_id, kKeyProofSalt); + if (!key_proof || key_proof->empty()) { + FinishAttempt(CryptAuthEnrollmentResult::ResultCode:: + kErrorKeyProofComputationFailed); + return; + } + + single_key_request->set_key_proof(*key_proof); } SetState(State::kWaitingForEnrollKeysResponse); @@ -743,9 +723,6 @@ case CryptAuthV2EnrollerImpl::State::kWaitingForKeyCreation: stream << "[Enroller state: Waiting for key creation]"; break; - case CryptAuthV2EnrollerImpl::State::kWaitingForKeyProofComputation: - stream << "[Enroller state: Waiting for key proof computation]"; - break; case CryptAuthV2EnrollerImpl::State::kWaitingForEnrollKeysResponse: stream << "[Enroller state: Waiting for EnrollKeys response]"; break;
diff --git a/chromeos/services/device_sync/cryptauth_v2_enroller_impl.h b/chromeos/services/device_sync/cryptauth_v2_enroller_impl.h index 014954e..5b3e01b 100644 --- a/chromeos/services/device_sync/cryptauth_v2_enroller_impl.h +++ b/chromeos/services/device_sync/cryptauth_v2_enroller_impl.h
@@ -36,7 +36,6 @@ class CryptAuthClient; class CryptAuthClientFactory; -class CryptAuthKeyProofComputer; class CryptAuthKeyRegistry; // An implementation of CryptAuthV2Enroller, using instances of CryptAuthClient @@ -65,7 +64,6 @@ kNotStarted, kWaitingForSyncKeysResponse, kWaitingForKeyCreation, - kWaitingForKeyProofComputation, kWaitingForEnrollKeysResponse, kFinished }; @@ -87,6 +85,7 @@ // enroller reads the existing keys from the registry and is responsible // for updating the key registry during the enrollment flow. // |client_factory|: Creates CryptAuthClient instances for making API calls. + // |timer|: Handles timeouts for asynchronous operations. CryptAuthV2EnrollerImpl(CryptAuthKeyRegistry* key_registry, CryptAuthClientFactory* client_factory, std::unique_ptr<base::OneShotTimer> timer); @@ -130,15 +129,6 @@ const base::flat_map<CryptAuthKeyBundle::Name, CryptAuthKey>& new_keys, const base::Optional<CryptAuthKey>& client_ephemeral_dh); - void OnKeyProofsComputed( - const std::string& session_id, - const base::flat_map<CryptAuthKeyBundle::Name, cryptauthv2::KeyDirective>& - new_key_directives, - const base::flat_map<CryptAuthKeyBundle::Name, CryptAuthKey>& new_keys, - const base::Optional<CryptAuthKey>& client_ephemeral_dh, - const std::vector<CryptAuthKeyBundle::Name>& key_bundle_order_for_proofs, - const std::vector<std::string>& key_proofs); - void OnEnrollKeysSuccess( const base::flat_map<CryptAuthKeyBundle::Name, cryptauthv2::KeyDirective>& new_key_directives, @@ -178,11 +168,6 @@ // CryptAuth in the EnrollKeysRequest. std::unique_ptr<CryptAuthKeyCreator> key_creator_; - // An instance of CryptAuthKeyProofComputer, used to generate the key proofs - // associated with the new keys requested in SyncKeysResponse. These key - // proofs are sent to CryptAuth in the EnrollKeysRequest. - std::unique_ptr<CryptAuthKeyProofComputer> key_proof_computer_; - DISALLOW_COPY_AND_ASSIGN(CryptAuthV2EnrollerImpl); };
diff --git a/chromeos/services/device_sync/cryptauth_v2_enroller_impl_unittest.cc b/chromeos/services/device_sync/cryptauth_v2_enroller_impl_unittest.cc index 9fc479e..bfb847a 100644 --- a/chromeos/services/device_sync/cryptauth_v2_enroller_impl_unittest.cc +++ b/chromeos/services/device_sync/cryptauth_v2_enroller_impl_unittest.cc
@@ -2,11 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chromeos/services/device_sync/cryptauth_v2_enroller_impl.h" - #include <memory> #include <string> #include <utility> +#include <vector> #include "base/bind.h" #include "base/containers/flat_map.h" @@ -18,6 +17,7 @@ #include "chromeos/services/device_sync/cryptauth_key_creator_impl.h" #include "chromeos/services/device_sync/cryptauth_key_proof_computer_impl.h" #include "chromeos/services/device_sync/cryptauth_key_registry_impl.h" +#include "chromeos/services/device_sync/cryptauth_v2_enroller_impl.h" #include "chromeos/services/device_sync/fake_cryptauth_key_creator.h" #include "chromeos/services/device_sync/fake_cryptauth_key_proof_computer.h" #include "chromeos/services/device_sync/mock_cryptauth_client.h" @@ -93,7 +93,6 @@ const char kNewPublicKey[] = "new_public_key"; const char kNewPrivateKey[] = "new_private_key"; const char kFixedUserKeyPairHandle[] = "device_key"; -const char kNewAsymmetricKeyProof[] = "asymmetric_key_proof"; const char kServerEphemeralDh[] = "server_ephemeral_dh"; const char kClientDhPublicKey[] = "client_ephemeral_dh_public_key"; @@ -103,6 +102,8 @@ CryptAuthKey::Status::kActive, KeyType::P256); +const char kKeyProofSalt[] = "CryptAuth Key Proof"; + class FakeCryptAuthKeyCreatorFactory : public CryptAuthKeyCreatorImpl::Factory { public: FakeCryptAuthKeyCreatorFactory() = default; @@ -132,18 +133,19 @@ ~FakeCryptAuthKeyProofComputerFactory() override = default; - FakeCryptAuthKeyProofComputer* instance() { return instance_; } + void set_should_return_null_key_proof(bool should_return_null_key_proof) { + should_return_null_key_proof_ = should_return_null_key_proof; + } private: // CryptAuthKeyProofComputerImpl::Factory: std::unique_ptr<CryptAuthKeyProofComputer> BuildInstance() override { auto instance = std::make_unique<FakeCryptAuthKeyProofComputer>(); - instance_ = instance.get(); - + instance->set_should_return_null(should_return_null_key_proof_); return instance; } - FakeCryptAuthKeyProofComputer* instance_ = nullptr; + bool should_return_null_key_proof_ = false; DISALLOW_COPY_AND_ASSIGN(FakeCryptAuthKeyProofComputerFactory); }; @@ -445,11 +447,6 @@ .Run(new_keys_output, client_ephemeral_dh_output); } - void RunKeyProofComputer(const std::vector<std::string>& key_proofs_output) { - std::move(key_proof_computer()->compute_key_proofs_callback()) - .Run(key_proofs_output); - } - void SendEnrollKeysResponse(const EnrollKeysResponse& enroll_keys_response) { std::move(enroll_keys_success_callback_).Run(enroll_keys_response); } @@ -506,6 +503,10 @@ CryptAuthClientFactory* client_factory() { return client_factory_.get(); } + FakeCryptAuthKeyProofComputerFactory* key_proof_computer_factory() { + return fake_cryptauth_key_proof_computer_factory_.get(); + } + base::MockOneShotTimer* timer() { return timer_; } const base::Optional<SyncKeysRequest>& sync_keys_request() { @@ -530,10 +531,6 @@ return fake_cryptauth_key_creator_factory_->instance(); } - FakeCryptAuthKeyProofComputer* key_proof_computer() { - return fake_cryptauth_key_proof_computer_factory_->instance(); - } - TestingPrefServiceSimple pref_service_; std::unique_ptr<CryptAuthKeyRegistry> key_registry_; std::unique_ptr<MockCryptAuthClientFactory> client_factory_; @@ -621,9 +618,6 @@ RunKeyCreator(expected_new_keys, kClientEphemeralDh); - // Assume successful key proof generation. - RunKeyProofComputer({kNewAsymmetricKeyProof} /* key_proof_output */); - // Verify EnrollKeysRequest. EXPECT_EQ(kRandomSessionId, enroll_keys_request()->random_session_id()); EXPECT_EQ(kClientDhPublicKey, enroll_keys_request()->client_ephemeral_dh()); @@ -638,7 +632,14 @@ EXPECT_EQ(kFixedUserKeyPairHandle, single_request_user_key_pair.new_key_handle()); EXPECT_EQ(kNewPublicKey, single_request_user_key_pair.key_material()); - EXPECT_EQ(kNewAsymmetricKeyProof, single_request_user_key_pair.key_proof()); + EXPECT_EQ( + CryptAuthKeyProofComputerImpl::Factory::Get() + ->BuildInstance() + ->ComputeKeyProof( + expected_new_keys.find(CryptAuthKeyBundle::Name::kUserKeyPair) + ->second, + kRandomSessionId, kKeyProofSalt), + single_request_user_key_pair.key_proof()); // Assume a successful EnrollKeys() call. // Note: No parameters in EnrollKeysResponse are processed by the enroller @@ -852,6 +853,35 @@ enrollment_result()); } +TEST_F(DeviceSyncCryptAuthV2EnrollerImplTest, + Failure_KeyProofComputationFailed) { + CallEnroll(GetSampleClientMetadata(), GetSampleClientAppMetadata(), + GetSamplePreviousClientDirectivePolicyReference()); + + SyncKeysResponse sync_keys_response = + BuildSyncKeysResponse({SyncSingleKeyResponseData( + CryptAuthKeyBundle::Name::kUserKeyPair, key_registry(), + {} /* handle_to_action_map */, + SyncSingleKeyResponse::ACTIVE /* new_key_creation */, + KeyType::P256 /* new_key_type */, + base::nullopt /* new_key_directive */)}); + SendSyncKeysResponse(sync_keys_response); + + key_proof_computer_factory()->set_should_return_null_key_proof(true); + + base::flat_map<CryptAuthKeyBundle::Name, CryptAuthKey> expected_new_keys = { + {CryptAuthKeyBundle::Name::kUserKeyPair, + CryptAuthKey(kNewPublicKey, kNewPrivateKey, + CryptAuthKey::Status::kActive, KeyType::P256, + kFixedUserKeyPairHandle)}}; + RunKeyCreator(expected_new_keys, kClientEphemeralDh); + + EXPECT_EQ(CryptAuthEnrollmentResult(CryptAuthEnrollmentResult::ResultCode:: + kErrorKeyProofComputationFailed, + sync_keys_response.client_directive()), + enrollment_result()); +} + TEST_F(DeviceSyncCryptAuthV2EnrollerImplTest, Failure_SyncKeysApiCall) { CallEnroll(GetSampleClientMetadata(), GetSampleClientAppMetadata(), GetSamplePreviousClientDirectivePolicyReference()); @@ -884,7 +914,6 @@ CryptAuthKey::Status::kActive, KeyType::P256, kFixedUserKeyPairHandle)}}; RunKeyCreator(expected_new_keys, kClientEphemeralDh); - RunKeyProofComputer({kNewAsymmetricKeyProof} /* key_proof_output */); FailEnrollKeysRequest(NetworkRequestError::kBadRequest); @@ -935,38 +964,6 @@ } TEST_F(DeviceSyncCryptAuthV2EnrollerImplTest, - Failure_Timeout_WaitingForKeyProofComputation) { - CallEnroll(GetSampleClientMetadata(), GetSampleClientAppMetadata(), - GetSamplePreviousClientDirectivePolicyReference()); - - SyncKeysResponse sync_keys_response = - BuildSyncKeysResponse({SyncSingleKeyResponseData( - CryptAuthKeyBundle::Name::kUserKeyPair, key_registry(), - {} /* handle_to_action_map */, - SyncSingleKeyResponse::ACTIVE /* new_key_creation */, - KeyType::P256 /* new_key_type */, - base::nullopt /* new_key_directive */)}); - SendSyncKeysResponse(sync_keys_response); - - base::flat_map<CryptAuthKeyBundle::Name, CryptAuthKey> expected_new_keys = { - {CryptAuthKeyBundle::Name::kUserKeyPair, - CryptAuthKey(kNewPublicKey, kNewPrivateKey, - CryptAuthKey::Status::kActive, KeyType::P256, - kFixedUserKeyPairHandle)}}; - RunKeyCreator(expected_new_keys, kClientEphemeralDh); - - // Timeout waiting for key proof creation. - EXPECT_TRUE(timer()->IsRunning()); - timer()->Fire(); - - EXPECT_EQ( - CryptAuthEnrollmentResult(CryptAuthEnrollmentResult::ResultCode:: - kErrorTimeoutWaitingForKeyProofComputation, - sync_keys_response.client_directive()), - enrollment_result()); -} - -TEST_F(DeviceSyncCryptAuthV2EnrollerImplTest, Failure_Timeout_WaitingForEnrollKeysResponse) { CallEnroll(GetSampleClientMetadata(), GetSampleClientAppMetadata(), GetSamplePreviousClientDirectivePolicyReference()); @@ -986,7 +983,6 @@ CryptAuthKey::Status::kActive, KeyType::P256, kFixedUserKeyPairHandle)}}; RunKeyCreator(expected_new_keys, kClientEphemeralDh); - RunKeyProofComputer({kNewAsymmetricKeyProof} /* key_proof_output */); // Timeout waiting for EnrollKeysResponse. EXPECT_TRUE(timer()->IsRunning());
diff --git a/chromeos/services/device_sync/fake_cryptauth_key_proof_computer.cc b/chromeos/services/device_sync/fake_cryptauth_key_proof_computer.cc index 901fe753..225b4b1 100644 --- a/chromeos/services/device_sync/fake_cryptauth_key_proof_computer.cc +++ b/chromeos/services/device_sync/fake_cryptauth_key_proof_computer.cc
@@ -4,7 +4,14 @@ #include "chromeos/services/device_sync/fake_cryptauth_key_proof_computer.h" -#include <utility> +#include "base/optional.h" +#include "chromeos/services/device_sync/cryptauth_key.h" + +namespace { + +const char kFakeKeyProofPrefix[] = "fake_key_proof"; + +} // namespace namespace chromeos { @@ -14,13 +21,15 @@ FakeCryptAuthKeyProofComputer::~FakeCryptAuthKeyProofComputer() = default; -void FakeCryptAuthKeyProofComputer::ComputeKeyProofs( - const std::vector<std::pair<CryptAuthKey, std::string>>& key_payload_pairs, - ComputeKeyProofsCallback compute_key_proofs_callback) { - DCHECK(!key_payload_pairs.empty()); - DCHECK(key_payload_pairs_.empty()); - key_payload_pairs_ = key_payload_pairs; - compute_key_proofs_callback_ = std::move(compute_key_proofs_callback); +base::Optional<std::string> FakeCryptAuthKeyProofComputer::ComputeKeyProof( + const CryptAuthKey& key, + const std::string& payload, + const std::string& salt) { + if (should_return_null_) + return base::nullopt; + + return kFakeKeyProofPrefix + std::string("_") + key.handle() + + std::string("_") + payload + std::string("_") + salt; } } // namespace device_sync
diff --git a/chromeos/services/device_sync/fake_cryptauth_key_proof_computer.h b/chromeos/services/device_sync/fake_cryptauth_key_proof_computer.h index 9734cf3..bd7c017 100644 --- a/chromeos/services/device_sync/fake_cryptauth_key_proof_computer.h +++ b/chromeos/services/device_sync/fake_cryptauth_key_proof_computer.h
@@ -6,39 +6,34 @@ #define CHROMEOS_SERVICES_DEVICE_SYNC_FAKE_CRYPTAUTH_KEY_PROOF_COMPUTER_H_ #include <string> -#include <vector> #include "base/macros.h" -#include "chromeos/services/device_sync/cryptauth_key.h" #include "chromeos/services/device_sync/cryptauth_key_proof_computer.h" namespace chromeos { namespace device_sync { +class CryptAuthKey; + class FakeCryptAuthKeyProofComputer : public CryptAuthKeyProofComputer { public: FakeCryptAuthKeyProofComputer(); ~FakeCryptAuthKeyProofComputer() override; // CryptAuthKeyProofComputer: - void ComputeKeyProofs( - const std::vector<std::pair<CryptAuthKey, std::string>>& - key_payload_pairs, - ComputeKeyProofsCallback compute_key_proofs_callback) override; + // Returns "fake_key_proof_<key handle>_<payload>_<salt>". + base::Optional<std::string> ComputeKeyProof(const CryptAuthKey& key, + const std::string& payload, + const std::string& salt) override; - const std::vector<std::pair<CryptAuthKey, std::string>>& key_payload_pairs() - const { - return key_payload_pairs_; - } - - ComputeKeyProofsCallback& compute_key_proofs_callback() { - return compute_key_proofs_callback_; + void set_should_return_null(bool should_return_null) { + should_return_null_ = should_return_null; } private: - std::vector<std::pair<CryptAuthKey, std::string>> key_payload_pairs_; - ComputeKeyProofsCallback compute_key_proofs_callback_; + // If true, ComputeKeyProof() returns base::nullopt. + bool should_return_null_ = false; DISALLOW_COPY_AND_ASSIGN(FakeCryptAuthKeyProofComputer); };
diff --git a/components/autofill_assistant/browser/BUILD.gn b/components/autofill_assistant/browser/BUILD.gn index 13202d5..0bffb91 100644 --- a/components/autofill_assistant/browser/BUILD.gn +++ b/components/autofill_assistant/browser/BUILD.gn
@@ -21,7 +21,6 @@ java_cpp_enum("autofill_assistant_enums_java") { sources = [ - "chip.h", "metrics.h", "overlay_state.h", ]
diff --git a/components/autofill_assistant/browser/actions/prompt_action.cc b/components/autofill_assistant/browser/actions/prompt_action.cc index 4b466727..a5fa7a2f 100644 --- a/components/autofill_assistant/browser/actions/prompt_action.cc +++ b/components/autofill_assistant/browser/actions/prompt_action.cc
@@ -74,16 +74,6 @@ std::unique_ptr<std::vector<Chip>> PromptAction::CreateChips() { auto chips = std::make_unique<std::vector<Chip>>(); - // TODO(crbug.com/806868): Surface type in proto instead of guessing it from - // highlight flag. - Chip::Type non_highlight_type = Chip::Type::CHIP_ASSISTIVE; - for (const auto& choice_proto : proto_.prompt().choices()) { - if (!choice_proto.name().empty() && choice_proto.highlight()) { - non_highlight_type = Chip::Type::BUTTON_HAIRLINE; - break; - } - } - for (int i = 0; i < proto_.prompt().choices_size(); i++) { auto& choice_proto = proto_.prompt().choices(i); if (choice_proto.show_only_if_element_exists().selectors_size() > 0 && @@ -91,11 +81,9 @@ continue; chips->emplace_back(); - chips->back().type = choice_proto.highlight() - ? Chip::Type::BUTTON_FILLED_BLUE - : non_highlight_type; - chips->back().text = choice_proto.name(); - + Chip& chip = chips->back(); + chip.text = choice_proto.name(); + chip.type = choice_proto.chip_type(); std::string server_payload; choice_proto.SerializeToString(&server_payload); @@ -103,6 +91,7 @@ base::BindOnce(&PromptAction::OnSuggestionChosen, weak_ptr_factory_.GetWeakPtr(), server_payload); } + SetDefaultChipType(chips.get()); return chips; }
diff --git a/components/autofill_assistant/browser/actions/show_details_action.cc b/components/autofill_assistant/browser/actions/show_details_action.cc index 2ed3975e..3d656eb5 100644 --- a/components/autofill_assistant/browser/actions/show_details_action.cc +++ b/components/autofill_assistant/browser/actions/show_details_action.cc
@@ -17,8 +17,7 @@ namespace autofill_assistant { -ShowDetailsAction::ShowDetailsAction(const ActionProto& proto) - : Action(proto), weak_ptr_factory_(this) { +ShowDetailsAction::ShowDetailsAction(const ActionProto& proto) : Action(proto) { DCHECK(proto_.has_show_details()); } @@ -26,57 +25,12 @@ void ShowDetailsAction::InternalProcessAction(ActionDelegate* delegate, ProcessActionCallback callback) { - callback_ = std::move(callback); - if (!proto_.show_details().has_details()) { delegate->ClearDetails(); - OnActionProcessed(ACTION_APPLIED); - return; + } else { + delegate->SetDetails(Details(proto_.show_details())); } - - Details details(proto_.show_details()); - delegate->SetDetails(details); - - if (!details.proto().change_flags().user_approval_required()) { - OnActionProcessed(ACTION_APPLIED); - return; - } - - // Ask for user approval. - - std::string previous_status_message = delegate->GetStatusMessage(); - delegate->SetStatusMessage( - l10n_util::GetStringUTF8(IDS_AUTOFILL_ASSISTANT_DETAILS_DIFFER)); - - // Continue button. - auto chips = std::make_unique<std::vector<Chip>>(); - chips->emplace_back(); - chips->back().text = - l10n_util::GetStringUTF8(IDS_AUTOFILL_ASSISTANT_CONTINUE_BUTTON); - chips->back().type = Chip::Type::BUTTON_FILLED_BLUE; - chips->back().callback = base::BindOnce( - &ShowDetailsAction::OnUserConfirmation, weak_ptr_factory_.GetWeakPtr(), - base::Unretained(delegate), previous_status_message); - - delegate->Prompt(std::move(chips)); -} - -void ShowDetailsAction::OnUserConfirmation( - ActionDelegate* delegate, - const std::string& previous_status_message) { - // Same details, without highlights. - Details details(proto_.show_details()); - details.ClearChanges(); - delegate->SetDetails(details); - // Restore status message - delegate->SetStatusMessage(previous_status_message); - OnActionProcessed(ACTION_APPLIED); -} - -void ShowDetailsAction::OnActionProcessed(ProcessedActionStatusProto status) { - DCHECK(callback_); - - UpdateProcessedAction(status); - std::move(callback_).Run(std::move(processed_action_proto_)); + UpdateProcessedAction(ACTION_APPLIED); + std::move(callback).Run(std::move(processed_action_proto_)); } } // namespace autofill_assistant
diff --git a/components/autofill_assistant/browser/actions/show_details_action.h b/components/autofill_assistant/browser/actions/show_details_action.h index ced6ba2..1b1b8bd 100644 --- a/components/autofill_assistant/browser/actions/show_details_action.h +++ b/components/autofill_assistant/browser/actions/show_details_action.h
@@ -23,12 +23,6 @@ // Overrides Action: void InternalProcessAction(ActionDelegate* delegate, ProcessActionCallback callback) override; - void OnUserConfirmation(ActionDelegate* delegate, - const std::string& old_status_message); - void OnActionProcessed(ProcessedActionStatusProto status); - - ProcessActionCallback callback_; - base::WeakPtrFactory<ShowDetailsAction> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(ShowDetailsAction); };
diff --git a/components/autofill_assistant/browser/actions/stop_action.cc b/components/autofill_assistant/browser/actions/stop_action.cc index 4ff6cd5..b220bf5 100644 --- a/components/autofill_assistant/browser/actions/stop_action.cc +++ b/components/autofill_assistant/browser/actions/stop_action.cc
@@ -20,7 +20,11 @@ void StopAction::InternalProcessAction(ActionDelegate* delegate, ProcessActionCallback callback) { - delegate->Shutdown(); + if (proto_.stop().close_cct()) { + delegate->Close(); + } else { + delegate->Shutdown(); + } UpdateProcessedAction(ACTION_APPLIED); std::move(callback).Run(std::move(processed_action_proto_)); }
diff --git a/components/autofill_assistant/browser/chip.cc b/components/autofill_assistant/browser/chip.cc index ca62f06a..8d97580 100644 --- a/components/autofill_assistant/browser/chip.cc +++ b/components/autofill_assistant/browser/chip.cc
@@ -11,4 +11,21 @@ Chip::Chip(Chip&&) = default; Chip& Chip::operator=(Chip&&) = default; -} // namespace autofill_assistant \ No newline at end of file +void SetDefaultChipType(std::vector<Chip>* chips) { + ChipType default_type = SUGGESTION; + for (const Chip& chip : *chips) { + if (chip.type != UNKNOWN_CHIP_TYPE && chip.type != SUGGESTION) { + // If there's an action chip, assume chips with unknown type are also + // actions. + default_type = NORMAL_ACTION; + break; + } + } + for (Chip& chip : *chips) { + if (chip.type == UNKNOWN_CHIP_TYPE) { + chip.type = default_type; + } + } +} + +} // namespace autofill_assistant
diff --git a/components/autofill_assistant/browser/chip.h b/components/autofill_assistant/browser/chip.h index ca872e21..941b5a410 100644 --- a/components/autofill_assistant/browser/chip.h +++ b/components/autofill_assistant/browser/chip.h
@@ -6,8 +6,10 @@ #define COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_CHIP_H_ #include <string> +#include <vector> #include "base/callback.h" +#include "components/autofill_assistant/browser/service.pb.h" namespace autofill_assistant { @@ -18,20 +20,7 @@ Chip(Chip&&); Chip& operator=(Chip&&); - // The type a chip can have. The terminology is borrow from: - // - https://guidelines.googleplex.com/googlematerial/components/chips.html - // - https://guidelines.googleplex.com/googlematerial/components/buttons.html - // GENERATED_JAVA_ENUM_PACKAGE: ( - // org.chromium.chrome.browser.autofill_assistant.carousel) - // GENERATED_JAVA_CLASS_NAME_OVERRIDE: AssistantChipType - enum Type { - CHIP_ASSISTIVE = 0, - BUTTON_FILLED_BLUE = 1, - BUTTON_HAIRLINE = 2, - }; - - // The type of the chip. - Type type; + ChipType type; // Localized string to display. std::string text; @@ -40,6 +29,9 @@ base::OnceClosure callback; }; +// Guarantees that the Chip.type of all chips is set to a sensible value. +void SetDefaultChipType(std::vector<Chip>* chips); + } // namespace autofill_assistant #endif // COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_CHIP_H_
diff --git a/components/autofill_assistant/browser/controller.cc b/components/autofill_assistant/browser/controller.cc index 10314300..6b44fca7 100644 --- a/components/autofill_assistant/browser/controller.cc +++ b/components/autofill_assistant/browser/controller.cc
@@ -171,7 +171,7 @@ if (chips && !chips->empty()) { for (auto iter = chips->begin(); iter != chips->end(); iter++) { - if (iter->type == Chip::Type::CHIP_ASSISTIVE) { + if (iter->type == SUGGESTION) { if (!suggestions_) { suggestions_ = std::make_unique<std::vector<Chip>>(); } @@ -652,28 +652,18 @@ } // Update the set of scripts in the UI. - // TODO(crbug.com/806868): Surface type in proto instead of guessing it from - // highlight flag. - Chip::Type non_highlight_type = Chip::Type::CHIP_ASSISTIVE; - for (const auto& script : runnable_scripts) { - if (!script.autostart && !script.name.empty() && script.highlight) { - non_highlight_type = Chip::Type::BUTTON_HAIRLINE; - break; - } - } - auto chips = std::make_unique<std::vector<Chip>>(); for (const auto& script : runnable_scripts) { if (!script.autostart && !script.name.empty()) { chips->emplace_back(); - chips->back().type = script.highlight ? Chip::Type::BUTTON_FILLED_BLUE - : non_highlight_type; chips->back().text = script.name; + chips->back().type = script.chip_type; chips->back().callback = base::BindOnce(&Controller::OnScriptSelected, weak_ptr_factory_.GetWeakPtr(), script.path); } } + SetDefaultChipType(chips.get()); if (allow_autostart_) { // Autostart was expected, but only non-autostartable scripts were found.
diff --git a/components/autofill_assistant/browser/protocol_utils.cc b/components/autofill_assistant/browser/protocol_utils.cc index 58399953..d5e88c5 100644 --- a/components/autofill_assistant/browser/protocol_utils.cc +++ b/components/autofill_assistant/browser/protocol_utils.cc
@@ -96,7 +96,7 @@ script->handle.autostart = presentation.autostart(); script->handle.interrupt = presentation.interrupt(); script->handle.initial_prompt = presentation.initial_prompt(); - script->handle.highlight = presentation.highlight(); + script->handle.chip_type = presentation.chip_type(); script->precondition = ScriptPrecondition::FromProto( script_proto.path(), presentation.precondition()); script->priority = presentation.priority();
diff --git a/components/autofill_assistant/browser/script.h b/components/autofill_assistant/browser/script.h index 320aa60..b728b6f65 100644 --- a/components/autofill_assistant/browser/script.h +++ b/components/autofill_assistant/browser/script.h
@@ -9,6 +9,7 @@ #include <string> #include "components/autofill_assistant/browser/script_precondition.h" +#include "components/autofill_assistant/browser/service.pb.h" namespace autofill_assistant { @@ -25,7 +26,7 @@ // When set to true this script can be run in 'autostart mode'. Script won't // be shown. bool autostart; - bool highlight; + ChipType chip_type; // If set, the script might be run during WaitForDom actions with // allow_interrupt=true.
diff --git a/components/autofill_assistant/browser/script_tracker.cc b/components/autofill_assistant/browser/script_tracker.cc index 4a80219a..104ec31 100644 --- a/components/autofill_assistant/browser/script_tracker.cc +++ b/components/autofill_assistant/browser/script_tracker.cc
@@ -172,7 +172,7 @@ script_js.SetKey("path", base::Value(entry.path)); script_js.SetKey("initial_prompt", base::Value(entry.initial_prompt)); script_js.SetKey("autostart", base::Value(entry.autostart)); - script_js.SetKey("highlight", base::Value(entry.highlight)); + script_js.SetKey("chip_type", base::Value(entry.chip_type)); runnable_scripts_js.push_back(std::move(script_js)); } dict.SetKey("runnable-scripts", base::Value(runnable_scripts_js));
diff --git a/components/autofill_assistant/browser/service.proto b/components/autofill_assistant/browser/service.proto index cff464d..142e6ec1 100644 --- a/components/autofill_assistant/browser/service.proto +++ b/components/autofill_assistant/browser/service.proto
@@ -80,11 +80,12 @@ // priority 1. optional int32 priority = 5; - // Whether the script should be highlighted. - optional bool highlight = 7; + // Describes the chip to be shown. The name of the chip is set by the + // name field. + optional ChipType chip_type = 10; - // When set to true this script can be run in 'autostart mode'. Script won't - // be shown. + // When set to true this script can be run in 'autostart mode'. Chip won't + // be shown; name and chip_type are ignored. optional bool autostart = 8; // When set to true this script will be run from WaitForDom actions with @@ -94,6 +95,35 @@ optional PresentationProto presentation = 2; } +enum ChipType { + UNKNOWN_CHIP_TYPE = 0; + + // Chip is a highlighted (blue) action chip. + HIGHLIGHTED_ACTION = 1; + + // Chip is a suggestion. + SUGGESTION = 2; + + // Chip is a normal action chip. + NORMAL_ACTION = 3; + + // A cancel chip, which closes AA in a way that allows the user to undo. + // + // The action associated with the chip is only executed after enough time has + // passed that undo is not possible. + // + // The presence of this chip inhibit the addition of an implicit close or + // cancel button. + CANCEL_ACTION = 4; + + // A close chip, which closes AA immediately. + // + // The presence of this chip inhibit the addition of an implicit close or + // cancel button. Otherwise, buttons of this type work and look like a + // NORMAL_ACTION. + CLOSE_ACTION = 5; +} + enum ScriptStatusProto { // Never explicitly set. Reading this value means the enum field is either // not set or set to a value not listed here. @@ -547,7 +577,7 @@ // Display this message to the user. optional string message = 1; - // A choice that is made either directly by clicking on a chip or button, or + // A choice that is made either directly by clicking on a chip or chip, or // implicitly by making a change on the website that is then detected by // looking for the existence of an element. // @@ -557,8 +587,9 @@ // Localized text message to display. Not required if element_exists is set. optional string name = 2; - // If set, the choice should be highlighted. Ignored unless name is set. - optional bool highlight = 3; + // Describes the chip to be shown. The name of the chip is set by the + // name field. + optional ChipType chip_type = 7; // Optionally auto-select this choice if the given element exist. optional ElementReferenceProto element_exists = 4; @@ -608,7 +639,13 @@ message ResetProto {} // Stop Autofill Assistant. -message StopProto {} +message StopProto { + // If true, close the Chrome Custom Tab, in addition to shutting down Autofill + // Assistant. + optional bool close_cct = 2; + + reserved 1; // stop_action_type +} message DateProto { optional int64 year = 1; @@ -637,7 +674,8 @@ } message DetailsChangesProto { - // Whether the changes require user approval. + // Whether the changes require user approval. This de-emphasize + // non-highlighted fields. optional bool user_approval_required = 1; // Whether the title should be highlighted.
diff --git a/components/chrome_cleaner/public/constants/result_codes.h b/components/chrome_cleaner/public/constants/result_codes.h index 8993f81..0068f91 100644 --- a/components/chrome_cleaner/public/constants/result_codes.h +++ b/components/chrome_cleaner/public/constants/result_codes.h
@@ -237,6 +237,10 @@ // file system. RESULT_CODE_WATCHDOG_TIMEOUT_WHILE_SCANNING_FILES = 58, + // The target process for the test engine sandbox disconnected from the IPC + // while the pipe was still needed by the broker process. + RESULT_CODE_TEST_ENGINE_SANDBOX_DISCONNECTED_TOO_SOON = 59, + // WHEN YOU ADD NEW EXIT CODES, DON'T FORGET TO UPDATE THE MONITORING RULES. // See http://go/chrome-cleaner-exit-codes. (Google internal only - external // contributors please ask one of the OWNERS to do the update.)
diff --git a/components/crash/core/common/crash_key.cc b/components/crash/core/common/crash_key.cc index 1e2952d..7acaed36 100644 --- a/components/crash/core/common/crash_key.cc +++ b/components/crash/core/common/crash_key.cc
@@ -4,6 +4,7 @@ #include "components/crash/core/common/crash_key.h" +#include "base/debug/stack_trace.h" #include "base/format_macros.h" #include "base/strings/stringprintf.h"
diff --git a/components/crash/core/common/crash_key.h b/components/crash/core/common/crash_key.h index f27b6eb..a38e24c 100644 --- a/components/crash/core/common/crash_key.h +++ b/components/crash/core/common/crash_key.h
@@ -9,7 +9,6 @@ #include <string> -#include "base/debug/stack_trace.h" #include "base/macros.h" #include "base/strings/string_piece.h" #include "build/build_config.h" @@ -24,6 +23,12 @@ #include "third_party/crashpad/crashpad/client/annotation.h" // nogncheck #endif +namespace base { +namespace debug { +class StackTrace; +} // namespace debug +} // namespace base + namespace crash_reporter { class CrashKeyBreakpadTest;
diff --git a/components/cronet/native/engine.cc b/components/cronet/native/engine.cc index 3cb3c82..f866a97 100644 --- a/components/cronet/native/engine.cc +++ b/components/cronet/native/engine.cc
@@ -36,13 +36,15 @@ // Marks |storage_path| in use, so multiple engines would not use it at the // same time. Returns |true| if marked successfully, |false| if it is in use // by another engine. - bool MarkStoragePathInUse(const std::string& storage_path) { + bool MarkStoragePathInUse(const std::string& storage_path) + LOCKS_EXCLUDED(lock_) { base::AutoLock lock(lock_); return in_use_storage_paths_.emplace(storage_path).second; } // Unmarks |storage_path| in use, so another engine could use it. - void UnmarkStoragePathInUse(const std::string& storage_path) { + void UnmarkStoragePathInUse(const std::string& storage_path) + LOCKS_EXCLUDED(lock_) { base::AutoLock lock(lock_); in_use_storage_paths_.erase(storage_path); } @@ -59,7 +61,7 @@ const std::string default_user_agent_; // Protecting shared state. base::Lock lock_; - std::unordered_set<std::string> in_use_storage_paths_; + std::unordered_set<std::string> in_use_storage_paths_ GUARDED_BY(lock_); DISALLOW_COPY_AND_ASSIGN(SharedEngineState); }; @@ -302,7 +304,7 @@ ~Callback() override; // CronetURLRequestContext::Callback implementation: - void OnInitNetworkThread() override; + void OnInitNetworkThread() override LOCKS_EXCLUDED(engine_->lock_); void OnDestroyNetworkThread() override; void OnEffectiveConnectionTypeChanged( net::EffectiveConnectionType effective_connection_type) override; @@ -317,7 +319,7 @@ int32_t throughput_kbps, int32_t timestamp_ms, net::NetworkQualityObservationSource source) override; - void OnStopNetLogCompleted() override; + void OnStopNetLogCompleted() override LOCKS_EXCLUDED(engine_->lock_); private: // The engine which owns context that owns |this| callback.
diff --git a/components/cronet/native/engine.h b/components/cronet/native/engine.h index 74a5c13..acc79bc 100644 --- a/components/cronet/native/engine.h +++ b/components/cronet/native/engine.h
@@ -11,6 +11,7 @@ #include "base/macros.h" #include "base/synchronization/lock.h" #include "base/synchronization/waitable_event.h" +#include "base/thread_annotations.h" #include "components/cronet/native/generated/cronet.idl_impl_interface.h" extern "C" typedef struct stream_engine stream_engine; @@ -29,12 +30,14 @@ ~Cronet_EngineImpl() override; // Cronet_Engine implementation: - Cronet_RESULT StartWithParams(Cronet_EngineParamsPtr params) override; - bool StartNetLogToFile(Cronet_String file_name, bool log_all) override; - void StopNetLog() override; + Cronet_RESULT StartWithParams(Cronet_EngineParamsPtr params) override + LOCKS_EXCLUDED(lock_); + bool StartNetLogToFile(Cronet_String file_name, bool log_all) override + LOCKS_EXCLUDED(lock_); + void StopNetLog() override LOCKS_EXCLUDED(lock_); Cronet_String GetVersionString() override; Cronet_String GetDefaultUserAgent() override; - Cronet_RESULT Shutdown() override; + Cronet_RESULT Shutdown() override LOCKS_EXCLUDED(lock_); void AddRequestFinishedListener( Cronet_RequestFinishedInfoListenerPtr listener, Cronet_ExecutorPtr executor) override; @@ -72,12 +75,12 @@ base::WaitableEvent init_completed_; // Flag that indicates whether logging is in progress. - bool is_logging_ = false; + bool is_logging_ GUARDED_BY(lock_) = false; // Signaled when |StopNetLog| is done. base::WaitableEvent stop_netlog_completed_; // Storage path used by this engine. - std::string in_use_storage_path_; + std::string in_use_storage_path_ GUARDED_BY(lock_); // Stream engine for GRPC Bidirectional Stream support. std::unique_ptr<StreamEngineImpl> stream_engine_;
diff --git a/components/flags_ui/flags_state.cc b/components/flags_ui/flags_state.cc index 6114397..0ae3d7d 100644 --- a/components/flags_ui/flags_state.cc +++ b/components/flags_ui/flags_state.cc
@@ -411,8 +411,6 @@ std::set<std::string> enabled_entries; GetSanitizedEnabledFlags(flags_storage, &enabled_entries); - // const bool enabled = - // enabled_entries.find(entry->internal_name) != enabled_entries.end(); const bool enabled = base::ContainsKey(enabled_entries, entry->internal_name); switch_values_[entry->command_line_switch] = value; DidModifyOriginListFlag(*entry, enabled);
diff --git a/components/gwp_asan/client/guarded_page_allocator.cc b/components/gwp_asan/client/guarded_page_allocator.cc index 2c25206..82c9fa89 100644 --- a/components/gwp_asan/client/guarded_page_allocator.cc +++ b/components/gwp_asan/client/guarded_page_allocator.cc
@@ -9,6 +9,7 @@ #include <memory> #include "base/bits.h" +#include "base/debug/stack_trace.h" #include "base/no_destructor.h" #include "base/process/process_metrics.h" #include "base/rand_util.h"
diff --git a/components/leveldb_proto/internal/proto_database_impl_unittest.cc b/components/leveldb_proto/internal/proto_database_impl_unittest.cc index 09ab189..3aa5d7fd 100644 --- a/components/leveldb_proto/internal/proto_database_impl_unittest.cc +++ b/components/leveldb_proto/internal/proto_database_impl_unittest.cc
@@ -7,6 +7,7 @@ #include "base/bind.h" #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" +#include "base/task/task_scheduler/task_scheduler.h" #include "base/test/scoped_task_environment.h" #include "base/threading/thread.h" #include "components/leveldb_proto/internal/shared_proto_database_provider.h" @@ -556,6 +557,7 @@ Enums::InitStatus::kOK); // Kill the DB impl so it doesn't have a lock on the DB anymore. unique_db_impl.reset(); + base::TaskScheduler::GetInstance()->FlushForTesting(); auto db_provider_withshared = CreateProviderWithSharedDB(); auto shared_db_impl = CreateDBImpl( @@ -832,4 +834,4 @@ EXPECT_FALSE(base::PathExists(temp_dir.GetPath())); } -} // namespace leveldb_proto \ No newline at end of file +} // namespace leveldb_proto
diff --git a/components/metrics/call_stack_profile_builder_unittest.cc b/components/metrics/call_stack_profile_builder_unittest.cc index 9922b4af..0cc4de0 100644 --- a/components/metrics/call_stack_profile_builder_unittest.cc +++ b/components/metrics/call_stack_profile_builder_unittest.cc
@@ -17,12 +17,33 @@ #include "third_party/metrics_proto/sampled_profile.pb.h" using Frame = base::StackSamplingProfiler::Frame; -using Module = base::ModuleCache::Module; namespace metrics { namespace { +// Stub module for testing. +class TestModule : public base::ModuleCache::Module { + public: + TestModule(uintptr_t base_address = 0, + const std::string& id = "", + const base::FilePath& debug_basename = base::FilePath()) + : base_address_(base_address), id_(id), debug_basename_(debug_basename) {} + + TestModule(const TestModule&) = delete; + TestModule& operator=(const TestModule&) = delete; + + uintptr_t GetBaseAddress() const override { return base_address_; } + std::string GetId() const override { return id_; } + base::FilePath GetDebugBasename() const override { return debug_basename_; } + size_t GetSize() const override { return 0; } + + private: + uintptr_t base_address_; + std::string id_; + base::FilePath debug_basename_; +}; + constexpr CallStackProfileParams kProfileParams = { CallStackProfileParams::BROWSER_PROCESS, CallStackProfileParams::MAIN_THREAD, @@ -85,15 +106,15 @@ #endif const uintptr_t module_base_address1 = 0x1000; - Module module1(module_base_address1, "1", module_path, 0x100); + TestModule module1(module_base_address1, "1", module_path); Frame frame1 = {module_base_address1 + 0x10, &module1}; const uintptr_t module_base_address2 = 0x1100; - Module module2(module_base_address2, "2", module_path, 0x10); + TestModule module2(module_base_address2, "2", module_path); Frame frame2 = {module_base_address2 + 0x10, &module2}; const uintptr_t module_base_address3 = 0x1010; - Module module3(module_base_address3, "3", module_path, 0x100); + TestModule module3(module_base_address3, "3", module_path); Frame frame3 = {module_base_address3 + 0x10, &module3}; std::vector<Frame> frames1 = {frame1, frame2}; @@ -158,19 +179,11 @@ auto profile_builder = std::make_unique<TestingCallStackProfileBuilder>(kProfileParams); -#if defined(OS_WIN) - base::FilePath module_path(L"c:\\some\\path\\to\\chrome.exe"); -#else - base::FilePath module_path("/some/path/to/chrome"); -#endif + TestModule module1; + Frame frame1 = {0x10, &module1}; - const uintptr_t module_base_address1 = 0x1000; - Module module1(module_base_address1, "1", module_path, 0x100); - Frame frame1 = {module_base_address1 + 0x10, &module1}; - - const uintptr_t module_base_address2 = 0x1100; - Module module2(module_base_address2, "2", module_path, 0x100); - Frame frame2 = {module_base_address2 + 0x10, &module2}; + TestModule module2; + Frame frame2 = {0x20, &module2}; std::vector<Frame> frames = {frame1, frame2}; @@ -204,19 +217,11 @@ auto profile_builder = std::make_unique<TestingCallStackProfileBuilder>(kProfileParams); -#if defined(OS_WIN) - base::FilePath module_path(L"c:\\some\\path\\to\\chrome.exe"); -#else - base::FilePath module_path("/some/path/to/chrome"); -#endif + TestModule module1; + Frame frame1 = {0x10, &module1}; - const uintptr_t module_base_address1 = 0x1000; - Module module1(module_base_address1, "1", module_path, 0x100); - Frame frame1 = {module_base_address1 + 0x10, &module1}; - - const uintptr_t module_base_address2 = 0x1100; - Module module2(module_base_address2, "2", module_path, 0x100); - Frame frame2 = {module_base_address2 + 0x10, &module2}; + TestModule module2; + Frame frame2 = {0x20, &module2}; std::vector<Frame> frames1 = {frame1}; std::vector<Frame> frames2 = {frame2}; @@ -250,9 +255,8 @@ auto profile_builder = std::make_unique<TestingCallStackProfileBuilder>(kProfileParams); - const uintptr_t module_base_address1 = 0x1000; // A frame with no module. - Frame frame1 = {module_base_address1 + 0x10, nullptr}; + Frame frame1 = {0x1010, nullptr}; const uintptr_t module_base_address2 = 0x1100; #if defined(OS_WIN) @@ -262,7 +266,7 @@ uint64_t module_md5 = 0x554838A8451AC36CULL; base::FilePath module_path("/some/path/to/chrome"); #endif - Module module2(module_base_address2, "2", module_path, 0x100); + TestModule module2(module_base_address2, "2", module_path); Frame frame2 = {module_base_address2 + 0x10, &module2}; std::vector<Frame> frames = {frame1, frame2}; @@ -311,7 +315,7 @@ base::FilePath module_path("/some/path/to/chrome"); #endif - Module module(module_base_address, "1", module_path, 0x100); + TestModule module(module_base_address, "1", module_path); Frame frame1 = {module_base_address + 0x10, &module}; Frame frame2 = {module_base_address + 0x20, &module}; @@ -363,14 +367,8 @@ auto profile_builder = std::make_unique<TestingCallStackProfileBuilder>( kProfileParams, &work_id_recorder); -#if defined(OS_WIN) - base::FilePath module_path(L"c:\\some\\path\\to\\chrome.exe"); -#else - base::FilePath module_path("/some/path/to/chrome"); -#endif - - Module module(0x1000, "1", module_path, 0x100); - Frame frame = {0x1000 + 0x10, &module}; + TestModule module; + Frame frame = {0x10, &module}; // Id 0 means the message loop hasn't been started yet, so the sample should // not have continued_work set. @@ -420,14 +418,8 @@ auto profile_builder = std::make_unique<TestingCallStackProfileBuilder>( kProfileParams, nullptr, &metadata_recorder); -#if defined(OS_WIN) - base::FilePath module_path(L"c:\\some\\path\\to\\chrome.exe"); -#else - base::FilePath module_path("/some/path/to/chrome"); -#endif - - Module module = {0x1000, "1", module_path, 0x100}; - Frame frame = {0x1000 + 0x10, &module}; + TestModule module; + Frame frame = {0x10, &module}; metadata_recorder.current_value = 5; profile_builder->OnSampleCompleted({frame});
diff --git a/components/ntp_snippets/contextual/reporting/contextual_suggestions_reporter.cc b/components/ntp_snippets/contextual/reporting/contextual_suggestions_reporter.cc index 579a8f81..018c2eb5 100644 --- a/components/ntp_snippets/contextual/reporting/contextual_suggestions_reporter.cc +++ b/components/ntp_snippets/contextual/reporting/contextual_suggestions_reporter.cc
@@ -4,7 +4,6 @@ #include "components/ntp_snippets/contextual/reporting/contextual_suggestions_reporter.h" -#include "base/debug/stack_trace.h" #include "components/ntp_snippets/contextual/reporting/contextual_suggestions_composite_reporter.h" #include "components/ntp_snippets/contextual/reporting/contextual_suggestions_debugging_reporter.h" #include "components/ntp_snippets/contextual/reporting/contextual_suggestions_metrics_reporter.h" @@ -36,4 +35,4 @@ ContextualSuggestionsReporter::ContextualSuggestionsReporter() = default; ContextualSuggestionsReporter::~ContextualSuggestionsReporter() = default; -} // namespace contextual_suggestions \ No newline at end of file +} // namespace contextual_suggestions
diff --git a/components/ntp_snippets/features.cc b/components/ntp_snippets/features.cc index b3e424fe..a8bd7d1 100644 --- a/components/ntp_snippets/features.cc +++ b/components/ntp_snippets/features.cc
@@ -31,7 +31,6 @@ &kIncreasedVisibility, &kKeepPrefetchedContentSuggestions, &kNotificationsFeature, - &kPublisherFaviconsFromNewServerFeature, &kRemoteSuggestionsBackendFeature}; const base::Feature kArticleSuggestionsFeature{ @@ -49,10 +48,6 @@ const base::Feature kCategoryRanker{"ContentSuggestionsCategoryRanker", base::FEATURE_ENABLED_BY_DEFAULT}; -const base::Feature kPublisherFaviconsFromNewServerFeature{ - "ContentSuggestionsFaviconsFromNewServer", - base::FEATURE_ENABLED_BY_DEFAULT}; - const base::Feature kRemoteSuggestionsEmulateM58FetchingSchedule{ "RemoteSuggestionsEmulateM58FetchingSchedule", base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/components/ntp_snippets/features.h b/components/ntp_snippets/features.h index bec6695..2399980 100644 --- a/components/ntp_snippets/features.h +++ b/components/ntp_snippets/features.h
@@ -48,9 +48,6 @@ // Feature to choose a category ranker. extern const base::Feature kCategoryRanker; -// Feature to allow the new Google favicon server for fetching publisher icons. -extern const base::Feature kPublisherFaviconsFromNewServerFeature; - // Feature for simple experimental comparison and validation of changes since // M58: enabling this brings back the M58 Stable fetching schedule (which is // suitable for Holdback groups).
diff --git a/components/omnibox/browser/autocomplete_classifier.cc b/components/omnibox/browser/autocomplete_classifier.cc index 2d3ea9b..e20b233c 100644 --- a/components/omnibox/browser/autocomplete_classifier.cc +++ b/components/omnibox/browser/autocomplete_classifier.cc
@@ -40,11 +40,10 @@ #if !defined(OS_ANDROID) && !defined(OS_IOS) // Custom search engines cannot be used on mobile. AutocompleteProvider::TYPE_KEYWORD | +#else + AutocompleteProvider::TYPE_CLIPBOARD | #endif AutocompleteProvider::TYPE_ZERO_SUGGEST | - (base::FeatureList::IsEnabled(omnibox::kEnableClipboardProvider) - ? AutocompleteProvider::TYPE_CLIPBOARD - : 0) | (base::FeatureList::IsEnabled(omnibox::kDocumentProvider) ? AutocompleteProvider::TYPE_DOCUMENT : 0) |
diff --git a/components/omnibox/browser/omnibox_field_trial.cc b/components/omnibox/browser/omnibox_field_trial.cc index 2703046..ecfbe96d 100644 --- a/components/omnibox/browser/omnibox_field_trial.cc +++ b/components/omnibox/browser/omnibox_field_trial.cc
@@ -147,17 +147,6 @@ const base::Feature kOmniboxContextMenuForSuggestions{ "OmniboxContextMenuForSuggestions", base::FEATURE_DISABLED_BY_DEFAULT}; -// Feature used to enable clipboard provider, which provides the user with -// suggestions of the URL in the user's clipboard (if any) upon omnibox focus. -const base::Feature kEnableClipboardProvider { - "OmniboxEnableClipboardProvider", -#if defined(OS_IOS) || defined(OS_ANDROID) - base::FEATURE_ENABLED_BY_DEFAULT -#else - base::FEATURE_DISABLED_BY_DEFAULT -#endif -}; - // Feature to enable clipboard provider to suggest copied text. const base::Feature kEnableClipboardProviderTextSuggestions{ "OmniboxEnableClipboardProviderTextSuggestions",
diff --git a/components/omnibox/browser/omnibox_field_trial.h b/components/omnibox/browser/omnibox_field_trial.h index a8d31ff..7e6b328 100644 --- a/components/omnibox/browser/omnibox_field_trial.h +++ b/components/omnibox/browser/omnibox_field_trial.h
@@ -40,7 +40,6 @@ extern const base::Feature kExperimentalKeywordMode; extern const base::Feature kOmniboxPedalSuggestions; extern const base::Feature kOmniboxContextMenuForSuggestions; -extern const base::Feature kEnableClipboardProvider; extern const base::Feature kEnableClipboardProviderTextSuggestions; extern const base::Feature kEnableClipboardProviderImageSuggestions; extern const base::Feature kSearchProviderWarmUpOnFocus;
diff --git a/components/password_manager/core/browser/sync/password_sync_bridge.cc b/components/password_manager/core/browser/sync/password_sync_bridge.cc index 2feafd6..281423d 100644 --- a/components/password_manager/core/browser/sync/password_sync_bridge.cc +++ b/components/password_manager/core/browser/sync/password_sync_bridge.cc
@@ -112,6 +112,39 @@ return primary_key; } +// Returns true iff |password_specifics| and |password_form| are equal +// memberwise. +bool AreLocalAndRemotePasswordsEqual( + const sync_pb::PasswordSpecificsData& password_specifics, + const autofill::PasswordForm& password_form) { + return (password_form.scheme == password_specifics.scheme() && + password_form.signon_realm == password_specifics.signon_realm() && + password_form.origin.spec() == password_specifics.origin() && + password_form.action.spec() == password_specifics.action() && + base::UTF16ToUTF8(password_form.username_element) == + password_specifics.username_element() && + base::UTF16ToUTF8(password_form.password_element) == + password_specifics.password_element() && + base::UTF16ToUTF8(password_form.username_value) == + password_specifics.username_value() && + base::UTF16ToUTF8(password_form.password_value) == + password_specifics.password_value() && + password_form.preferred == password_specifics.preferred() && + password_form.date_created == + base::Time::FromDeltaSinceWindowsEpoch( + base::TimeDelta::FromMicroseconds( + password_specifics.date_created())) && + password_form.blacklisted_by_user == + password_specifics.blacklisted() && + password_form.type == password_specifics.type() && + password_form.times_used == password_specifics.times_used() && + base::UTF16ToUTF8(password_form.display_name) == + password_specifics.display_name() && + password_form.icon_url.spec() == password_specifics.avatar_url() && + url::Origin::Create(GURL(password_specifics.federation_url())) + .Serialize() == password_form.federation_origin.Serialize()); +} + // A simple class for scoping a password store sync transaction. This does not // support rollback since the password store sync doesn't either. class ScopedStoreTransaction { @@ -202,6 +235,16 @@ base::Optional<syncer::ModelError> PasswordSyncBridge::MergeSyncData( std::unique_ptr<syncer::MetadataChangeList> metadata_change_list, syncer::EntityChangeList entity_data) { + // This method merges the local and remote passwords based on their client + // tags. For a form |F|, there are three cases to handle: + // 1. |F| exists only in the local model --> |F| should be Put() in the change + // processor. + // 2. |F| exists only in the remote model --> |F| should be AddLoginSync() to + // the local password store. + // 3. |F| exists in both the local and the remote models --> both versions + // should be merged by accepting the most recently created one, and update + // local and remote models accordingly. + base::AutoReset<bool> processing_changes(&is_processing_remote_sync_changes_, true); // Read all local passwords. @@ -211,11 +254,13 @@ "Failed to load entries from password store."); } - // Collect the client tags of remote passwords. Note that |entity_data| only - // contains client tag *hashes*. - std::unordered_set<std::string> client_tags_of_remote_passwords; + // Collect the client tags of remote passwords and the corresponding + // EntityChange. Note that |entity_data| only contains client tag *hashes*. + std::map<std::string, const syncer::EntityChange*> + client_tag_to_remote_entity_change_map; for (const syncer::EntityChange& entity_change : entity_data) { - client_tags_of_remote_passwords.insert(GetClientTag(entity_change.data())); + client_tag_to_remote_entity_change_map[GetClientTag(entity_change.data())] = + &entity_change; } // This is used to keep track of all the changes applied to the password @@ -224,47 +269,102 @@ base::Optional<syncer::ModelError> error; { ScopedStoreTransaction transaction(password_store_sync_); + const base::Time time_now = base::Time::Now(); // For any local password that doesn't exist in the remote passwords, issue - // a change_processor()->Put(). Password comparison is done by comparing the - // client tags. In addition, collect the client tags of local passwords. + // a change_processor()->Put(). For any local password that exists in the + // remote passwords, both should be merged by picking the most recently + // created version. Password comparison is done by comparing the client + // tags. In addition, collect the client tags of local passwords. std::unordered_set<std::string> client_tags_of_local_passwords; for (const auto& pair : key_to_local_form_map) { - std::unique_ptr<syncer::EntityData> entity_data = - CreateEntityData(/*password_form=*/*pair.second); + const int primary_key = pair.first; + const autofill::PasswordForm& local_password_form = *pair.second; + std::unique_ptr<syncer::EntityData> local_form_entity_data = + CreateEntityData(local_password_form); const std::string client_tag_of_local_password = - GetClientTag(*entity_data); + GetClientTag(*local_form_entity_data); client_tags_of_local_passwords.insert(client_tag_of_local_password); - if (client_tags_of_remote_passwords.count(client_tag_of_local_password) == - 0) { + + if (client_tag_to_remote_entity_change_map.count( + client_tag_of_local_password) == 0) { + // Local password doesn't exist in the remote model, Put() it in the + // processor. change_processor()->Put( - /*storage_key=*/base::NumberToString(pair.first), - std::move(entity_data), metadata_change_list.get()); + /*storage_key=*/base::NumberToString(primary_key), + std::move(local_form_entity_data), metadata_change_list.get()); + continue; + } + + // Local password exists in the remote model as well. A merge is required. + const syncer::EntityChange& remote_entity_change = + *client_tag_to_remote_entity_change_map[client_tag_of_local_password]; + const sync_pb::PasswordSpecificsData& remote_password_specifics = + remote_entity_change.data() + .specifics.password() + .client_only_encrypted_data(); + + // First, we need to inform the processor about the storage key anyway. + change_processor()->UpdateStorageKey(remote_entity_change.data(), + /*storage_key=*/ + base::NumberToString(primary_key), + metadata_change_list.get()); + + if (AreLocalAndRemotePasswordsEqual(remote_password_specifics, + local_password_form)) { + // Passwords are identical, nothing else to do. + continue; + } + + // Passwords aren't identical, pick the most recently created one. + if (base::Time::FromDeltaSinceWindowsEpoch( + base::TimeDelta::FromMicroseconds( + remote_password_specifics.date_created())) < + local_password_form.date_created) { + // The local password is more recent, update the processor. + change_processor()->Put( + /*storage_key=*/base::NumberToString(primary_key), + std::move(local_form_entity_data), metadata_change_list.get()); + } else { + // The remote password is more recent, update the local model. + PasswordStoreChangeList changes = + password_store_sync_->UpdateLoginSync(PasswordFromEntityChange( + remote_entity_change, /*sync_time=*/time_now)); + DCHECK_LE(changes.size(), 1U); + if (changes.empty()) { + return syncer::ModelError( + FROM_HERE, "Failed to update an entry in the password store."); + } + DCHECK(changes[0].primary_key() == primary_key); + password_store_changes.push_back(changes[0]); } } + // At this point, we have processed all local passwords. In addition, we + // also have processed all remote passwords that exist in the local model. + // What's remaining is to process remote passwords that don't exist in the + // local model. + // For any remote password that doesn't exist in the local passwords, issue - // a password_store_sync_->AddLoginSync() and for those that exist in the - // local passwords, issue a password_store_sync_->UpdateLoginSync(). - // Password comparison is done by comparing the client tags. In both cases, - // invoke the change_processor()->UpdateStorageKey(). - const base::Time time_now = base::Time::Now(); + // a password_store_sync_->AddLoginSync() and invoke the + // change_processor()->UpdateStorageKey(). Password comparison is done by + // comparing the client tags. for (const syncer::EntityChange& entity_change : entity_data) { const std::string client_tag_of_remote_password = GetClientTag(entity_change.data()); - PasswordStoreChangeList changes; - if (client_tags_of_local_passwords.count(client_tag_of_remote_password) == + if (client_tags_of_local_passwords.count(client_tag_of_remote_password) != 0) { - changes = password_store_sync_->AddLoginSync( - PasswordFromEntityChange(entity_change, /*sync_time=*/time_now)); - DCHECK_LE(changes.size(), 1U); - } else { - changes = password_store_sync_->UpdateLoginSync( - PasswordFromEntityChange(entity_change, /*sync_time=*/time_now)); - DCHECK_LE(changes.size(), 1U); + // Passwords in both local and remote models have been processed + // already. + continue; } + + PasswordStoreChangeList changes = password_store_sync_->AddLoginSync( + PasswordFromEntityChange(entity_change, /*sync_time=*/time_now)); + DCHECK_LE(changes.size(), 1U); + if (changes.empty()) { return syncer::ModelError( - FROM_HERE, "Failed to add/update an entry in the password store."); + FROM_HERE, "Failed to add an entry in the password store."); } change_processor()->UpdateStorageKey(
diff --git a/components/password_manager/core/browser/sync/password_sync_bridge_unittest.cc b/components/password_manager/core/browser/sync/password_sync_bridge_unittest.cc index 3f38d40..243973d 100644 --- a/components/password_manager/core/browser/sync/password_sync_bridge_unittest.cc +++ b/components/password_manager/core/browser/sync/password_sync_bridge_unittest.cc
@@ -513,41 +513,48 @@ fake_db()->AddLoginForPrimaryKey(kPrimaryKey1, form1); fake_db()->AddLoginForPrimaryKey(kPrimaryKey2, form2); - // Form 1 will be added to the change processor, Form 2 will be updated in the - // password sync store, and Form 3 will be added to the password store sync. + // Form 1 will be added to the change processor. The local version of Form 2 + // isn't more recent than the remote version, therefore it will be updated in + // the password sync store using the remote version. Form 3 will be added to + // the password store sync. // Interactions should happen in this order: // +--> Put(1) ------------------------------------+ // | | - // Begin() --|--> UpdateLoginSync(2) --> UpdateStorageKey(2)-|--> Commit() + // |--> UpdateStorageKey(2) -----------------------| + // Begin() --| |--> Commit() + // |--> UpdateLoginSync(3) ------------------------| // | | - // +--> AddLoginSync (3) --> UpdateStorageKey(3)-+ + // +--> AddLoginSync (4) ---> UpdateStorageKey(4)--+ - testing::Sequence s1, s2, s3; + testing::Sequence s1, s2, s3, s4; EXPECT_CALL(*mock_password_store_sync(), BeginTransaction()) - .InSequence(s1, s2, s3); + .InSequence(s1, s2, s3, s4); EXPECT_CALL(mock_processor(), Put(kPrimaryKeyStr1, EntityDataHasSignonRealm(kSignonRealm1), _)) .InSequence(s1); - EXPECT_CALL(*mock_password_store_sync(), - UpdateLoginSync(FormHasSignonRealm(kSignonRealm2))) - .InSequence(s2); - EXPECT_CALL(*mock_password_store_sync(), - AddLoginSync(FormHasSignonRealm(kSignonRealm3))) - .InSequence(s3); EXPECT_CALL(mock_processor(), UpdateStorageKey(_, kPrimaryKeyStr2, _)) .InSequence(s2); - EXPECT_CALL(mock_processor(), UpdateStorageKey(_, kExpectedPrimaryKeyStr3, _)) + + EXPECT_CALL(*mock_password_store_sync(), + UpdateLoginSync(FormHasSignonRealm(kSignonRealm2))) .InSequence(s3); + + EXPECT_CALL(*mock_password_store_sync(), + AddLoginSync(FormHasSignonRealm(kSignonRealm3))) + .InSequence(s4); + EXPECT_CALL(mock_processor(), UpdateStorageKey(_, kExpectedPrimaryKeyStr3, _)) + .InSequence(s4); + EXPECT_CALL(*mock_password_store_sync(), CommitTransaction()) - .InSequence(s1, s2, s3); + .InSequence(s1, s2, s3, s4); EXPECT_CALL(*mock_password_store_sync(), NotifyLoginsChanged(UnorderedElementsAre( ChangeHasPrimaryKey(kPrimaryKey2), ChangeHasPrimaryKey(kExpectedPrimaryKey3)))) - .InSequence(s1, s2, s3); + .InSequence(s1, s2, s3, s4); // Processor shouldn't be informed about Form 2 or Form 3. EXPECT_CALL(mock_processor(), Put(kPrimaryKeyStr2, _, _)).Times(0); @@ -562,6 +569,60 @@ EXPECT_FALSE(error); } +TEST_F(PasswordSyncBridgeTest, + ShouldMergeSyncRemoteAndLocalPasswordsChoosingTheMoreRecent) { + // Setup the test to have Form 1 and Form 2 stored locally and remotely. Local + // Form 1 is more recent than the remote one. Remote Form 2 is more recent + // than the local one. We will assign primary keys for Form 1 and Form 2 in + // the local DB. + base::Time now = base::Time::Now(); + base::Time yesterday = now - base::TimeDelta::FromDays(1); + const int kPrimaryKey1 = 1000; + const int kPrimaryKey2 = 1001; + const std::string kPrimaryKeyStr1 = "1000"; + const std::string kPrimaryKeyStr2 = "1001"; + + // Local form 1 is more recent than the remote. + autofill::PasswordForm form1 = MakePasswordForm(kSignonRealm1); + form1.date_created = now; + sync_pb::PasswordSpecifics specifics1 = + CreateSpecificsWithSignonRealm(kSignonRealm1); + specifics1.mutable_client_only_encrypted_data()->set_date_created( + yesterday.ToDeltaSinceWindowsEpoch().InMicroseconds()); + + // Remote form 2 is more recent than the local. + autofill::PasswordForm form2 = MakePasswordForm(kSignonRealm2); + form2.date_created = yesterday; + sync_pb::PasswordSpecifics specifics2 = + CreateSpecificsWithSignonRealm(kSignonRealm2); + specifics2.mutable_client_only_encrypted_data()->set_date_created( + now.ToDeltaSinceWindowsEpoch().InMicroseconds()); + + fake_db()->AddLoginForPrimaryKey(kPrimaryKey1, form1); + fake_db()->AddLoginForPrimaryKey(kPrimaryKey2, form2); + + // The processor should be informed about the storage keys of both passwords. + EXPECT_CALL(mock_processor(), UpdateStorageKey(_, kPrimaryKeyStr1, _)); + EXPECT_CALL(mock_processor(), UpdateStorageKey(_, kPrimaryKeyStr2, _)); + + // Since local Form 1 is more recent, it will be put() in the processor. + EXPECT_CALL(mock_processor(), + Put(kPrimaryKeyStr1, EntityDataHasSignonRealm(kSignonRealm1), _)); + + // Since the remote Form 2 is more recent, it will be updated in the password + // store. + EXPECT_CALL(*mock_password_store_sync(), + UpdateLoginSync(FormHasSignonRealm(kSignonRealm2))); + + base::Optional<syncer::ModelError> error = bridge()->MergeSyncData( + bridge()->CreateMetadataChangeList(), + {syncer::EntityChange::CreateAdd( + /*storage_key=*/"", SpecificsToEntity(specifics1)), + syncer::EntityChange::CreateAdd( + /*storage_key=*/"", SpecificsToEntity(specifics2))}); + EXPECT_FALSE(error); +} + TEST_F(PasswordSyncBridgeTest, ShouldGetAllDataForDebuggingWithHiddenPassword) { const int kPrimaryKey1 = 1000; const int kPrimaryKey2 = 1001;
diff --git a/components/printing/renderer/print_render_frame_helper.cc b/components/printing/renderer/print_render_frame_helper.cc index 560a6e4..40ea9d2 100644 --- a/components/printing/renderer/print_render_frame_helper.cc +++ b/components/printing/renderer/print_render_frame_helper.cc
@@ -93,10 +93,10 @@ PREVIEW_EVENT_MAX, }; -const double kMinDpi = 1.0; +constexpr double kMinDpi = 1.0; // Also set in third_party/WebKit/Source/core/page/PrintContext.h -const float kPrintingMinimumShrinkFactor = 1.33333333f; +constexpr float kPrintingMinimumShrinkFactor = 1.33333333f; #if BUILDFLAG(ENABLE_PRINT_PREVIEW) bool g_is_preview_enabled = true; @@ -134,9 +134,8 @@ bool PrintMsg_Print_Params_IsValid(const PrintMsg_Print_Params& params) { return !params.content_size.IsEmpty() && !params.page_size.IsEmpty() && !params.printable_area.IsEmpty() && params.document_cookie && - !params.dpi.IsEmpty() && params.dpi.width() > kMinDpi && - params.dpi.height() > kMinDpi && params.margin_top >= 0 && - params.margin_left >= 0 && params.document_cookie != 0; + params.dpi.width() > kMinDpi && params.dpi.height() > kMinDpi && + params.margin_top >= 0 && params.margin_left >= 0; } // Helper function to check for fit to page @@ -181,7 +180,7 @@ // Invalid page size and/or margins. We just use the default setting. if (new_content_width < 1 || new_content_height < 1) { - CHECK(frame != nullptr); + CHECK(frame); page_css_params = GetCssPrintParams(nullptr, page_index, page_params); return page_css_params; } @@ -624,9 +623,9 @@ } blink::WebLocalFrame* FrameReference::GetFrame() { - if (view_ == nullptr || frame_ == nullptr) + if (!view_ || !frame_) return nullptr; - for (blink::WebFrame* frame = view_->MainFrame(); frame != nullptr; + for (blink::WebFrame* frame = view_->MainFrame(); frame; frame = frame->TraverseNext()) { if (frame == frame_) return frame_;
diff --git a/components/reading_list/core/proto/BUILD.gn b/components/reading_list/core/proto/BUILD.gn index 927a5ee..e6d9f53 100644 --- a/components/reading_list/core/proto/BUILD.gn +++ b/components/reading_list/core/proto/BUILD.gn
@@ -8,7 +8,4 @@ sources = [ "reading_list.proto", ] - deps = [ - "//components/sync/protocol", - ] }
diff --git a/components/services/font/public/cpp/font_loader.cc b/components/services/font/public/cpp/font_loader.cc index d8076b0e..6342887 100644 --- a/components/services/font/public/cpp/font_loader.cc +++ b/components/services/font/public/cpp/font_loader.cc
@@ -27,15 +27,15 @@ FontIdentity* out_font_identifier, SkString* out_family_name, SkFontStyle* out_style) { - TRACE_EVENT1("font_service", "FontServiceThread::MatchFamilyName", - "family_name", TRACE_STR_COPY(family_name)); + TRACE_EVENT1("fonts", "FontServiceThread::MatchFamilyName", "family_name", + TRACE_STR_COPY(family_name)); return thread_->MatchFamilyName(family_name, requested, out_font_identifier, out_family_name, out_style); } SkStreamAsset* FontLoader::openStream(const FontIdentity& identity) { - TRACE_EVENT2("font_loader", "FontLoader::openStream", "identity", - identity.fID, "name", TRACE_STR_COPY(identity.fString.c_str())); + TRACE_EVENT2("fonts", "FontLoader::openStream", "identity", identity.fID, + "name", TRACE_STR_COPY(identity.fString.c_str())); { base::AutoLock lock(lock_); auto mapped_font_files_it = mapped_font_files_.find(identity.fID); @@ -105,8 +105,8 @@ } void FontLoader::OnMappedFontFileDestroyed(internal::MappedFontFile* f) { - TRACE_EVENT1("font_loader", "FontLoader::OnMappedFontFileDestroyed", - "identity", f->font_id()); + TRACE_EVENT1("fonts", "FontLoader::OnMappedFontFileDestroyed", "identity", + f->font_id()); base::AutoLock lock(lock_); mapped_font_files_.erase(f->font_id()); }
diff --git a/components/tracing/common/tracing_sampler_profiler_unittest.cc b/components/tracing/common/tracing_sampler_profiler_unittest.cc index da4b899..6bd88e9 100644 --- a/components/tracing/common/tracing_sampler_profiler_unittest.cc +++ b/components/tracing/common/tracing_sampler_profiler_unittest.cc
@@ -6,7 +6,6 @@ #include "base/at_exit.h" #include "base/bind.h" -#include "base/files/file_path.h" #include "base/json/json_reader.h" #include "base/memory/ref_counted_memory.h" #include "base/profiler/stack_sampling_profiler.h" @@ -143,6 +142,20 @@ DISALLOW_COPY_AND_ASSIGN(TracingSampleProfilerTest); }; +// Stub module for testing. +class TestModule : public base::ModuleCache::Module { + public: + TestModule() = default; + + TestModule(const TestModule&) = delete; + TestModule& operator=(const TestModule&) = delete; + + uintptr_t GetBaseAddress() const override { return 0; } + std::string GetId() const override { return ""; } + base::FilePath GetDebugBasename() const override { return base::FilePath(); } + size_t GetSize() const override { return 0; } +}; + } // namespace TEST_F(TracingSampleProfilerTest, OnSampleCompleted) { @@ -178,13 +191,7 @@ } TEST(TracingProfileBuilderTest, ValidModule) { -#if defined(OS_WIN) - base::FilePath module_path(L"c:\\some\\path\\to\\chrome.exe"); -#else - base::FilePath module_path("/some/path/to/chrome"); -#endif - - base::ModuleCache::Module module(0x1000, "ID", module_path, 0x2000); + TestModule module; TracingSamplerProfiler::TracingProfileBuilder profile_builder( (base::PlatformThreadId())); profile_builder.OnSampleCompleted(
diff --git a/components/user_manager/user_manager_base.cc b/components/user_manager/user_manager_base.cc index 5dbb470..5e050b7 100644 --- a/components/user_manager/user_manager_base.cc +++ b/components/user_manager/user_manager_base.cc
@@ -94,7 +94,7 @@ // Feature that hides Supervised Users. const base::Feature kHideSupervisedUsers{"HideSupervisedUsers", - base::FEATURE_DISABLED_BY_DEFAULT}; + base::FEATURE_ENABLED_BY_DEFAULT}; // static void UserManagerBase::RegisterPrefs(PrefRegistrySimple* registry) {
diff --git a/components/viz/common/hit_test/hit_test_data_builder.cc b/components/viz/common/hit_test/hit_test_data_builder.cc index 1d7ae75a..1fce595 100644 --- a/components/viz/common/hit_test/hit_test_data_builder.cc +++ b/components/viz/common/hit_test/hit_test_data_builder.cc
@@ -27,7 +27,8 @@ const gfx::Rect& visible_rect, const gfx::Transform& hit_test_region_transform, std::vector<HitTestRegion>* regions, - bool should_ask_for_child_region) { + bool should_ask_for_child_region, + bool ignores_input_event) { regions->emplace_back(); HitTestRegion* hit_test_region = ®ions->back(); hit_test_region->frame_sink_id = frame_sink_id; @@ -39,6 +40,8 @@ hit_test_region->async_hit_test_reasons = AsyncHitTestReasons::kUseDrawQuadData; } + if (ignores_input_event) + hit_test_region->flags |= HitTestRegionFlags::kHitTestIgnore; hit_test_region->rect = visible_rect; hit_test_region->transform = hit_test_region_transform; } @@ -100,10 +103,6 @@ if (quad->material == DrawQuad::SURFACE_CONTENT) { const SurfaceDrawQuad* surface_quad = SurfaceDrawQuad::MaterialCast(quad); - // Skip the quad if it has pointer-events:none set. - if (surface_quad->ignores_input_event) - continue; - // Skip the quad if the transform is not invertible (i.e. it will not // be able to receive events). gfx::Transform quad_to_target_transform = @@ -126,12 +125,14 @@ if (filter_regions.empty()) { AddHitTestRegion(surface_quad->surface_range.end().frame_sink_id(), surface_quad->rect, hit_test_region_transform, regions, - should_ask_for_child_region); + should_ask_for_child_region, + surface_quad->ignores_input_event); } else { for (const auto& filter_region : filter_regions) { AddHitTestRegion(surface_quad->surface_range.end().frame_sink_id(), filter_region, hit_test_region_transform, regions, - should_ask_for_child_region); + should_ask_for_child_region, + surface_quad->ignores_input_event); } } } else if (quad->material == DrawQuad::RENDER_PASS) {
diff --git a/components/viz/host/hit_test/hit_test_query.cc b/components/viz/host/hit_test/hit_test_query.cc index 7e74fc7..6bc7ff2 100644 --- a/components/viz/host/hit_test/hit_test_query.cc +++ b/components/viz/host/hit_test/hit_test_query.cc
@@ -109,7 +109,6 @@ } bool HitTestQuery::TransformLocationForTarget( - EventSource event_source, const std::vector<FrameSinkId>& target_ancestors, const gfx::PointF& location_in_root, gfx::PointF* transformed_location) const { @@ -142,9 +141,8 @@ transform_timer.Elapsed(), base::TimeDelta::FromMicroseconds(1), base::TimeDelta::FromSeconds(10), 50); - return TransformLocationForTargetRecursively(event_source, target_ancestors, - target_ancestors.size() - 1, 0, - transformed_location); + return TransformLocationForTargetRecursively( + target_ancestors, target_ancestors.size() - 1, 0, transformed_location); } bool HitTestQuery::GetTransformToTarget(const FrameSinkId& target, @@ -235,7 +233,8 @@ DCHECK_EQ(!!(flags & HitTestRegionFlags::kHitTestAsk), !!hit_test_data_[region_index].async_hit_test_reasons); - if (flags & HitTestRegionFlags::kHitTestAsk) { + if ((flags & HitTestRegionFlags::kHitTestAsk) && + !(flags & HitTestRegionFlags::kHitTestIgnore)) { target->frame_sink_id = hit_test_data_[region_index].frame_sink_id; target->location_in_target = location_in_target; target->flags = flags; @@ -262,7 +261,8 @@ if (!RegionMatchEventSource(event_source, flags)) return false; - if (flags & HitTestRegionFlags::kHitTestMine) { + if ((flags & HitTestRegionFlags::kHitTestMine) && + !(flags & HitTestRegionFlags::kHitTestIgnore)) { target->frame_sink_id = hit_test_data_[region_index].frame_sink_id; target->location_in_target = location_in_target; target->flags = flags; @@ -275,17 +275,10 @@ } bool HitTestQuery::TransformLocationForTargetRecursively( - EventSource event_source, const std::vector<FrameSinkId>& target_ancestors, size_t target_ancestor, size_t region_index, gfx::PointF* location_in_target) const { - const uint32_t flags = hit_test_data_[region_index].flags; - if ((flags & HitTestRegionFlags::kHitTestChildSurface) == 0u && - !RegionMatchEventSource(event_source, flags)) { - return false; - } - hit_test_data_[region_index].transform().TransformPoint(location_in_target); if (!target_ancestor) return true; @@ -302,7 +295,7 @@ if (hit_test_data_[child_region].frame_sink_id == target_ancestors[target_ancestor - 1]) { return TransformLocationForTargetRecursively( - event_source, target_ancestors, target_ancestor - 1, child_region, + target_ancestors, target_ancestor - 1, child_region, location_in_target); }
diff --git a/components/viz/host/hit_test/hit_test_query.h b/components/viz/host/hit_test/hit_test_query.h index 8261e31..c1f50fde 100644 --- a/components/viz/host/hit_test/hit_test_query.h +++ b/components/viz/host/hit_test/hit_test_query.h
@@ -93,7 +93,6 @@ // |target_ancestors.front()| is the target, and |target_ancestors.back()| // is the root. bool TransformLocationForTarget( - EventSource event_source, const std::vector<FrameSinkId>& target_ancestors, const gfx::PointF& location_in_root, gfx::PointF* transformed_location) const; @@ -143,7 +142,6 @@ // |location_in_target| is in the coordinate space of |region_index|'s parent // at the beginning. bool TransformLocationForTargetRecursively( - EventSource event_source, const std::vector<FrameSinkId>& target_ancestors, size_t target_ancestor, size_t region_index,
diff --git a/components/viz/host/hit_test/hit_test_query_fuzzer.cc b/components/viz/host/hit_test/hit_test_query_fuzzer.cc index 9af346c..64f601a 100644 --- a/components/viz/host/hit_test/hit_test_query_fuzzer.cc +++ b/components/viz/host/hit_test/hit_test_query_fuzzer.cc
@@ -83,8 +83,7 @@ for (float y = 0; y < 1000.; y += 10) { gfx::PointF location(x, y); query.FindTargetForLocation(viz::EventSource::MOUSE, location); - query.TransformLocationForTarget(viz::EventSource::MOUSE, frame_sink_ids, - location, &location); + query.TransformLocationForTarget(frame_sink_ids, location, &location); } }
diff --git a/components/viz/host/hit_test/hit_test_query_unittest.cc b/components/viz/host/hit_test/hit_test_query_unittest.cc index 29c876f..9ac8c00 100644 --- a/components/viz/host/hit_test/hit_test_query_unittest.cc +++ b/components/viz/host/hit_test/hit_test_query_unittest.cc
@@ -400,19 +400,19 @@ std::vector<FrameSinkId> target_ancestors1{e_id}; gfx::PointF transformed_point; EXPECT_TRUE(hit_test_query().TransformLocationForTarget( - EventSource::MOUSE, target_ancestors1, point1, &transformed_point)); + target_ancestors1, point1, &transformed_point)); EXPECT_EQ(transformed_point, point1); std::vector<FrameSinkId> target_ancestors2{a_id, c_id, e_id}; EXPECT_TRUE(hit_test_query().TransformLocationForTarget( - EventSource::MOUSE, target_ancestors2, point2, &transformed_point)); + target_ancestors2, point2, &transformed_point)); EXPECT_EQ(transformed_point, gfx::PointF(2, 2)); std::vector<FrameSinkId> target_ancestors3{d_id, e_id}; EXPECT_TRUE(hit_test_query().TransformLocationForTarget( - EventSource::MOUSE, target_ancestors3, point3, &transformed_point)); + target_ancestors3, point3, &transformed_point)); EXPECT_EQ(transformed_point, gfx::PointF(50, 100)); std::vector<FrameSinkId> target_ancestors4{b_id, c_id, e_id}; EXPECT_TRUE(hit_test_query().TransformLocationForTarget( - EventSource::MOUSE, target_ancestors4, point4, &transformed_point)); + target_ancestors4, point4, &transformed_point)); EXPECT_EQ(transformed_point, gfx::PointF(2, 2)); } @@ -617,29 +617,29 @@ std::vector<FrameSinkId> target_ancestors1{e_id}; gfx::PointF transformed_point; EXPECT_TRUE(hit_test_query().TransformLocationForTarget( - EventSource::MOUSE, target_ancestors1, point1, &transformed_point)); + target_ancestors1, point1, &transformed_point)); EXPECT_EQ(transformed_point, point1); std::vector<FrameSinkId> target_ancestors2{a_id, c1_id, e_id}; EXPECT_TRUE(hit_test_query().TransformLocationForTarget( - EventSource::MOUSE, target_ancestors2, point2, &transformed_point)); + target_ancestors2, point2, &transformed_point)); EXPECT_EQ(transformed_point, gfx::PointF(2, 2)); EXPECT_TRUE(hit_test_query().TransformLocationForTarget( - EventSource::MOUSE, target_ancestors1, point3, &transformed_point)); + target_ancestors1, point3, &transformed_point)); EXPECT_EQ(transformed_point, point3); std::vector<FrameSinkId> target_ancestors3{b_id, c1_id, e_id}; EXPECT_TRUE(hit_test_query().TransformLocationForTarget( - EventSource::MOUSE, target_ancestors3, point4, &transformed_point)); + target_ancestors3, point4, &transformed_point)); EXPECT_EQ(transformed_point, gfx::PointF(2, 2)); std::vector<FrameSinkId> target_ancestors4{g_id, c2_id, e_id}; EXPECT_TRUE(hit_test_query().TransformLocationForTarget( - EventSource::MOUSE, target_ancestors4, point5, &transformed_point)); + target_ancestors4, point5, &transformed_point)); EXPECT_EQ(transformed_point, gfx::PointF(50, 50)); EXPECT_TRUE(hit_test_query().TransformLocationForTarget( - EventSource::MOUSE, target_ancestors1, point6, &transformed_point)); + target_ancestors1, point6, &transformed_point)); EXPECT_EQ(transformed_point, point6); std::vector<FrameSinkId> target_ancestors5{h_id, c2_id, e_id}; EXPECT_TRUE(hit_test_query().TransformLocationForTarget( - EventSource::MOUSE, target_ancestors5, point7, &transformed_point)); + target_ancestors5, point7, &transformed_point)); EXPECT_EQ(transformed_point, gfx::PointF(150, 300)); }
diff --git a/components/viz/service/display/display.cc b/components/viz/service/display/display.cc index cd9f1dd..41e2a09 100644 --- a/components/viz/service/display/display.cc +++ b/components/viz/service/display/display.cc
@@ -290,15 +290,13 @@ &settings_, output_surface_.get(), resource_provider_.get(), skia_output_surface_, SkiaRenderer::DrawMode::DDL); } else { - // GPU compositing with GL. + // GPU compositing with GL to an SKP. DCHECK(output_surface_); DCHECK(output_surface_->context_provider()); - SkiaRenderer::DrawMode mode = settings_.record_sk_picture - ? SkiaRenderer::DrawMode::SKPRECORD - : SkiaRenderer::DrawMode::GL; + DCHECK(settings_.record_sk_picture); renderer_ = std::make_unique<SkiaRenderer>( &settings_, output_surface_.get(), resource_provider_.get(), - nullptr /* skia_output_surface */, mode); + nullptr /* skia_output_surface */, SkiaRenderer::DrawMode::SKPRECORD); } } else if (output_surface_->context_provider()) { renderer_ = std::make_unique<GLRenderer>(&settings_, output_surface_.get(),
diff --git a/components/viz/service/display/skia_renderer.cc b/components/viz/service/display/skia_renderer.cc index 227d52a..4882351 100644 --- a/components/viz/service/display/skia_renderer.cc +++ b/components/viz/service/display/skia_renderer.cc
@@ -203,17 +203,6 @@ draw_mode_(mode), skia_output_surface_(skia_output_surface) { switch (draw_mode_) { - case DrawMode::GL: { - DCHECK(output_surface_); - context_provider_ = output_surface_->context_provider(); - const auto& context_caps = context_provider_->ContextCapabilities(); - use_swap_with_bounds_ = context_caps.swap_buffers_with_bounds; - if (context_caps.sync_query) { - sync_queries_ = - base::Optional<SyncQueryCollection>(context_provider_->ContextGL()); - } - break; - } case DrawMode::DDL: { DCHECK(skia_output_surface_); lock_set_for_external_use_.emplace(resource_provider, @@ -236,7 +225,7 @@ SkiaRenderer::~SkiaRenderer() = default; bool SkiaRenderer::CanPartialSwap() { - if (draw_mode_ != DrawMode::GL && draw_mode_ != DrawMode::SKPRECORD) + if (draw_mode_ != DrawMode::SKPRECORD) return false; DCHECK(context_provider_); @@ -248,7 +237,7 @@ void SkiaRenderer::BeginDrawingFrame() { TRACE_EVENT0("viz", "SkiaRenderer::BeginDrawingFrame"); - if (draw_mode_ != DrawMode::GL && draw_mode_ != DrawMode::SKPRECORD) + if (draw_mode_ != DrawMode::SKPRECORD) return; // Copied from GLRenderer. @@ -308,10 +297,6 @@ skia_output_surface_->SkiaSwapBuffers(std::move(output_frame)); break; } - case DrawMode::GL: { - output_surface_->SwapBuffers(std::move(output_frame)); - break; - } case DrawMode::SKPRECORD: { // write to skp files std::string file_name = "composited-frame.skp"; @@ -347,43 +332,12 @@ DCHECK(!output_surface_->HasExternalStencilTest()); non_root_surface_ = nullptr; - // LegacyFontHost will get LCD text and skia figures out what type to use. - SkSurfaceProps surface_props = - SkSurfaceProps(0, SkSurfaceProps::kLegacyFontHost_InitType); - - // TODO(weiliangc): Set up correct can_use_lcd_text for SkSurfaceProps flags. - // How to setup is in ResourceProvider. (http://crbug.com/644851) switch (draw_mode_) { case DrawMode::DDL: { root_canvas_ = skia_output_surface_->BeginPaintCurrentFrame(); DCHECK(root_canvas_); break; } - case DrawMode::GL: { - auto* gr_context = GetGrContext(); - if (!root_canvas_ || root_canvas_->getGrContext() != gr_context || - gfx::SkISizeToSize(root_canvas_->getBaseLayerSize()) != - current_frame()->device_viewport_size) { - // Either no SkSurface setup yet, or new GrContext, need to create new - // surface. - GrGLFramebufferInfo framebuffer_info; - framebuffer_info.fFBOID = 0; - framebuffer_info.fFormat = GL_RGB8_OES; - GrBackendRenderTarget render_target( - current_frame()->device_viewport_size.width(), - current_frame()->device_viewport_size.height(), 0, 8, - framebuffer_info); - - root_surface_ = SkSurface::MakeFromBackendRenderTarget( - gr_context, render_target, kBottomLeft_GrSurfaceOrigin, - kRGB_888x_SkColorType, - current_frame()->root_render_pass->color_space.ToSkColorSpace(), - &surface_props); - DCHECK(root_surface_); - root_canvas_ = root_surface_->getCanvas(); - } - break; - } case DrawMode::SKPRECORD: { root_recorder_ = std::make_unique<SkPictureRecorder>(); @@ -428,12 +382,6 @@ backing.color_space.ToSkColorSpace()); break; } - case DrawMode::GL: { - non_root_surface_ = backing.render_pass_surface; - current_surface_ = non_root_surface_.get(); - current_canvas_ = non_root_surface_->getCanvas(); - break; - } case DrawMode::SKPRECORD: { current_recorder_ = backing.recorder.get(); current_picture_ = &backing.picture; @@ -984,10 +932,6 @@ backing.generate_mipmap, backing.color_space.ToSkColorSpace()); break; } - case DrawMode::GL: { - content_image = backing.render_pass_surface->makeImageSnapshot(); - break; - } case DrawMode::SKPRECORD: { content_image = SkImage::MakeFromPicture( backing.picture, @@ -1142,37 +1086,6 @@ std::move(request)); break; } - case DrawMode::GL: { - if (request->result_format() != CopyOutputResult::Format::RGBA_BITMAP || - request->is_scaled() || - geometry.result_bounds != geometry.result_selection) { - // TODO(crbug.com/644851): Complete the implementation for all request - // types, scaling, etc. - NOTIMPLEMENTED(); - return; - } - sk_sp<SkImage> copy_image = - current_surface_->makeImageSnapshot()->makeSubset( - RectToSkIRect(geometry.sampling_bounds)); - - // Send copy request by copying into a bitmap. - SkBitmap bitmap; - copy_image->asLegacyBitmap(&bitmap); - // TODO(crbug.com/795132): Plumb color space throughout SkiaRenderer up to - // the SkSurface/SkImage here. Until then, play "musical chairs" with the - // SkPixelRef to hack-in the RenderPass's |color_space|. - sk_sp<SkPixelRef> pixels(SkSafeRef(bitmap.pixelRef())); - SkIPoint origin = bitmap.pixelRefOrigin(); - bitmap.setInfo( - bitmap.info().makeColorSpace( - current_frame() - ->current_render_pass->color_space.ToSkColorSpace()), - bitmap.rowBytes()); - bitmap.setPixelRef(std::move(pixels), origin.x(), origin.y()); - request->SendResult(std::make_unique<CopyOutputSkBitmapResult>( - geometry.result_bounds, bitmap)); - break; - } case DrawMode::SKPRECORD: { NOTIMPLEMENTED(); break; @@ -1206,23 +1119,6 @@ lock_set_for_external_use_->UnlockResources(sync_token); break; } - case DrawMode::GL: { - // For SkiaRendererPixelTestWithOverdrawFeedback, CopyDrawnRenderPass - // happens before FinishDrawingFrame which results in an empty image. So - // force a draw here. - if (settings_->show_overdraw_feedback && - (current_frame()->current_render_pass == - current_frame()->root_render_pass)) { - sk_sp<SkImage> image = overdraw_surface_->makeImageSnapshot(); - SkPaint paint; - sk_sp<SkColorFilter> color_filter = - SkiaHelper::MakeOverdrawColorFilter(); - paint.setColorFilter(color_filter); - current_surface_->getCanvas()->drawImage(image.get(), 0, 0, &paint); - } - current_canvas_->flush(); - break; - } case DrawMode::SKPRECORD: { current_canvas_->flush(); sk_sp<SkPicture> picture = current_recorder_->finishRecordingAsPicture(); @@ -1249,8 +1145,6 @@ switch (draw_mode_) { case DrawMode::DDL: return nullptr; - case DrawMode::GL: - return context_provider_->GrContext(); case DrawMode::SKPRECORD: return nullptr; } @@ -1304,11 +1198,6 @@ switch (draw_mode_) { case DrawMode::DDL: break; - case DrawMode::GL: { - caps.texture_format_bgra8888 = - context_provider_->ContextCapabilities().texture_format_bgra8888; - break; - } case DrawMode::SKPRECORD: { render_pass_backings_.emplace( render_pass_id,
diff --git a/components/viz/service/display/skia_renderer.h b/components/viz/service/display/skia_renderer.h index b89fcc5..2456721 100644 --- a/components/viz/service/display/skia_renderer.h +++ b/components/viz/service/display/skia_renderer.h
@@ -37,7 +37,7 @@ class VIZ_SERVICE_EXPORT SkiaRenderer : public DirectRenderer { public: // Different draw modes that are supported by SkiaRenderer right now. - enum DrawMode { GL, DDL, SKPRECORD }; + enum DrawMode { DDL, SKPRECORD }; // TODO(penghuang): Remove skia_output_surface when DDL is used everywhere. SkiaRenderer(const RendererSettings* settings, @@ -123,8 +123,9 @@ const cc::FilterOperations* backdrop_filters) const; const TileDrawQuad* CanPassBeDrawnDirectly(const RenderPass* pass) override; - // Get corresponding GrContext in DrawMode::GL. Returns nullptr when there is - // no GrContext. + // Get corresponding GrContext. Returns nullptr when there is no GrContext. + // TODO(weiliangc): This currently only returns nullptr. If SKPRecord isn't + // going to use this later, it should be removed. GrContext* GetGrContext(); bool is_using_ddl() const { return draw_mode_ == DrawMode::DDL; } @@ -172,9 +173,7 @@ std::unique_ptr<SkCanvas> overdraw_canvas_; std::unique_ptr<SkNWayCanvas> nway_canvas_; - // Specific for GL. - ContextProvider* context_provider_ = nullptr; - base::Optional<SyncQueryCollection> sync_queries_; + // TODO(crbug.com/920344): Use partial swap for SkDDL. bool use_swap_with_bounds_ = false; gfx::Rect swap_buffer_rect_; std::vector<gfx::Rect> swap_content_bounds_; @@ -216,6 +215,8 @@ sk_sp<SkPicture> root_picture_; sk_sp<SkPicture>* current_picture_; SkPictureRecorder* current_recorder_; + ContextProvider* context_provider_ = nullptr; + base::Optional<SyncQueryCollection> sync_queries_; DISALLOW_COPY_AND_ASSIGN(SkiaRenderer); };
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn index 14780267..e019a1d 100644 --- a/content/browser/BUILD.gn +++ b/content/browser/BUILD.gn
@@ -1491,8 +1491,8 @@ "renderer_host/media/old_render_frame_audio_output_stream_factory.h", "renderer_host/media/peer_connection_tracker_host.cc", "renderer_host/media/peer_connection_tracker_host.h", - "renderer_host/media/ref_counted_video_capture_factory.cc", - "renderer_host/media/ref_counted_video_capture_factory.h", + "renderer_host/media/ref_counted_video_source_provider.cc", + "renderer_host/media/ref_counted_video_source_provider.h", "renderer_host/media/render_frame_audio_input_stream_factory.cc", "renderer_host/media/render_frame_audio_input_stream_factory.h", "renderer_host/media/render_frame_audio_output_stream_factory.cc",
diff --git a/content/browser/accessibility/browser_accessibility_com_win.cc b/content/browser/accessibility/browser_accessibility_com_win.cc index c3a43e5f..c9974ec 100644 --- a/content/browser/accessibility/browser_accessibility_com_win.cc +++ b/content/browser/accessibility/browser_accessibility_com_win.cc
@@ -131,10 +131,7 @@ if (!toolkit_name) return E_INVALIDARG; - // This is hard-coded; all products based on the Chromium engine - // will have the same toolkit name, so that assistive technology can - // detect any Chrome-based product. - *toolkit_name = SysAllocString(L"Chrome"); + *toolkit_name = SysAllocString(FRAMEWORK_ID); DCHECK(*toolkit_name); return *toolkit_name ? S_OK : E_FAIL; }
diff --git a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc index bdceb68b..59afe8c 100644 --- a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc +++ b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
@@ -1914,7 +1914,20 @@ RunHtmlTest(FILE_PATH_LITERAL("table-spans.html")); } +IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, + AccessibilityTableHeadersEmptyFirstCell) { + RunHtmlTest(FILE_PATH_LITERAL("table-headers-empty-first-cell.html")); +} +IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, + AccessibilityTableHeadersOnAllSides) { + RunHtmlTest(FILE_PATH_LITERAL("table-headers-on-all-sides.html")); +} + +IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, + AccessibilityTableMultipleRowAndColumnHeaders) { + RunHtmlTest(FILE_PATH_LITERAL("table-multiple-row-and-column-headers.html")); +} IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityTextarea) { RunHtmlTest(FILE_PATH_LITERAL("textarea.html"));
diff --git a/content/browser/dom_storage/session_storage_context_mojo.cc b/content/browser/dom_storage/session_storage_context_mojo.cc index 4e1fdfa..4480c078 100644 --- a/content/browser/dom_storage/session_storage_context_mojo.cc +++ b/content/browser/dom_storage/session_storage_context_mojo.cc
@@ -12,7 +12,6 @@ #include "base/barrier_closure.h" #include "base/bind.h" #include "base/bind_helpers.h" -#include "base/debug/stack_trace.h" #include "base/memory/ptr_util.h" #include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_macros.h"
diff --git a/content/browser/frame_host/cross_process_frame_connector.cc b/content/browser/frame_host/cross_process_frame_connector.cc index 1a47982..3d6b0e52 100644 --- a/content/browser/frame_host/cross_process_frame_connector.cc +++ b/content/browser/frame_host/cross_process_frame_connector.cc
@@ -241,8 +241,7 @@ const gfx::PointF& point, RenderWidgetHostViewBase* target_view, const viz::SurfaceId& local_surface_id, - gfx::PointF* transformed_point, - viz::EventSource source) { + gfx::PointF* transformed_point) { RenderWidgetHostViewBase* root_view = GetRootRenderWidgetHostView(); if (!root_view) return false; @@ -252,14 +251,14 @@ // be siblings). To account for this, the point is first transformed into the // root coordinate space and then the root is asked to perform the conversion. if (!root_view->TransformPointToLocalCoordSpace(point, local_surface_id, - transformed_point, source)) + transformed_point)) return false; if (target_view == root_view) return true; return root_view->TransformPointToCoordSpaceForView( - *transformed_point, target_view, transformed_point, source); + *transformed_point, target_view, transformed_point); } void CrossProcessFrameConnector::ForwardAckedTouchpadZoomEvent(
diff --git a/content/browser/frame_host/cross_process_frame_connector.h b/content/browser/frame_host/cross_process_frame_connector.h index ae968b8..5b04cf9f 100644 --- a/content/browser/frame_host/cross_process_frame_connector.h +++ b/content/browser/frame_host/cross_process_frame_connector.h
@@ -95,8 +95,7 @@ const gfx::PointF& point, RenderWidgetHostViewBase* target_view, const viz::SurfaceId& local_surface_id, - gfx::PointF* transformed_point, - viz::EventSource source = viz::EventSource::ANY) override; + gfx::PointF* transformed_point) override; void ForwardAckedTouchpadZoomEvent(const blink::WebGestureEvent& event, InputEventAckState ack_result) override; bool BubbleScrollEvent(const blink::WebGestureEvent& event) override;
diff --git a/content/browser/media/audio_stream_monitor_unittest.cc b/content/browser/media/audio_stream_monitor_unittest.cc index ffdea7d..ed9ac83 100644 --- a/content/browser/media/audio_stream_monitor_unittest.cc +++ b/content/browser/media/audio_stream_monitor_unittest.cc
@@ -10,7 +10,6 @@ #include "base/bind.h" #include "base/bind_helpers.h" -#include "base/debug/stack_trace.h" #include "base/macros.h" #include "base/test/simple_test_tick_clock.h" #include "content/browser/web_contents/web_contents_impl.h"
diff --git a/content/browser/net/browser_online_state_observer.cc b/content/browser/net/browser_online_state_observer.cc index a2bbdfe8..78d48be 100644 --- a/content/browser/net/browser_online_state_observer.cc +++ b/content/browser/net/browser_online_state_observer.cc
@@ -26,8 +26,12 @@ net::NetworkChangeNotifier::ConnectionType type) { for (RenderProcessHost::iterator it(RenderProcessHost::AllHostsIterator()); !it.IsAtEnd(); it.Advance()) { - it.GetCurrentValue()->GetRendererInterface()->OnNetworkConnectionChanged( - type, max_bandwidth_mbps); + // TODO(https://crbug.com/813045): Remove this check once we have a better + // way of iterating the hosts. + if (it.GetCurrentValue()->IsInitializedAndNotDead()) { + it.GetCurrentValue()->GetRendererInterface()->OnNetworkConnectionChanged( + type, max_bandwidth_mbps); + } } }
diff --git a/content/browser/pointer_lock_browsertest.cc b/content/browser/pointer_lock_browsertest.cc index 05b56a72..6f21c02 100644 --- a/content/browser/pointer_lock_browsertest.cc +++ b/content/browser/pointer_lock_browsertest.cc
@@ -208,8 +208,7 @@ gfx::PointF transformed_point; root_view->TransformPointToCoordSpaceForView(gfx::PointF(0, 0), child_view, - &transformed_point, - viz::EventSource::MOUSE); + &transformed_point); mouse_event.SetPositionInWidget(-transformed_point.x() + 14, -transformed_point.y() + 15); @@ -443,8 +442,7 @@ gfx::PointF transformed_point; root_view->TransformPointToCoordSpaceForView(gfx::PointF(0, 0), child_view, - &transformed_point, - viz::EventSource::MOUSE); + &transformed_point); wheel_event.SetPositionInWidget(-transformed_point.x() + 14, -transformed_point.y() + 15);
diff --git a/content/browser/renderer_host/dwrite_font_lookup_table_builder_win.cc b/content/browser/renderer_host/dwrite_font_lookup_table_builder_win.cc index b96565d..ee4ae53 100644 --- a/content/browser/renderer_host/dwrite_font_lookup_table_builder_win.cc +++ b/content/browser/renderer_host/dwrite_font_lookup_table_builder_win.cc
@@ -150,7 +150,7 @@ } bool DWriteFontLookupTableBuilder::EnsureFontUniqueNameTable() { - TRACE_EVENT0("dwrite", + TRACE_EVENT0("dwrite,fonts", "DWriteFontLookupTableBuilder::EnsureFontUniqueNameTable"); DCHECK(base::FeatureList::IsEnabled(features::kFontSrcLocalMatching)); base::ScopedAllowBaseSyncPrimitives allow_base_sync_primitives; @@ -176,7 +176,7 @@ } void DWriteFontLookupTableBuilder::BuildFontUniqueNameTable() { - TRACE_EVENT0("dwrite", + TRACE_EVENT0("dwrite,fonts", "DWriteFontLookupTableBuilder::BuildFontUniqueNameTable"); // The table must only be built once. DCHECK(!font_table_built_.IsSignaled()); @@ -232,7 +232,7 @@ base::TimeTicks start_time, SlowDownMode slow_down_mode_for_testing, base::WaitableEvent* hang_event_for_testing) { - TRACE_EVENT0("dwrite", + TRACE_EVENT0("dwrite,fonts", "DWriteFontLookupTableBuilder::ExtractPathAndNamesFromFamily"); static base::NoDestructor<base::string16> windows_fonts_path( @@ -345,7 +345,7 @@ void DWriteFontLookupTableBuilder::AppendFamilyResultAndFinalizeIfNeeded( const FamilyResult& family_result) { TRACE_EVENT0( - "dwrite", + "dwrite,fonts", "DWriteFontLookupTableBuilder::AppendFamilyResultAndFinalizeIfNeeded"); outstanding_family_results_--; @@ -378,7 +378,8 @@ } void DWriteFontLookupTableBuilder::FinalizeFontTable() { - TRACE_EVENT0("dwrite", "DWriteFontLookupTableBuilder::FinalizeFontTable"); + TRACE_EVENT0("dwrite,fonts", + "DWriteFontLookupTableBuilder::FinalizeFontTable"); DCHECK(!font_table_built_.IsSignaled()); ScopedAutoSignal auto_signal(&font_table_built_);
diff --git a/content/browser/renderer_host/dwrite_font_proxy_impl_win.cc b/content/browser/renderer_host/dwrite_font_proxy_impl_win.cc index 3583748..286cd18 100644 --- a/content/browser/renderer_host/dwrite_font_proxy_impl_win.cc +++ b/content/browser/renderer_host/dwrite_font_proxy_impl_win.cc
@@ -134,7 +134,7 @@ void DWriteFontProxyImpl::FindFamily(const base::string16& family_name, FindFamilyCallback callback) { InitializeDirectWrite(); - TRACE_EVENT0("dwrite", "FontProxyHost::OnFindFamily"); + TRACE_EVENT0("dwrite,fonts", "FontProxyHost::OnFindFamily"); UINT32 family_index = UINT32_MAX; if (collection_) { BOOL exists = FALSE; @@ -151,20 +151,20 @@ void DWriteFontProxyImpl::GetFamilyCount(GetFamilyCountCallback callback) { InitializeDirectWrite(); - TRACE_EVENT0("dwrite", "FontProxyHost::OnGetFamilyCount"); + TRACE_EVENT0("dwrite,fonts", "FontProxyHost::OnGetFamilyCount"); std::move(callback).Run(collection_ ? collection_->GetFontFamilyCount() : 0); } void DWriteFontProxyImpl::GetFamilyNames(UINT32 family_index, GetFamilyNamesCallback callback) { InitializeDirectWrite(); - TRACE_EVENT0("dwrite", "FontProxyHost::OnGetFamilyNames"); + TRACE_EVENT0("dwrite,fonts", "FontProxyHost::OnGetFamilyNames"); callback = mojo::WrapCallbackWithDefaultInvokeIfNotRun( std::move(callback), std::vector<blink::mojom::DWriteStringPairPtr>()); if (!collection_) return; - TRACE_EVENT0("dwrite", "FontProxyHost::DoGetFamilyNames"); + TRACE_EVENT0("dwrite,fonts", "FontProxyHost::DoGetFamilyNames"); mswr::ComPtr<IDWriteFontFamily> family; HRESULT hr = collection_->GetFontFamily(family_index, &family); @@ -219,7 +219,7 @@ void DWriteFontProxyImpl::GetFontFiles(uint32_t family_index, GetFontFilesCallback callback) { InitializeDirectWrite(); - TRACE_EVENT0("dwrite", "FontProxyHost::OnGetFontFiles"); + TRACE_EVENT0("dwrite,fonts", "FontProxyHost::OnGetFontFiles"); callback = mojo::WrapCallbackWithDefaultInvokeIfNotRun( std::move(callback), std::vector<base::FilePath>(), std::vector<base::File>());
diff --git a/content/browser/renderer_host/frame_connector_delegate.cc b/content/browser/renderer_host/frame_connector_delegate.cc index 4156111..39f910a 100644 --- a/content/browser/renderer_host/frame_connector_delegate.cc +++ b/content/browser/renderer_host/frame_connector_delegate.cc
@@ -71,8 +71,7 @@ const gfx::PointF& point, RenderWidgetHostViewBase* target_view, const viz::SurfaceId& local_surface_id, - gfx::PointF* transformed_point, - viz::EventSource source) { + gfx::PointF* transformed_point) { return false; }
diff --git a/content/browser/renderer_host/frame_connector_delegate.h b/content/browser/renderer_host/frame_connector_delegate.h index 34065ed..a7815b1 100644 --- a/content/browser/renderer_host/frame_connector_delegate.h +++ b/content/browser/renderer_host/frame_connector_delegate.h
@@ -144,8 +144,7 @@ const gfx::PointF& point, RenderWidgetHostViewBase* target_view, const viz::SurfaceId& local_surface_id, - gfx::PointF* transformed_point, - viz::EventSource source = viz::EventSource::ANY); + gfx::PointF* transformed_point); // Pass acked touchpad pinch or double tap gesture events to the root view // for processing.
diff --git a/content/browser/renderer_host/input/mouse_wheel_phase_handler.h b/content/browser/renderer_host/input/mouse_wheel_phase_handler.h index fc252b6..b0dfd84 100644 --- a/content/browser/renderer_host/input/mouse_wheel_phase_handler.h +++ b/content/browser/renderer_host/input/mouse_wheel_phase_handler.h
@@ -7,6 +7,7 @@ #include "base/timer/timer.h" #include "content/browser/renderer_host/render_widget_host_delegate.h" +#include "content/common/content_export.h" #include "content/public/common/input_event_ack_state.h" #include "third_party/blink/public/platform/web_mouse_wheel_event.h" @@ -55,7 +56,7 @@ // The MouseWheelPhaseHandler is responsible for adding the proper phase to // wheel events. Phase information is necessary for wheel scrolling since it // shows the start and end of a scrolling sequence. -class MouseWheelPhaseHandler { +class CONTENT_EXPORT MouseWheelPhaseHandler { public: MouseWheelPhaseHandler(RenderWidgetHostViewBase* const host_view); ~MouseWheelPhaseHandler() {}
diff --git a/content/browser/renderer_host/input/synthetic_gesture_target_aura.cc b/content/browser/renderer_host/input/synthetic_gesture_target_aura.cc index 45cb261..b4a0b81 100644 --- a/content/browser/renderer_host/input/synthetic_gesture_target_aura.cc +++ b/content/browser/renderer_host/input/synthetic_gesture_target_aura.cc
@@ -99,16 +99,18 @@ if (web_wheel.scroll_by_page) modifiers |= ui::EF_SCROLL_BY_PAGE; + gfx::PointF location(web_wheel.PositionInWidget().x, + web_wheel.PositionInWidget().y); ui::MouseWheelEvent wheel_event( - gfx::Vector2d(web_wheel.delta_x, web_wheel.delta_y), gfx::Point(), - gfx::Point(), timestamp, modifiers, ui::EF_NONE); - gfx::PointF location(web_wheel.PositionInWidget().x * device_scale_factor_, - web_wheel.PositionInWidget().y * device_scale_factor_); - wheel_event.set_location_f(location); - wheel_event.set_root_location_f(location); + gfx::Vector2d(web_wheel.delta_x, web_wheel.delta_y), location, location, + timestamp, modifiers, ui::EF_NONE); aura::Window* window = GetWindow(); wheel_event.ConvertLocationToTarget(window, window->GetRootWindow()); + wheel_event.set_location_f( + gfx::ScalePoint(wheel_event.location_f(), device_scale_factor_)); + wheel_event.set_root_location_f( + gfx::ScalePoint(wheel_event.root_location_f(), device_scale_factor_)); ui::EventDispatchDetails details = event_injector_.Inject(window->GetHost(), &wheel_event); if (details.dispatcher_destroyed) @@ -130,13 +132,15 @@ if (event_type == ui::ET_GESTURE_PINCH_UPDATE) pinch_details.set_scale(web_gesture.data.pinch_update.scale); - ui::GestureEvent pinch_event( - web_gesture.PositionInWidget().x * device_scale_factor_, - web_gesture.PositionInWidget().y * device_scale_factor_, flags, - ui::EventTimeForNow(), pinch_details); + ui::GestureEvent pinch_event(web_gesture.PositionInWidget().x, + web_gesture.PositionInWidget().y, flags, + ui::EventTimeForNow(), pinch_details); pinch_event.ConvertLocationToTarget(window, window->GetRootWindow()); - + pinch_event.set_location_f( + gfx::ScalePoint(pinch_event.location_f(), device_scale_factor_)); + pinch_event.set_root_location_f( + gfx::ScalePoint(pinch_event.root_location_f(), device_scale_factor_)); event_injector_.Inject(window->GetHost(), &pinch_event); return; } @@ -145,15 +149,18 @@ web_gesture.GetType() == blink::WebInputEvent::kGestureFlingStart ? ui::EventMomentumPhase::BEGAN : ui::EventMomentumPhase::END; - gfx::PointF location(web_gesture.PositionInWidget().x * device_scale_factor_, - web_gesture.PositionInWidget().y * device_scale_factor_); - ui::ScrollEvent scroll_event(event_type, gfx::Point(), ui::EventTimeForNow(), - flags, web_gesture.data.fling_start.velocity_x, + gfx::PointF location(web_gesture.PositionInWidget().x, + web_gesture.PositionInWidget().y); + ui::ScrollEvent scroll_event(event_type, location, location, + ui::EventTimeForNow(), flags, + web_gesture.data.fling_start.velocity_x, web_gesture.data.fling_start.velocity_y, 0, 0, 2, momentum_phase, ui::ScrollEventPhase::kNone); - scroll_event.set_location_f(location); - scroll_event.set_root_location_f(location); scroll_event.ConvertLocationToTarget(window, window->GetRootWindow()); + scroll_event.set_location_f( + gfx::ScalePoint(scroll_event.location_f(), device_scale_factor_)); + scroll_event.set_root_location_f( + gfx::ScalePoint(scroll_event.root_location_f(), device_scale_factor_)); event_injector_.Inject(window->GetHost(), &scroll_event); } @@ -171,17 +178,18 @@ changed_button_flags = WebEventButtonToUIEventButtonFlags(web_mouse_event.button); } - ui::MouseEvent mouse_event(event_type, gfx::Point(), gfx::Point(), + gfx::PointF location(web_mouse_event.PositionInWidget().x, + web_mouse_event.PositionInWidget().y); + ui::MouseEvent mouse_event(event_type, location, location, ui::EventTimeForNow(), flags, changed_button_flags, pointer_details); - gfx::PointF location( - web_mouse_event.PositionInWidget().x * device_scale_factor_, - web_mouse_event.PositionInWidget().y * device_scale_factor_); - mouse_event.set_location_f(location); - mouse_event.set_root_location_f(location); aura::Window* window = GetWindow(); mouse_event.ConvertLocationToTarget(window, window->GetRootWindow()); + mouse_event.set_location_f( + gfx::ScalePoint(mouse_event.location_f(), device_scale_factor_)); + mouse_event.set_root_location_f( + gfx::ScalePoint(mouse_event.root_location_f(), device_scale_factor_)); mouse_event.SetClickCount(web_mouse_event.click_count); ui::EventDispatchDetails details = event_injector_.Inject(window->GetHost(), &mouse_event);
diff --git a/content/browser/renderer_host/media/ref_counted_video_capture_factory.cc b/content/browser/renderer_host/media/ref_counted_video_capture_factory.cc deleted file mode 100644 index 0f56ad4d..0000000 --- a/content/browser/renderer_host/media/ref_counted_video_capture_factory.cc +++ /dev/null
@@ -1,35 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/browser/renderer_host/media/ref_counted_video_capture_factory.h" - -namespace content { - -RefCountedVideoCaptureFactory::RefCountedVideoCaptureFactory( - video_capture::mojom::DeviceFactoryPtr device_factory, - video_capture::mojom::DeviceFactoryProviderPtr device_factory_provider, - base::OnceClosure destruction_cb) - : device_factory_(std::move(device_factory)), - device_factory_provider_(std::move(device_factory_provider)), - destruction_cb_(std::move(destruction_cb)), - weak_ptr_factory_(this) {} - -RefCountedVideoCaptureFactory::~RefCountedVideoCaptureFactory() { - std::move(destruction_cb_).Run(); -} - -base::WeakPtr<RefCountedVideoCaptureFactory> -RefCountedVideoCaptureFactory::GetWeakPtr() { - return weak_ptr_factory_.GetWeakPtr(); -} - -void RefCountedVideoCaptureFactory::ShutdownServiceAsap() { - device_factory_provider_->ShutdownServiceAsap(); -} - -void RefCountedVideoCaptureFactory::ReleaseFactoryForTesting() { - device_factory_.reset(); -} - -} // namespace content
diff --git a/content/browser/renderer_host/media/ref_counted_video_capture_factory.h b/content/browser/renderer_host/media/ref_counted_video_capture_factory.h deleted file mode 100644 index 670e6cb..0000000 --- a/content/browser/renderer_host/media/ref_counted_video_capture_factory.h +++ /dev/null
@@ -1,52 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CONTENT_BROWSER_RENDERER_HOST_MEDIA_REF_COUNTED_VIDEO_CAPTURE_FACTORY_H_ -#define CONTENT_BROWSER_RENDERER_HOST_MEDIA_REF_COUNTED_VIDEO_CAPTURE_FACTORY_H_ - -#include "base/memory/ref_counted.h" -#include "content/common/content_export.h" -#include "services/video_capture/public/mojom/device_factory.mojom.h" -#include "services/video_capture/public/mojom/device_factory_provider.mojom.h" - -namespace content { - -// Enables ref-counted shared ownership of a -// video_capture::mojom::DeviceFactoryPtr. -// Since instances of this class do not guarantee that the connection stays open -// for its entire lifetime, clients must verify that the connection is bound -// before using it. -class CONTENT_EXPORT RefCountedVideoCaptureFactory - : public base::RefCounted<RefCountedVideoCaptureFactory> { - public: - RefCountedVideoCaptureFactory( - video_capture::mojom::DeviceFactoryPtr device_factory, - video_capture::mojom::DeviceFactoryProviderPtr device_factory_provider, - base::OnceClosure destruction_cb); - - base::WeakPtr<RefCountedVideoCaptureFactory> GetWeakPtr(); - - const video_capture::mojom::DeviceFactoryPtr& device_factory() { - return device_factory_; - } - - void ShutdownServiceAsap(); - - void ReleaseFactoryForTesting(); - - private: - friend class base::RefCounted<RefCountedVideoCaptureFactory>; - ~RefCountedVideoCaptureFactory(); - - video_capture::mojom::DeviceFactoryPtr device_factory_; - video_capture::mojom::DeviceFactoryProviderPtr device_factory_provider_; - base::OnceClosure destruction_cb_; - base::WeakPtrFactory<RefCountedVideoCaptureFactory> weak_ptr_factory_; - - DISALLOW_COPY_AND_ASSIGN(RefCountedVideoCaptureFactory); -}; - -} // namespace content - -#endif // CONTENT_BROWSER_RENDERER_HOST_MEDIA_REF_COUNTED_VIDEO_CAPTURE_FACTORY_H_
diff --git a/content/browser/renderer_host/media/ref_counted_video_source_provider.cc b/content/browser/renderer_host/media/ref_counted_video_source_provider.cc new file mode 100644 index 0000000..4414c7c --- /dev/null +++ b/content/browser/renderer_host/media/ref_counted_video_source_provider.cc
@@ -0,0 +1,35 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "content/browser/renderer_host/media/ref_counted_video_source_provider.h" + +namespace content { + +RefCountedVideoSourceProvider::RefCountedVideoSourceProvider( + video_capture::mojom::VideoSourceProviderPtr source_provider, + video_capture::mojom::DeviceFactoryProviderPtr device_factory_provider, + base::OnceClosure destruction_cb) + : source_provider_(std::move(source_provider)), + device_factory_provider_(std::move(device_factory_provider)), + destruction_cb_(std::move(destruction_cb)), + weak_ptr_factory_(this) {} + +RefCountedVideoSourceProvider::~RefCountedVideoSourceProvider() { + std::move(destruction_cb_).Run(); +} + +base::WeakPtr<RefCountedVideoSourceProvider> +RefCountedVideoSourceProvider::GetWeakPtr() { + return weak_ptr_factory_.GetWeakPtr(); +} + +void RefCountedVideoSourceProvider::ShutdownServiceAsap() { + device_factory_provider_->ShutdownServiceAsap(); +} + +void RefCountedVideoSourceProvider::ReleaseProviderForTesting() { + source_provider_.reset(); +} + +} // namespace content
diff --git a/content/browser/renderer_host/media/ref_counted_video_source_provider.h b/content/browser/renderer_host/media/ref_counted_video_source_provider.h new file mode 100644 index 0000000..cb6320c --- /dev/null +++ b/content/browser/renderer_host/media/ref_counted_video_source_provider.h
@@ -0,0 +1,51 @@ +// Copyright 2017 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_BROWSER_RENDERER_HOST_MEDIA_REF_COUNTED_VIDEO_SOURCE_PROVIDER_H_ +#define CONTENT_BROWSER_RENDERER_HOST_MEDIA_REF_COUNTED_VIDEO_SOURCE_PROVIDER_H_ + +#include "base/memory/ref_counted.h" +#include "content/common/content_export.h" +#include "services/video_capture/public/mojom/device_factory_provider.mojom.h" +#include "services/video_capture/public/mojom/video_source_provider.mojom.h" + +namespace content { + +// Enables ref-counted shared ownership of a +// video_capture::mojom::DeviceFactoryPtr. +// Since instances of this class do not guarantee that the connection stays open +// for its entire lifetime, clients must verify that the connection is bound +// before using it. +class CONTENT_EXPORT RefCountedVideoSourceProvider + : public base::RefCounted<RefCountedVideoSourceProvider> { + public: + RefCountedVideoSourceProvider( + video_capture::mojom::VideoSourceProviderPtr source_provider, + video_capture::mojom::DeviceFactoryProviderPtr device_factory_provider, + base::OnceClosure destruction_cb); + + base::WeakPtr<RefCountedVideoSourceProvider> GetWeakPtr(); + + const video_capture::mojom::VideoSourceProviderPtr& source_provider() { + return source_provider_; + } + + void ShutdownServiceAsap(); + void ReleaseProviderForTesting(); + + private: + friend class base::RefCounted<RefCountedVideoSourceProvider>; + ~RefCountedVideoSourceProvider(); + + video_capture::mojom::VideoSourceProviderPtr source_provider_; + video_capture::mojom::DeviceFactoryProviderPtr device_factory_provider_; + base::OnceClosure destruction_cb_; + base::WeakPtrFactory<RefCountedVideoSourceProvider> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(RefCountedVideoSourceProvider); +}; + +} // namespace content + +#endif // CONTENT_BROWSER_RENDERER_HOST_MEDIA_REF_COUNTED_VIDEO_SOURCE_PROVIDER_H_
diff --git a/content/browser/renderer_host/media/service_launched_video_capture_device.cc b/content/browser/renderer_host/media/service_launched_video_capture_device.cc index 947804866..c52a2c9 100644 --- a/content/browser/renderer_host/media/service_launched_video_capture_device.cc +++ b/content/browser/renderer_host/media/service_launched_video_capture_device.cc
@@ -3,19 +3,29 @@ // found in the LICENSE file. #include "content/browser/renderer_host/media/service_launched_video_capture_device.h" + #include "base/bind.h" +#include "base/bind_helpers.h" namespace content { ServiceLaunchedVideoCaptureDevice::ServiceLaunchedVideoCaptureDevice( - video_capture::mojom::DevicePtr device, + video_capture::mojom::VideoSourcePtr source, + video_capture::mojom::PushVideoStreamSubscriptionPtr subscription, base::OnceClosure connection_lost_cb) - : device_(std::move(device)), + : source_(std::move(source)), + subscription_(std::move(subscription)), connection_lost_cb_(std::move(connection_lost_cb)) { - // Unretained |this| is safe, because |this| owns |device_|. - device_.set_connection_error_handler(base::BindOnce( - &ServiceLaunchedVideoCaptureDevice::OnLostConnectionToDevice, - base::Unretained(this))); + // Unretained |this| is safe, because |this| owns |source_|. + source_.set_connection_error_handler( + base::BindOnce(&ServiceLaunchedVideoCaptureDevice:: + OnLostConnectionToSourceOrSubscription, + base::Unretained(this))); + // Unretained |this| is safe, because |this| owns |subscription_|. + subscription_.set_connection_error_handler( + base::BindOnce(&ServiceLaunchedVideoCaptureDevice:: + OnLostConnectionToSourceOrSubscription, + base::Unretained(this))); } ServiceLaunchedVideoCaptureDevice::~ServiceLaunchedVideoCaptureDevice() { @@ -25,7 +35,7 @@ void ServiceLaunchedVideoCaptureDevice::GetPhotoState( media::VideoCaptureDevice::GetPhotoStateCallback callback) const { DCHECK(sequence_checker_.CalledOnValidSequence()); - device_->GetPhotoState(base::BindOnce( + subscription_->GetPhotoState(base::BindOnce( &ServiceLaunchedVideoCaptureDevice::OnGetPhotoStateResponse, base::Unretained(this), std::move(callback))); } @@ -34,7 +44,7 @@ media::mojom::PhotoSettingsPtr settings, media::VideoCaptureDevice::SetPhotoOptionsCallback callback) { DCHECK(sequence_checker_.CalledOnValidSequence()); - device_->SetPhotoOptions( + subscription_->SetPhotoOptions( std::move(settings), base::BindOnce( &ServiceLaunchedVideoCaptureDevice::OnSetPhotoOptionsResponse, @@ -47,23 +57,25 @@ TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("video_and_image_capture"), "ServiceLaunchedVideoCaptureDevice::TakePhoto", TRACE_EVENT_SCOPE_PROCESS); - device_->TakePhoto( + subscription_->TakePhoto( base::BindOnce(&ServiceLaunchedVideoCaptureDevice::OnTakePhotoResponse, base::Unretained(this), std::move(callback))); } void ServiceLaunchedVideoCaptureDevice::MaybeSuspendDevice() { DCHECK(sequence_checker_.CalledOnValidSequence()); - device_->MaybeSuspend(); + subscription_->Suspend(base::DoNothing()); } void ServiceLaunchedVideoCaptureDevice::ResumeDevice() { DCHECK(sequence_checker_.CalledOnValidSequence()); - device_->Resume(); + subscription_->Resume(); } void ServiceLaunchedVideoCaptureDevice::RequestRefreshFrame() { - // Ignore this call. + DCHECK(sequence_checker_.CalledOnValidSequence()); + // Nothing to do here. The video capture service does not support refresh + // frames. } void ServiceLaunchedVideoCaptureDevice::SetDesktopCaptureWindowIdAsync( @@ -78,11 +90,16 @@ void ServiceLaunchedVideoCaptureDevice::OnUtilizationReport( int frame_feedback_id, double utilization) { - // Ignore this call. + DCHECK(sequence_checker_.CalledOnValidSequence()); + // Nothing to do here. The video capture service does not support utilization + // reporting. } -void ServiceLaunchedVideoCaptureDevice::OnLostConnectionToDevice() { +void ServiceLaunchedVideoCaptureDevice:: + OnLostConnectionToSourceOrSubscription() { DCHECK(sequence_checker_.CalledOnValidSequence()); + source_.reset(); + subscription_.reset(); base::ResetAndReturn(&connection_lost_cb_).Run(); }
diff --git a/content/browser/renderer_host/media/service_launched_video_capture_device.h b/content/browser/renderer_host/media/service_launched_video_capture_device.h index 86764d76..b36917f 100644 --- a/content/browser/renderer_host/media/service_launched_video_capture_device.h +++ b/content/browser/renderer_host/media/service_launched_video_capture_device.h
@@ -7,7 +7,7 @@ #include "content/browser/renderer_host/media/video_capture_provider.h" #include "content/public/browser/video_capture_device_launcher.h" -#include "services/video_capture/public/mojom/device.mojom.h" +#include "services/video_capture/public/mojom/video_source.mojom.h" namespace content { @@ -15,8 +15,10 @@ // service. class ServiceLaunchedVideoCaptureDevice : public LaunchedVideoCaptureDevice { public: - ServiceLaunchedVideoCaptureDevice(video_capture::mojom::DevicePtr device, - base::OnceClosure connection_lost_cb); + ServiceLaunchedVideoCaptureDevice( + video_capture::mojom::VideoSourcePtr source, + video_capture::mojom::PushVideoStreamSubscriptionPtr subscription, + base::OnceClosure connection_lost_cb); ~ServiceLaunchedVideoCaptureDevice() override; // LaunchedVideoCaptureDevice implementation. @@ -37,7 +39,7 @@ void OnUtilizationReport(int frame_feedback_id, double utilization) override; private: - void OnLostConnectionToDevice(); + void OnLostConnectionToSourceOrSubscription(); void OnGetPhotoStateResponse( media::VideoCaptureDevice::GetPhotoStateCallback callback, media::mojom::PhotoStatePtr capabilities) const; @@ -48,7 +50,8 @@ media::VideoCaptureDevice::TakePhotoCallback callback, media::mojom::BlobPtr blob); - video_capture::mojom::DevicePtr device_; + video_capture::mojom::VideoSourcePtr source_; + video_capture::mojom::PushVideoStreamSubscriptionPtr subscription_; base::OnceClosure connection_lost_cb_; base::SequenceChecker sequence_checker_; };
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 a37f0b2..87aca61 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
@@ -20,37 +20,26 @@ namespace { void ConcludeLaunchDeviceWithSuccess( - const media::VideoCaptureParams& params, - video_capture::mojom::DevicePtr device, - base::WeakPtr<media::VideoFrameReceiver> receiver, + video_capture::mojom::VideoSourcePtr source, + video_capture::mojom::PushVideoStreamSubscriptionPtr subscription, base::OnceClosure connection_lost_cb, VideoCaptureDeviceLauncher::Callbacks* callbacks, base::OnceClosure done_cb) { - auto receiver_adapter = - std::make_unique<video_capture::ReceiverMediaToMojoAdapter>( - std::make_unique<media::VideoFrameReceiverOnTaskRunner>( - std::move(receiver), base::CreateSingleThreadTaskRunnerWithTraits( - {BrowserThread::IO}))); - video_capture::mojom::ReceiverPtr receiver_proxy; - mojo::MakeStrongBinding<video_capture::mojom::Receiver>( - std::move(receiver_adapter), mojo::MakeRequest(&receiver_proxy)); - media::VideoCaptureParams new_params = params; - new_params.power_line_frequency = - media::VideoCaptureDevice::GetPowerLineFrequency(params); - device->Start(new_params, std::move(receiver_proxy)); + subscription->Activate(); callbacks->OnDeviceLaunched( std::make_unique<ServiceLaunchedVideoCaptureDevice>( - std::move(device), std::move(connection_lost_cb))); + std::move(source), std::move(subscription), + std::move(connection_lost_cb))); base::ResetAndReturn(&done_cb).Run(); } void ConcludeLaunchDeviceWithFailure( bool abort_requested, media::VideoCaptureError error, - scoped_refptr<RefCountedVideoCaptureFactory> device_factory, + scoped_refptr<RefCountedVideoSourceProvider> service_connection, VideoCaptureDeviceLauncher::Callbacks* callbacks, base::OnceClosure done_cb) { - device_factory.reset(); + service_connection.reset(); if (abort_requested) callbacks->OnDeviceLaunchAborted(); else @@ -61,8 +50,8 @@ } // anonymous namespace ServiceVideoCaptureDeviceLauncher::ServiceVideoCaptureDeviceLauncher( - ConnectToDeviceFactoryCB connect_to_device_factory_cb) - : connect_to_device_factory_cb_(std::move(connect_to_device_factory_cb)), + ConnectToDeviceFactoryCB connect_to_source_provider_cb) + : connect_to_source_provider_cb_(std::move(connect_to_source_provider_cb)), state_(State::READY_TO_LAUNCH), callbacks_(nullptr) {} @@ -88,16 +77,14 @@ return; } - connect_to_device_factory_cb_.Run(&device_factory_); - if (!device_factory_->device_factory().is_bound()) { - // This can happen when the ServiceVideoCaptureProvider owning - // |device_factory_| loses connection to the service process and resets - // |device_factory_|. + connect_to_source_provider_cb_.Run(&service_connection_); + if (!service_connection_->source_provider().is_bound()) { + // This can happen when the connection to the service was lost. ConcludeLaunchDeviceWithFailure( false, media::VideoCaptureError:: kServiceDeviceLauncherLostConnectionToDeviceFactoryDuringDeviceStart, - std::move(device_factory_), callbacks, std::move(done_cb)); + std::move(service_connection_), callbacks, std::move(done_cb)); return; } @@ -105,32 +92,62 @@ std::ostringstream string_stream; string_stream << "ServiceVideoCaptureDeviceLauncher::LaunchDeviceAsync: Asking " - "video capture service to create device for device_id = " + "video capture service to create source for device_id = " << device_id; receiver->OnLog(string_stream.str()); } - video_capture::mojom::DevicePtr device; - auto device_request = mojo::MakeRequest(&device); // Ownership of |done_cb| is moved to |this|. It is not sufficient to attach - // it to the callback passed to |device_factory_->CreateDevice()|, because - // |device_factory_| may get torn down before the callback is invoked. + // it to the callback passed to CreatePushSubscription(), because the + // connection to the service may get torn down before |callbacks| are + // invoked. done_cb_ = std::move(done_cb); callbacks_ = callbacks; + video_capture::mojom::VideoSourcePtr source; + service_connection_->source_provider()->GetVideoSource( + device_id, mojo::MakeRequest(&source)); + + auto receiver_adapter = + std::make_unique<video_capture::ReceiverMediaToMojoAdapter>( + std::make_unique<media::VideoFrameReceiverOnTaskRunner>( + std::move(receiver), base::CreateSingleThreadTaskRunnerWithTraits( + {BrowserThread::IO}))); + video_capture::mojom::ReceiverPtr receiver_proxy; + mojo::MakeStrongBinding<video_capture::mojom::Receiver>( + std::move(receiver_adapter), mojo::MakeRequest(&receiver_proxy)); + + video_capture::mojom::PushVideoStreamSubscriptionPtr subscription; + // Create message pipe so that we can subsequently call + // subscription.set_connection_error_handler(). + auto subscription_request = mojo::MakeRequest(&subscription); // Use of Unretained(this) is safe, because |done_cb_| guarantees that |this| // stays alive. - device.set_connection_error_handler( + subscription.set_connection_error_handler( base::BindOnce(&ServiceVideoCaptureDeviceLauncher:: OnConnectionLostWhileWaitingForCallback, base::Unretained(this))); - device_factory_->device_factory()->CreateDevice( - device_id, std::move(device_request), + + // TODO(crbug.com/925083) + media::VideoCaptureParams new_params = params; + new_params.power_line_frequency = + media::VideoCaptureDevice::GetPowerLineFrequency(params); + + // Note that we set |force_reopen_with_new_settings| to true in order + // to avoid the situation that a requests to open (or reopen) a device + // that has just been closed with different settings ends up getting the old + // settings, because from the perspective of the service, the device was still + // in use. In order to be able to set |force_reopen_with_new_settings|, we + // have to refactor code here and upstream to wait for a callback from the + // service indicating that the device closing is complete. + source->CreatePushSubscription( + std::move(receiver_proxy), new_params, + true /*force_reopen_with_new_settings*/, std::move(subscription_request), base::BindOnce( // Use of Unretained |this| is safe, because |done_cb_| guarantees // that |this| stays alive. - &ServiceVideoCaptureDeviceLauncher::OnCreateDeviceCallback, - base::Unretained(this), params, std::move(device), - std::move(receiver), std::move(connection_lost_cb))); + &ServiceVideoCaptureDeviceLauncher::OnCreatePushSubscriptionCallback, + base::Unretained(this), std::move(source), std::move(subscription), + std::move(connection_lost_cb))); state_ = State::DEVICE_START_IN_PROGRESS; } @@ -140,40 +157,43 @@ state_ = State::DEVICE_START_ABORTING; } -void ServiceVideoCaptureDeviceLauncher::OnCreateDeviceCallback( - const media::VideoCaptureParams& params, - video_capture::mojom::DevicePtr device, - base::WeakPtr<media::VideoFrameReceiver> receiver, +void ServiceVideoCaptureDeviceLauncher::OnCreatePushSubscriptionCallback( + video_capture::mojom::VideoSourcePtr source, + video_capture::mojom::PushVideoStreamSubscriptionPtr subscription, base::OnceClosure connection_lost_cb, - video_capture::mojom::DeviceAccessResultCode result_code) { + video_capture::mojom::CreatePushSubscriptionResultCode result_code, + const media::VideoCaptureParams& params) { DCHECK(sequence_checker_.CalledOnValidSequence()); DCHECK(callbacks_); DCHECK(done_cb_); - device.set_connection_error_handler(base::DoNothing()); + subscription.set_connection_error_handler(base::DoNothing()); const bool abort_requested = (state_ == State::DEVICE_START_ABORTING); state_ = State::READY_TO_LAUNCH; Callbacks* callbacks = callbacks_; callbacks_ = nullptr; switch (result_code) { - case video_capture::mojom::DeviceAccessResultCode::SUCCESS: + case video_capture::mojom::CreatePushSubscriptionResultCode:: + kCreatedWithRequestedSettings: // Fall through. + case video_capture::mojom::CreatePushSubscriptionResultCode:: + kCreatedWithDifferentSettings: if (abort_requested) { - device.reset(); - device_factory_.reset(); + subscription.reset(); + source.reset(); + service_connection_.reset(); callbacks->OnDeviceLaunchAborted(); base::ResetAndReturn(&done_cb_).Run(); return; } ConcludeLaunchDeviceWithSuccess( - params, std::move(device), std::move(receiver), + std::move(source), std::move(subscription), std::move(connection_lost_cb), callbacks, std::move(done_cb_)); return; - case video_capture::mojom::DeviceAccessResultCode::ERROR_DEVICE_NOT_FOUND: - case video_capture::mojom::DeviceAccessResultCode::NOT_INITIALIZED: + case video_capture::mojom::CreatePushSubscriptionResultCode::kFailed: ConcludeLaunchDeviceWithFailure( abort_requested, media::VideoCaptureError:: kServiceDeviceLauncherServiceRespondedWithDeviceNotFound, - std::move(device_factory_), callbacks, std::move(done_cb_)); + std::move(service_connection_), callbacks, std::move(done_cb_)); return; } } @@ -190,7 +210,7 @@ abort_requested, media::VideoCaptureError:: kServiceDeviceLauncherConnectionLostWhileWaitingForCallback, - std::move(device_factory_), callbacks, std::move(done_cb_)); + std::move(service_connection_), callbacks, std::move(done_cb_)); } } // namespace content
diff --git a/content/browser/renderer_host/media/service_video_capture_device_launcher.h b/content/browser/renderer_host/media/service_video_capture_device_launcher.h index afe0b95..2936448 100644 --- a/content/browser/renderer_host/media/service_video_capture_device_launcher.h +++ b/content/browser/renderer_host/media/service_video_capture_device_launcher.h
@@ -5,7 +5,7 @@ #ifndef CONTENT_BROWSER_RENDERER_HOST_MEDIA_SERVICE_VIDEO_CAPTURE_DEVICE_LAUNCHER_H_ #define CONTENT_BROWSER_RENDERER_HOST_MEDIA_SERVICE_VIDEO_CAPTURE_DEVICE_LAUNCHER_H_ -#include "content/browser/renderer_host/media/ref_counted_video_capture_factory.h" +#include "content/browser/renderer_host/media/ref_counted_video_source_provider.h" #include "content/browser/renderer_host/media/video_capture_provider.h" #include "content/public/browser/video_capture_device_launcher.h" #include "services/video_capture/public/mojom/device_factory.mojom.h" @@ -18,12 +18,12 @@ class CONTENT_EXPORT ServiceVideoCaptureDeviceLauncher : public VideoCaptureDeviceLauncher { public: - // Receives an instance via output parameter |factory|. + // Receives an instance via output parameter |out_provider|. using ConnectToDeviceFactoryCB = base::RepeatingCallback<void( - scoped_refptr<RefCountedVideoCaptureFactory>*)>; + scoped_refptr<RefCountedVideoSourceProvider>* out_provider)>; explicit ServiceVideoCaptureDeviceLauncher( - ConnectToDeviceFactoryCB connect_to_device_factory_cb); + ConnectToDeviceFactoryCB connect_to_source_provider_cb); ~ServiceVideoCaptureDeviceLauncher() override; // VideoCaptureDeviceLauncher implementation. @@ -45,17 +45,17 @@ DEVICE_START_ABORTING }; - void OnCreateDeviceCallback( - const media::VideoCaptureParams& params, - video_capture::mojom::DevicePtr device, - base::WeakPtr<media::VideoFrameReceiver> receiver, + void OnCreatePushSubscriptionCallback( + video_capture::mojom::VideoSourcePtr source, + video_capture::mojom::PushVideoStreamSubscriptionPtr subscription, base::OnceClosure connection_lost_cb, - video_capture::mojom::DeviceAccessResultCode result_code); + video_capture::mojom::CreatePushSubscriptionResultCode result_code, + const media::VideoCaptureParams& params); void OnConnectionLostWhileWaitingForCallback(); - ConnectToDeviceFactoryCB connect_to_device_factory_cb_; - scoped_refptr<RefCountedVideoCaptureFactory> device_factory_; + ConnectToDeviceFactoryCB connect_to_source_provider_cb_; + scoped_refptr<RefCountedVideoSourceProvider> service_connection_; State state_; base::SequenceChecker sequence_checker_; base::OnceClosure done_cb_;
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 d7eaf68..e7d641b6 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
@@ -9,17 +9,20 @@ #include "base/run_loop.h" #include "base/test/mock_callback.h" #include "base/threading/thread.h" -#include "content/browser/renderer_host/media/ref_counted_video_capture_factory.h" +#include "content/browser/renderer_host/media/ref_counted_video_source_provider.h" #include "content/browser/renderer_host/media/service_launched_video_capture_device.h" #include "content/public/test/test_browser_thread_bundle.h" #include "mojo/public/cpp/bindings/binding.h" -#include "services/video_capture/public/cpp/mock_device_factory.h" +#include "mojo/public/cpp/bindings/binding_set.h" +#include "services/video_capture/public/cpp/mock_push_subscription.h" +#include "services/video_capture/public/cpp/mock_video_source.h" +#include "services/video_capture/public/cpp/mock_video_source_provider.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +using testing::_; using testing::Invoke; using testing::InvokeWithoutArgs; -using testing::_; namespace content { @@ -46,46 +49,87 @@ ServiceVideoCaptureDeviceLauncherTest() {} ~ServiceVideoCaptureDeviceLauncherTest() override {} + void CloseSourceBinding() { source_binding_.reset(); } + + void CloseSubscriptionBindings() { + subscription_bindings_.CloseAllBindings(); + } + protected: void SetUp() override { - video_capture::mojom::DeviceFactoryPtr device_factory; - factory_binding_ = - std::make_unique<mojo::Binding<video_capture::mojom::DeviceFactory>>( - &mock_device_factory_, mojo::MakeRequest(&device_factory)); - factory_delegate_ = base::MakeRefCounted<RefCountedVideoCaptureFactory>( - std::move(device_factory), + source_provider_binding_ = std::make_unique< + mojo::Binding<video_capture::mojom::VideoSourceProvider>>( + &mock_source_provider_, mojo::MakeRequest(&source_provider_)); + service_connection_ = base::MakeRefCounted<RefCountedVideoSourceProvider>( + std::move(source_provider_), video_capture::mojom::DeviceFactoryProviderPtr(), release_connection_cb_.Get()); launcher_ = std::make_unique<ServiceVideoCaptureDeviceLauncher>( connect_to_device_factory_cb_.Get()); - launcher_has_connected_to_device_factory_ = false; - launcher_has_released_device_factory_ = false; + launcher_has_connected_to_source_provider_ = false; + launcher_has_released_source_provider_ = false; ON_CALL(connect_to_device_factory_cb_, Run(_)) .WillByDefault(Invoke( - [this](scoped_refptr<RefCountedVideoCaptureFactory>* out_factory) { - launcher_has_connected_to_device_factory_ = true; - *out_factory = factory_delegate_; + [this](scoped_refptr<RefCountedVideoSourceProvider>* out_provider) { + launcher_has_connected_to_source_provider_ = true; + *out_provider = service_connection_; })); ON_CALL(release_connection_cb_, Run()) .WillByDefault(InvokeWithoutArgs([this]() { - launcher_has_released_device_factory_ = true; + launcher_has_released_source_provider_ = true; wait_for_release_connection_cb_.Quit(); })); + + ON_CALL(mock_source_provider_, DoGetVideoSource(kStubDeviceId, _)) + .WillByDefault(Invoke( + [this](const std::string& device_id, + video_capture::mojom::VideoSourceRequest* source_request) { + source_binding_ = std::make_unique< + mojo::Binding<video_capture::mojom::VideoSource>>( + &mock_source_, std::move(*source_request)); + })); + + ON_CALL(mock_source_, DoCreatePushSubscription(_, _, _, _, _)) + .WillByDefault(Invoke( + [this](video_capture::mojom::ReceiverPtr& subscriber, + const media::VideoCaptureParams& requested_settings, + bool force_reopen_with_new_settings, + video_capture::mojom::PushVideoStreamSubscriptionRequest& + subscription, + video_capture::mojom::VideoSource:: + CreatePushSubscriptionCallback& callback) { + subscription_bindings_.AddBinding(&mock_subscription_, + std::move(subscription)); + std::move(callback).Run( + video_capture::mojom::CreatePushSubscriptionResultCode:: + kCreatedWithRequestedSettings, + requested_settings); + })); } void TearDown() override {} void RunLaunchingDeviceIsAbortedTest( - video_capture::mojom::DeviceAccessResultCode service_result_code); + video_capture::mojom::CreatePushSubscriptionResultCode + service_result_code); + void RunConnectionLostAfterSuccessfulStartTest( + base::OnceClosure close_connection_cb); TestBrowserThreadBundle thread_bundle_; - video_capture::MockDeviceFactory mock_device_factory_; MockVideoCaptureDeviceLauncherCallbacks mock_callbacks_; - std::unique_ptr<mojo::Binding<video_capture::mojom::DeviceFactory>> - factory_binding_; + video_capture::mojom::VideoSourceProviderPtr source_provider_; + video_capture::MockVideoSourceProvider mock_source_provider_; + std::unique_ptr<mojo::Binding<video_capture::mojom::VideoSourceProvider>> + source_provider_binding_; + video_capture::MockVideoSource mock_source_; + std::unique_ptr<mojo::Binding<video_capture::mojom::VideoSource>> + source_binding_; + video_capture::MockPushSubcription mock_subscription_; + mojo::BindingSet<video_capture::mojom::PushVideoStreamSubscription> + subscription_bindings_; std::unique_ptr<ServiceVideoCaptureDeviceLauncher> launcher_; base::MockCallback<base::OnceClosure> connection_lost_cb_; base::MockCallback<base::OnceClosure> done_cb_; @@ -93,11 +137,11 @@ ServiceVideoCaptureDeviceLauncher::ConnectToDeviceFactoryCB> connect_to_device_factory_cb_; base::MockCallback<base::OnceClosure> release_connection_cb_; - // |factory_delegate_| needs to go below |release_connection_cb_|, because its - // destructor will call |release_connection_cb_|. - scoped_refptr<RefCountedVideoCaptureFactory> factory_delegate_; - bool launcher_has_connected_to_device_factory_; - bool launcher_has_released_device_factory_; + // |service_connection_| needs to go below |release_connection_cb_|, because + // its destructor will call |release_connection_cb_|. + scoped_refptr<RefCountedVideoSourceProvider> service_connection_; + bool launcher_has_connected_to_source_provider_; + bool launcher_has_released_source_provider_; base::RunLoop wait_for_release_connection_cb_; private: @@ -105,26 +149,6 @@ }; TEST_F(ServiceVideoCaptureDeviceLauncherTest, LaunchingDeviceSucceeds) { - EXPECT_CALL(mock_device_factory_, DoCreateDevice(kStubDeviceId, _, _)) - .WillOnce(Invoke([](const std::string& device_id, - video_capture::mojom::DeviceRequest* device_request, - video_capture::mojom::DeviceFactory:: - CreateDeviceCallback& callback) { - // Note: We must keep |device_request| alive at least until we have - // sent out the callback. Otherwise, |launcher_| may interpret this - // as the connection having been lost before receiving the callback. - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, - base::BindOnce( - [](video_capture::mojom::DeviceRequest device_request, - video_capture::mojom::DeviceFactory::CreateDeviceCallback - callback) { - std::move(callback).Run( - video_capture::mojom::DeviceAccessResultCode::SUCCESS); - }, - std::move(*device_request), std::move(callback))); - })); - EXPECT_CALL(mock_callbacks_, DoOnDeviceLaunched(_)).Times(1); EXPECT_CALL(mock_callbacks_, OnDeviceLaunchAborted()).Times(0); EXPECT_CALL(mock_callbacks_, OnDeviceLaunchFailed(_)).Times(0); @@ -142,55 +166,64 @@ wait_for_done_cb.Run(); launcher_.reset(); - factory_delegate_.reset(); + service_connection_.reset(); wait_for_release_connection_cb_.Run(); - EXPECT_TRUE(launcher_has_connected_to_device_factory_); - EXPECT_TRUE(launcher_has_released_device_factory_); + EXPECT_TRUE(launcher_has_connected_to_source_provider_); + EXPECT_TRUE(launcher_has_released_source_provider_); } TEST_F(ServiceVideoCaptureDeviceLauncherTest, LaunchingDeviceIsAbortedBeforeServiceRespondsWithSuccess) { RunLaunchingDeviceIsAbortedTest( - video_capture::mojom::DeviceAccessResultCode::SUCCESS); + video_capture::mojom::CreatePushSubscriptionResultCode:: + kCreatedWithRequestedSettings); } TEST_F(ServiceVideoCaptureDeviceLauncherTest, LaunchingDeviceIsAbortedBeforeServiceRespondsWithNotFound) { RunLaunchingDeviceIsAbortedTest( - video_capture::mojom::DeviceAccessResultCode::ERROR_DEVICE_NOT_FOUND); + video_capture::mojom::CreatePushSubscriptionResultCode:: + kCreatedWithDifferentSettings); } TEST_F(ServiceVideoCaptureDeviceLauncherTest, LaunchingDeviceIsAbortedBeforeServiceRespondsWithNotInitialized) { RunLaunchingDeviceIsAbortedTest( - video_capture::mojom::DeviceAccessResultCode::NOT_INITIALIZED); + video_capture::mojom::CreatePushSubscriptionResultCode::kFailed); } void ServiceVideoCaptureDeviceLauncherTest::RunLaunchingDeviceIsAbortedTest( - video_capture::mojom::DeviceAccessResultCode service_result_code) { + video_capture::mojom::CreatePushSubscriptionResultCode + service_result_code) { base::RunLoop step_1_run_loop; base::RunLoop step_2_run_loop; - base::OnceClosure create_device_success_answer_cb; - EXPECT_CALL(mock_device_factory_, DoCreateDevice(kStubDeviceId, _, _)) - .WillOnce( - Invoke([&create_device_success_answer_cb, &step_1_run_loop, - service_result_code]( - const std::string& device_id, - video_capture::mojom::DeviceRequest* device_request, - video_capture::mojom::DeviceFactory::CreateDeviceCallback& - callback) { + base::OnceClosure create_push_subscription_success_answer_cb; + EXPECT_CALL(mock_source_, DoCreatePushSubscription(_, _, _, _, _)) + .WillOnce(Invoke( + [&create_push_subscription_success_answer_cb, &step_1_run_loop, + service_result_code]( + video_capture::mojom::ReceiverPtr& subscriber, + const media::VideoCaptureParams& requested_settings, + bool force_reopen_with_new_settings, + video_capture::mojom::PushVideoStreamSubscriptionRequest& + subscription, + video_capture::mojom::VideoSource::CreatePushSubscriptionCallback& + callback) { // Prepare the callback, but save it for now instead of invoking it. - create_device_success_answer_cb = base::BindOnce( - [](video_capture::mojom::DeviceRequest device_request, - video_capture::mojom::DeviceFactory::CreateDeviceCallback - callback, - video_capture::mojom::DeviceAccessResultCode + create_push_subscription_success_answer_cb = base::BindOnce( + [](const media::VideoCaptureParams& requested_settings, + video_capture::mojom::PushVideoStreamSubscriptionRequest + subscription, + video_capture::mojom::VideoSource:: + CreatePushSubscriptionCallback callback, + video_capture::mojom::CreatePushSubscriptionResultCode service_result_code) { - std::move(callback).Run(service_result_code); + std::move(callback).Run(service_result_code, + requested_settings); }, - std::move(*device_request), std::move(callback), - service_result_code); + requested_settings, std::move(subscription), + std::move(callback), service_result_code); step_1_run_loop.Quit(); })); EXPECT_CALL(mock_callbacks_, DoOnDeviceLaunched(_)).Times(0); @@ -209,39 +242,46 @@ step_1_run_loop.Run(); launcher_->AbortLaunch(); - std::move(create_device_success_answer_cb).Run(); + std::move(create_push_subscription_success_answer_cb).Run(); step_2_run_loop.Run(); - factory_delegate_.reset(); + service_connection_.reset(); - EXPECT_TRUE(launcher_has_connected_to_device_factory_); - EXPECT_TRUE(launcher_has_released_device_factory_); + EXPECT_TRUE(launcher_has_connected_to_source_provider_); + EXPECT_TRUE(launcher_has_released_source_provider_); } TEST_F(ServiceVideoCaptureDeviceLauncherTest, LaunchingDeviceFailsBecauseDeviceNotFound) { base::RunLoop run_loop; - EXPECT_CALL(mock_device_factory_, DoCreateDevice(kStubDeviceId, _, _)) - .WillOnce( - Invoke([](const std::string& device_id, - video_capture::mojom::DeviceRequest* device_request, - video_capture::mojom::DeviceFactory::CreateDeviceCallback& - callback) { - // Note: We must keep |device_request| alive at least until we have - // sent out the callback. Otherwise, |launcher_| may interpret this - // as the connection having been lost before receiving the callback. + EXPECT_CALL(mock_source_, DoCreatePushSubscription(_, _, _, _, _)) + .WillOnce(Invoke( + [](video_capture::mojom::ReceiverPtr& subscriber, + const media::VideoCaptureParams& requested_settings, + bool force_reopen_with_new_settings, + video_capture::mojom::PushVideoStreamSubscriptionRequest& + subscription, + video_capture::mojom::VideoSource::CreatePushSubscriptionCallback& + callback) { + // Note: We post this to the end of the message queue to make it + // asynchronous. base::ThreadTaskRunnerHandle::Get()->PostTask( FROM_HERE, base::BindOnce( - [](video_capture::mojom::DeviceRequest device_request, - video_capture::mojom::DeviceFactory::CreateDeviceCallback - callback) { + [](video_capture::mojom::ReceiverPtr subscriber, + const media::VideoCaptureParams& requested_settings, + video_capture::mojom::PushVideoStreamSubscriptionRequest + subscription, + video_capture::mojom::VideoSource:: + CreatePushSubscriptionCallback callback) { std::move(callback).Run( - video_capture::mojom::DeviceAccessResultCode:: - ERROR_DEVICE_NOT_FOUND); + video_capture::mojom:: + CreatePushSubscriptionResultCode::kFailed, + requested_settings); }, - std::move(*device_request), std::move(callback))); + std::move(subscriber), requested_settings, + std::move(subscription), std::move(callback))); })); EXPECT_CALL(mock_callbacks_, DoOnDeviceLaunched(_)).Times(0); EXPECT_CALL(mock_callbacks_, OnDeviceLaunchAborted()).Times(0); @@ -264,7 +304,7 @@ } TEST_F(ServiceVideoCaptureDeviceLauncherTest, - LaunchingDeviceFailsBecauseFactoryIsUnbound) { + LaunchingDeviceFailsBecauseSourceProviderIsUnbound) { base::RunLoop run_loop(base::RunLoop::Type::kNestableTasksAllowed); EXPECT_CALL(mock_callbacks_, DoOnDeviceLaunched(_)).Times(0); @@ -276,7 +316,7 @@ })); // Exercise - factory_delegate_->ReleaseFactoryForTesting(); + service_connection_->ReleaseProviderForTesting(); launcher_->LaunchDeviceAsync(kStubDeviceId, blink::MEDIA_DEVICE_VIDEO_CAPTURE, kArbitraryParams, kNullReceiver, @@ -290,18 +330,22 @@ LaunchingDeviceFailsBecauseConnectionLostWhileLaunching) { base::RunLoop run_loop; - video_capture::mojom::DeviceFactory::CreateDeviceCallback create_device_cb; - EXPECT_CALL(mock_device_factory_, DoCreateDevice(kStubDeviceId, _, _)) - .WillOnce( - Invoke([&create_device_cb]( - const std::string& device_id, - video_capture::mojom::DeviceRequest* device_request, - video_capture::mojom::DeviceFactory::CreateDeviceCallback& - callback) { + video_capture::mojom::VideoSource::CreatePushSubscriptionCallback + create_subscription_cb; + EXPECT_CALL(mock_source_, DoCreatePushSubscription(_, _, _, _, _)) + .WillOnce(Invoke( + [&create_subscription_cb]( + video_capture::mojom::ReceiverPtr& subscriber, + const media::VideoCaptureParams& requested_settings, + bool force_reopen_with_new_settings, + video_capture::mojom::PushVideoStreamSubscriptionRequest& + subscription, + video_capture::mojom::VideoSource::CreatePushSubscriptionCallback& + callback) { // Simulate connection lost by not invoking |callback| and releasing - // |device_request|. We have to save |callback| and invoke it later + // |subscription|. We have to save |callback| and invoke it later // to avoid hitting a DCHECK. - create_device_cb = std::move(callback); + create_subscription_cb = std::move(callback); })); EXPECT_CALL(mock_callbacks_, DoOnDeviceLaunched(_)).Times(0); EXPECT_CALL(mock_callbacks_, OnDeviceLaunchAborted()).Times(0); @@ -321,36 +365,35 @@ run_loop.Run(); - // Cut the connection to the factory, so that the outstanding - // |create_device_cb| will be dropped. - factory_binding_.reset(); + // Cleanup + // Cut the connection to the source, so that the outstanding + // |create_subscription_cb| will be dropped when we invoke it below. + source_binding_.reset(); // We have to invoke the callback, because not doing so triggers a DCHECK. - const video_capture::mojom::DeviceAccessResultCode arbitrary_result_code = - video_capture::mojom::DeviceAccessResultCode::SUCCESS; - std::move(create_device_cb).Run(arbitrary_result_code); + const video_capture::mojom::CreatePushSubscriptionResultCode + arbitrary_result_code = video_capture::mojom:: + CreatePushSubscriptionResultCode::kCreatedWithRequestedSettings; + std::move(create_subscription_cb) + .Run(arbitrary_result_code, kArbitraryParams); } TEST_F(ServiceVideoCaptureDeviceLauncherTest, - ConnectionLostAfterSuccessfulLaunch) { - video_capture::mojom::DeviceRequest device_request_owned_by_service; - EXPECT_CALL(mock_device_factory_, DoCreateDevice(kStubDeviceId, _, _)) - .WillOnce(Invoke([&device_request_owned_by_service]( - const std::string& device_id, - video_capture::mojom::DeviceRequest* device_request, - video_capture::mojom::DeviceFactory:: - CreateDeviceCallback& callback) { - // The service holds on to the |device_request|. - device_request_owned_by_service = std::move(*device_request); - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, - base::BindOnce( - [](video_capture::mojom::DeviceFactory::CreateDeviceCallback - callback) { - std::move(callback).Run( - video_capture::mojom::DeviceAccessResultCode::SUCCESS); - }, - std::move(callback))); - })); + ConnectionToSubscriptionLostAfterSuccessfulLaunch) { + RunConnectionLostAfterSuccessfulStartTest( + base::BindOnce(&ServiceVideoCaptureDeviceLauncherTest::CloseSourceBinding, + base::Unretained(this))); +} + +TEST_F(ServiceVideoCaptureDeviceLauncherTest, + ConnectionToSourceLostAfterSuccessfulLaunch) { + RunConnectionLostAfterSuccessfulStartTest(base::BindOnce( + &ServiceVideoCaptureDeviceLauncherTest::CloseSubscriptionBindings, + base::Unretained(this))); +} + +void ServiceVideoCaptureDeviceLauncherTest:: + RunConnectionLostAfterSuccessfulStartTest( + base::OnceClosure close_connection_cb) { std::unique_ptr<LaunchedVideoCaptureDevice> launched_device; EXPECT_CALL(mock_callbacks_, DoOnDeviceLaunched(_)) .WillOnce( @@ -376,14 +419,14 @@ step_2_run_loop.Quit(); })); // Exercise step 2: The service cuts/loses the connection - device_request_owned_by_service = nullptr; + std::move(close_connection_cb).Run(); step_2_run_loop.Run(); launcher_.reset(); - factory_delegate_.reset(); + service_connection_.reset(); wait_for_release_connection_cb_.Run(); - EXPECT_TRUE(launcher_has_connected_to_device_factory_); - EXPECT_TRUE(launcher_has_released_device_factory_); + EXPECT_TRUE(launcher_has_connected_to_source_provider_); + EXPECT_TRUE(launcher_has_released_source_provider_); } } // namespace content
diff --git a/content/browser/renderer_host/media/service_video_capture_provider.cc b/content/browser/renderer_host/media/service_video_capture_provider.cc index fa741990..55c56ec 100644 --- a/content/browser/renderer_host/media/service_video_capture_provider.cc +++ b/content/browser/renderer_host/media/service_video_capture_provider.cc
@@ -59,7 +59,7 @@ : connector_(connector ? connector->Clone() : nullptr), create_accelerator_factory_cb_(std::move(create_accelerator_factory_cb)), emit_log_message_cb_(std::move(emit_log_message_cb)), - launcher_has_connected_to_device_factory_(false), + launcher_has_connected_to_source_provider_(false), service_listener_binding_(this), weak_ptr_factory_(this) { base::PostTaskWithTraits( @@ -86,7 +86,7 @@ DCHECK_CURRENTLY_ON(content::BrowserThread::IO); return std::make_unique<ServiceVideoCaptureDeviceLauncher>( base::BindRepeating( - &ServiceVideoCaptureProvider::OnLauncherConnectingToDeviceFactory, + &ServiceVideoCaptureProvider::OnLauncherConnectingToSourceProvider, weak_ptr_factory_.GetWeakPtr())); } @@ -106,7 +106,7 @@ mojo::MakeStrongBinding( std::make_unique<VirtualVideoCaptureDevicesChangedObserver>(), mojo::MakeRequest(&observer)); - service_connection->device_factory()->RegisterVirtualDevicesChangedObserver( + service_connection->source_provider()->RegisterVirtualDevicesChangedObserver( std::move(observer), true /*raise_event_if_virtual_devices_already_present*/); } @@ -144,14 +144,14 @@ service_manager->AddListener(std::move(listener)); } -void ServiceVideoCaptureProvider::OnLauncherConnectingToDeviceFactory( - scoped_refptr<RefCountedVideoCaptureFactory>* out_factory) { +void ServiceVideoCaptureProvider::OnLauncherConnectingToSourceProvider( + scoped_refptr<RefCountedVideoSourceProvider>* out_provider) { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - launcher_has_connected_to_device_factory_ = true; - *out_factory = LazyConnectToService(); + launcher_has_connected_to_source_provider_ = true; + *out_provider = LazyConnectToService(); } -scoped_refptr<RefCountedVideoCaptureFactory> +scoped_refptr<RefCountedVideoSourceProvider> ServiceVideoCaptureProvider::LazyConnectToService() { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); @@ -163,7 +163,7 @@ video_capture::uma::LogVideoCaptureServiceEvent( video_capture::uma::BROWSER_CONNECTING_TO_SERVICE); if (time_of_last_uninitialize_ != base::TimeTicks()) { - if (launcher_has_connected_to_device_factory_) { + if (launcher_has_connected_to_source_provider_) { video_capture::uma::LogDurationUntilReconnectAfterCapture( base::TimeTicks::Now() - time_of_last_uninitialize_); } else { @@ -172,7 +172,7 @@ } } - launcher_has_connected_to_device_factory_ = false; + launcher_has_connected_to_source_provider_ = false; time_of_last_connect_ = base::TimeTicks::Now(); video_capture::mojom::AcceleratorFactoryPtr accelerator_factory; @@ -189,14 +189,14 @@ device_factory_provider->InjectGpuDependencies( std::move(accelerator_factory)); - video_capture::mojom::DeviceFactoryPtr device_factory; - device_factory_provider->ConnectToDeviceFactory( - mojo::MakeRequest(&device_factory)); - device_factory.set_connection_error_handler(base::BindOnce( - &ServiceVideoCaptureProvider::OnLostConnectionToDeviceFactory, + video_capture::mojom::VideoSourceProviderPtr source_provider; + device_factory_provider->ConnectToVideoSourceProvider( + mojo::MakeRequest(&source_provider)); + source_provider.set_connection_error_handler(base::BindOnce( + &ServiceVideoCaptureProvider::OnLostConnectionToSourceProvider, weak_ptr_factory_.GetWeakPtr())); - auto result = base::MakeRefCounted<RefCountedVideoCaptureFactory>( - std::move(device_factory), std::move(device_factory_provider), + auto result = base::MakeRefCounted<RefCountedVideoSourceProvider>( + std::move(source_provider), std::move(device_factory_provider), base::BindOnce(&ServiceVideoCaptureProvider::OnServiceConnectionClosed, weak_ptr_factory_.GetWeakPtr(), ReasonForDisconnect::kUnused)); @@ -211,7 +211,7 @@ auto service_connection = LazyConnectToService(); // Use a ScopedCallbackRunner to make sure that |result_callback| gets // invoked with an empty result in case that the service drops the request. - service_connection->device_factory()->GetDeviceInfos( + service_connection->source_provider()->GetSourceInfos( mojo::WrapCallbackWithDefaultInvokeIfNotRun( base::BindOnce(&ServiceVideoCaptureProvider::OnDeviceInfosReceived, weak_ptr_factory_.GetWeakPtr(), service_connection, @@ -220,7 +220,7 @@ } void ServiceVideoCaptureProvider::OnDeviceInfosReceived( - scoped_refptr<RefCountedVideoCaptureFactory> service_connection, + scoped_refptr<RefCountedVideoSourceProvider> service_connection, GetDeviceInfosCallback result_callback, int retry_count, const std::vector<media::VideoCaptureDeviceInfo>& infos) { @@ -254,10 +254,10 @@ base::ResetAndReturn(&result_callback).Run(infos); } -void ServiceVideoCaptureProvider::OnLostConnectionToDeviceFactory() { +void ServiceVideoCaptureProvider::OnLostConnectionToSourceProvider() { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); emit_log_message_cb_.Run( - "ServiceVideoCaptureProvider::OnLostConnectionToDeviceFactory"); + "ServiceVideoCaptureProvider::OnLostConnectionToSourceProvider"); // This may indicate that the video capture service has crashed. Uninitialize // here, so that a new connection will be established when clients try to // reconnect. @@ -272,7 +272,7 @@ switch (reason) { case ReasonForDisconnect::kShutdown: case ReasonForDisconnect::kUnused: - if (launcher_has_connected_to_device_factory_) { + if (launcher_has_connected_to_source_provider_) { video_capture::uma::LogVideoCaptureServiceEvent( video_capture::uma:: BROWSER_CLOSING_CONNECTION_TO_SERVICE_AFTER_CAPTURE);
diff --git a/content/browser/renderer_host/media/service_video_capture_provider.h b/content/browser/renderer_host/media/service_video_capture_provider.h index 55fb590..ed95c61 100644 --- a/content/browser/renderer_host/media/service_video_capture_provider.h +++ b/content/browser/renderer_host/media/service_video_capture_provider.h
@@ -7,7 +7,7 @@ #include "base/threading/thread_checker.h" #include "build/build_config.h" -#include "content/browser/renderer_host/media/ref_counted_video_capture_factory.h" +#include "content/browser/renderer_host/media/ref_counted_video_source_provider.h" #include "content/browser/renderer_host/media/video_capture_provider.h" #include "mojo/public/cpp/bindings/binding.h" #include "services/service_manager/public/cpp/connector.h" @@ -66,31 +66,31 @@ void RegisterServiceListenerOnIOThread(); // Note, this needs to have void return value because of "weak_ptrs can only // bind to methods without return values". - void OnLauncherConnectingToDeviceFactory( - scoped_refptr<RefCountedVideoCaptureFactory>* out_factory); - // Discarding the returned RefCountedVideoCaptureFactory indicates that the + void OnLauncherConnectingToSourceProvider( + scoped_refptr<RefCountedVideoSourceProvider>* out_provider); + // Discarding the returned RefCountedVideoSourceProvider indicates that the // caller no longer requires the connection to the service and allows it to // disconnect. - scoped_refptr<RefCountedVideoCaptureFactory> LazyConnectToService() + scoped_refptr<RefCountedVideoSourceProvider> LazyConnectToService() WARN_UNUSED_RESULT; void GetDeviceInfosAsyncForRetry(GetDeviceInfosCallback result_callback, int retry_count); void OnDeviceInfosReceived( - scoped_refptr<RefCountedVideoCaptureFactory> service_connection, + scoped_refptr<RefCountedVideoSourceProvider> service_connection, GetDeviceInfosCallback result_callback, int retry_count, const std::vector<media::VideoCaptureDeviceInfo>& infos); - void OnLostConnectionToDeviceFactory(); + void OnLostConnectionToSourceProvider(); void OnServiceConnectionClosed(ReasonForDisconnect reason); std::unique_ptr<service_manager::Connector> connector_; CreateAcceleratorFactoryCallback create_accelerator_factory_cb_; base::RepeatingCallback<void(const std::string&)> emit_log_message_cb_; - base::WeakPtr<RefCountedVideoCaptureFactory> weak_service_connection_; + base::WeakPtr<RefCountedVideoSourceProvider> weak_service_connection_; - bool launcher_has_connected_to_device_factory_; + bool launcher_has_connected_to_source_provider_; base::TimeTicks time_of_last_connect_; base::TimeTicks time_of_last_uninitialize_;
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 7220d9d..6246579 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
@@ -12,12 +12,15 @@ #include "content/public/browser/video_capture_device_launcher.h" #include "content/public/test/test_browser_thread_bundle.h" #include "mojo/public/cpp/bindings/binding.h" +#include "mojo/public/cpp/bindings/binding_set.h" #include "services/service_manager/public/cpp/binder_registry.h" #include "services/service_manager/public/cpp/service.h" #include "services/service_manager/public/cpp/service_binding.h" #include "services/service_manager/public/cpp/test/test_connector_factory.h" -#include "services/video_capture/public/cpp/mock_device_factory.h" #include "services/video_capture/public/cpp/mock_device_factory_provider.h" +#include "services/video_capture/public/cpp/mock_push_subscription.h" +#include "services/video_capture/public/cpp/mock_video_source.h" +#include "services/video_capture/public/cpp/mock_video_source_provider.h" #include "services/video_capture/public/mojom/constants.mojom.h" #include "services/video_capture/public/mojom/producer.mojom.h" #include "testing/gmock/include/gmock/gmock.h" @@ -101,7 +104,7 @@ service_manager::mojom::kServiceName)), factory_provider_binding_(&mock_device_factory_provider_), factory_provider_is_bound_(false), - device_factory_binding_(&mock_device_factory_) {} + source_provider_binding_(&mock_source_provider_) {} ~ServiceVideoCaptureProviderTest() override {} protected: @@ -127,14 +130,45 @@ }, &factory_provider_is_bound_)); })); - ON_CALL(mock_device_factory_provider_, DoConnectToDeviceFactory(_)) - .WillByDefault( - Invoke([this](video_capture::mojom::DeviceFactoryRequest& request) { - if (device_factory_binding_.is_bound()) - device_factory_binding_.Close(); - device_factory_binding_.Bind(std::move(request)); + ON_CALL(mock_device_factory_provider_, DoConnectToVideoSourceProvider(_)) + .WillByDefault(Invoke( + [this](video_capture::mojom::VideoSourceProviderRequest& request) { + if (source_provider_binding_.is_bound()) + source_provider_binding_.Close(); + source_provider_binding_.Bind(std::move(request)); wait_for_connection_to_service_.Quit(); })); + + ON_CALL(mock_source_provider_, DoGetSourceInfos(_)) + .WillByDefault(Invoke([](video_capture::mojom::VideoSourceProvider:: + GetSourceInfosCallback& callback) { + std::vector<media::VideoCaptureDeviceInfo> arbitrarily_empty_results; + base::ResetAndReturn(&callback).Run(arbitrarily_empty_results); + })); + + ON_CALL(mock_source_provider_, DoGetVideoSource(_, _)) + .WillByDefault( + Invoke([this](const std::string& device_id, + video_capture::mojom::VideoSourceRequest* request) { + source_bindings_.AddBinding(&mock_source_, std::move(*request)); + })); + + ON_CALL(mock_source_, DoCreatePushSubscription(_, _, _, _, _)) + .WillByDefault(Invoke( + [this](video_capture::mojom::ReceiverPtr& subscriber, + const media::VideoCaptureParams& requested_settings, + bool force_reopen_with_new_settings, + video_capture::mojom::PushVideoStreamSubscriptionRequest& + subscription, + video_capture::mojom::VideoSource:: + CreatePushSubscriptionCallback& callback) { + subscription_bindings_.AddBinding(&mock_subscription_, + std::move(subscription)); + std::move(callback).Run( + video_capture::mojom::CreatePushSubscriptionResultCode:: + kCreatedWithRequestedSettings, + requested_settings); + })); } void TearDown() override {} @@ -147,12 +181,18 @@ mojo::Binding<video_capture::mojom::DeviceFactoryProvider> factory_provider_binding_; bool factory_provider_is_bound_; - video_capture::MockDeviceFactory mock_device_factory_; - mojo::Binding<video_capture::mojom::DeviceFactory> device_factory_binding_; + video_capture::MockVideoSourceProvider mock_source_provider_; + mojo::Binding<video_capture::mojom::VideoSourceProvider> + source_provider_binding_; + video_capture::MockVideoSource mock_source_; + mojo::BindingSet<video_capture::mojom::VideoSource> source_bindings_; + video_capture::MockPushSubcription mock_subscription_; + mojo::BindingSet<video_capture::mojom::PushVideoStreamSubscription> + subscription_bindings_; std::unique_ptr<ServiceVideoCaptureProvider> provider_; base::MockCallback<VideoCaptureProvider::GetDeviceInfosCallback> results_cb_; base::MockCallback< - video_capture::mojom::DeviceFactory::GetDeviceInfosCallback> + video_capture::mojom::VideoSourceProvider::GetSourceInfosCallback> service_cb_; base::RunLoop wait_for_connection_to_service_; @@ -167,14 +207,14 @@ GetDeviceInfosAsyncInvokesCallbackWhenLosingConnection) { base::RunLoop run_loop; - video_capture::mojom::DeviceFactory::GetDeviceInfosCallback + video_capture::mojom::VideoSourceProvider::GetSourceInfosCallback callback_to_be_called_by_service; base::RunLoop wait_for_call_to_arrive_at_service; - EXPECT_CALL(mock_device_factory_, DoGetDeviceInfos(_)) + EXPECT_CALL(mock_source_provider_, DoGetSourceInfos(_)) .WillOnce(Invoke( [&callback_to_be_called_by_service, &wait_for_call_to_arrive_at_service]( - video_capture::mojom::DeviceFactory::GetDeviceInfosCallback& + video_capture::mojom::VideoSourceProvider::GetSourceInfosCallback& callback) { // Hold on to the callback so we can drop it later. callback_to_be_called_by_service = std::move(callback); @@ -194,7 +234,7 @@ wait_for_call_to_arrive_at_service.Run(); // Simulate that the service goes down by cutting the connections. - device_factory_binding_.Close(); + source_provider_binding_.Close(); factory_provider_binding_.Close(); wait_for_callback_from_service.Run(); @@ -205,14 +245,14 @@ TEST_F(ServiceVideoCaptureProviderTest, ClosesServiceConnectionAfterGetDeviceInfos) { // Setup part 1 - video_capture::mojom::DeviceFactory::GetDeviceInfosCallback + video_capture::mojom::VideoSourceProvider::GetSourceInfosCallback callback_to_be_called_by_service; base::RunLoop wait_for_call_to_arrive_at_service; - EXPECT_CALL(mock_device_factory_, DoGetDeviceInfos(_)) + EXPECT_CALL(mock_source_provider_, DoGetSourceInfos(_)) .WillOnce(Invoke( [&callback_to_be_called_by_service, &wait_for_call_to_arrive_at_service]( - video_capture::mojom::DeviceFactory::GetDeviceInfosCallback& + video_capture::mojom::VideoSourceProvider::GetSourceInfosCallback& callback) { // Hold on to the callback so we can drop it later. callback_to_be_called_by_service = std::move(callback); @@ -225,11 +265,11 @@ // Setup part 2: Now that the connection to the service is established, we can // listen for disconnects. - base::RunLoop wait_for_connection_to_device_factory_to_close; + base::RunLoop wait_for_connection_to_source_provider_to_close; base::RunLoop wait_for_connection_to_device_factory_provider_to_close; - device_factory_binding_.set_connection_error_handler( + source_provider_binding_.set_connection_error_handler( base::BindOnce([](base::RunLoop* run_loop) { run_loop->Quit(); }, - &wait_for_connection_to_device_factory_to_close)); + &wait_for_connection_to_source_provider_to_close)); factory_provider_binding_.set_connection_error_handler( base::BindOnce([](base::RunLoop* run_loop) { run_loop->Quit(); }, &wait_for_connection_to_device_factory_provider_to_close)); @@ -240,7 +280,7 @@ .Run(arbitrarily_empty_results); // Verification: Expect |provider_| to close the connection to the service. - wait_for_connection_to_device_factory_to_close.Run(); + wait_for_connection_to_source_provider_to_close.Run(); if (factory_provider_is_bound_) { wait_for_connection_to_device_factory_provider_to_close.Run(); } @@ -252,21 +292,6 @@ // soon as the last VideoCaptureDeviceLauncher instance is released. TEST_F(ServiceVideoCaptureProviderTest, KeepsServiceConnectionWhileDeviceLauncherAlive) { - ON_CALL(mock_device_factory_, DoGetDeviceInfos(_)) - .WillByDefault(Invoke([](video_capture::mojom::DeviceFactory:: - GetDeviceInfosCallback& callback) { - std::vector<media::VideoCaptureDeviceInfo> arbitrarily_empty_results; - base::ResetAndReturn(&callback).Run(arbitrarily_empty_results); - })); - ON_CALL(mock_device_factory_, DoCreateDevice(_, _, _)) - .WillByDefault( - Invoke([](const std::string& device_id, - video_capture::mojom::DeviceRequest* device_request, - video_capture::mojom::DeviceFactory::CreateDeviceCallback& - callback) { - base::ResetAndReturn(&callback).Run( - video_capture::mojom::DeviceAccessResultCode::SUCCESS); - })); MockVideoCaptureDeviceLauncherCallbacks mock_callbacks; // Exercise part 1: Create a device launcher and hold on to it. @@ -281,7 +306,7 @@ // Monitor if connection gets closed bool connection_has_been_closed = false; - device_factory_binding_.set_connection_error_handler(base::BindOnce( + source_provider_binding_.set_connection_error_handler(base::BindOnce( [](bool* connection_has_been_closed) { *connection_has_been_closed = true; }, @@ -335,7 +360,7 @@ } ASSERT_FALSE(connection_has_been_closed); - // Exercise part 3: Release the initial device launcher. + // Exercise part 4: Release the initial device launcher. device_launcher_1.reset(); { base::RunLoop give_provider_chance_to_disconnect; @@ -352,12 +377,12 @@ DoesNotCloseServiceConnectionWhileGetDeviceInfoResponsePending) { // When GetDeviceInfos gets called, hold on to the callbacks, but do not // yet invoke them. - std::vector<video_capture::mojom::DeviceFactory::GetDeviceInfosCallback> + std::vector<video_capture::mojom::VideoSourceProvider::GetSourceInfosCallback> callbacks_to_be_called_by_service; - ON_CALL(mock_device_factory_, DoGetDeviceInfos(_)) + ON_CALL(mock_source_provider_, DoGetSourceInfos(_)) .WillByDefault(Invoke( [&callbacks_to_be_called_by_service]( - video_capture::mojom::DeviceFactory::GetDeviceInfosCallback& + video_capture::mojom::VideoSourceProvider::GetSourceInfosCallback& callback) { callbacks_to_be_called_by_service.push_back(std::move(callback)); })); @@ -377,7 +402,7 @@ // Monitor if connection gets closed bool connection_has_been_closed = false; - device_factory_binding_.set_connection_error_handler(base::BindOnce( + source_provider_binding_.set_connection_error_handler(base::BindOnce( [](bool* connection_has_been_closed) { *connection_has_been_closed = true; },
diff --git a/content/browser/renderer_host/media/virtual_video_capture_devices_changed_observer.h b/content/browser/renderer_host/media/virtual_video_capture_devices_changed_observer.h index f40e0f9e..591c3d7 100644 --- a/content/browser/renderer_host/media/virtual_video_capture_devices_changed_observer.h +++ b/content/browser/renderer_host/media/virtual_video_capture_devices_changed_observer.h
@@ -6,6 +6,7 @@ #define CONTENT_BROWSER_RENDERER_HOST_MEDIA_VIRTUAL_VIDEO_CAPTURE_DEVICES_CHANGED_OBSERVER_H_ #include "services/video_capture/public/mojom/device_factory.mojom.h" +#include "services/video_capture/public/mojom/devices_changed_observer.mojom.h" namespace content {
diff --git a/content/browser/renderer_host/render_widget_host_input_event_router.cc b/content/browser/renderer_host/render_widget_host_input_event_router.cc index e9fbacf3..4e8b510c 100644 --- a/content/browser/renderer_host/render_widget_host_input_event_router.cc +++ b/content/browser/renderer_host/render_widget_host_input_event_router.cc
@@ -497,8 +497,7 @@ if (needs_transform_point) { if (!root_view->TransformPointToCoordSpaceForView( - event.PositionInWidget(), target, &transformed_point, - viz::EventSource::MOUSE)) { + event.PositionInWidget(), target, &transformed_point)) { return {nullptr, false, base::nullopt, latched_target, false}; } } @@ -515,8 +514,7 @@ if (root_view->IsMouseLocked()) { target = root_view->host()->delegate()->GetMouseLockWidget()->GetView(); if (!root_view->TransformPointToCoordSpaceForView( - event.PositionInWidget(), target, &transformed_point, - viz::EventSource::MOUSE)) { + event.PositionInWidget(), target, &transformed_point)) { return {nullptr, false, base::nullopt, true, false}; } return {target, false, transformed_point, true, false}; @@ -1001,8 +999,7 @@ // propagated to its embedding surface, which makes it impossible to // compute the transformation for it if (!root_view->TransformPointToCoordSpaceForView( - event.PositionInWidget(), view, &transformed_point, - viz::EventSource::MOUSE)) { + event.PositionInWidget(), view, &transformed_point)) { transformed_point = gfx::PointF(); } mouse_leave.SetPositionInWidget(transformed_point.x(), @@ -1015,8 +1012,7 @@ blink::WebMouseEvent mouse_move(event); mouse_move.SetType(blink::WebInputEvent::kMouseMove); if (!root_view->TransformPointToCoordSpaceForView( - event.PositionInWidget(), common_ancestor, &transformed_point, - viz::EventSource::MOUSE)) { + event.PositionInWidget(), common_ancestor, &transformed_point)) { transformed_point = gfx::PointF(); } mouse_move.SetPositionInWidget(transformed_point.x(), @@ -1031,8 +1027,7 @@ blink::WebMouseEvent mouse_enter(event); mouse_enter.SetType(blink::WebInputEvent::kMouseMove); if (!root_view->TransformPointToCoordSpaceForView( - event.PositionInWidget(), view, &transformed_point, - viz::EventSource::MOUSE)) { + event.PositionInWidget(), view, &transformed_point)) { transformed_point = gfx::PointF(); } mouse_enter.SetPositionInWidget(transformed_point.x(),
diff --git a/content/browser/renderer_host/render_widget_host_input_event_router_unittest.cc b/content/browser/renderer_host/render_widget_host_input_event_router_unittest.cc index d1727f7..83645a6 100644 --- a/content/browser/renderer_host/render_widget_host_input_event_router_unittest.cc +++ b/content/browser/renderer_host/render_widget_host_input_event_router_unittest.cc
@@ -148,8 +148,7 @@ bool TransformPointToCoordSpaceForView( const gfx::PointF& point, RenderWidgetHostViewBase* target_view, - gfx::PointF* transformed_point, - viz::EventSource source = viz::EventSource::ANY) override { + gfx::PointF* transformed_point) override { return true; }
diff --git a/content/browser/renderer_host/render_widget_host_view_android.cc b/content/browser/renderer_host/render_widget_host_view_android.cc index ba2cca4..3417786c 100644 --- a/content/browser/renderer_host/render_widget_host_view_android.cc +++ b/content/browser/renderer_host/render_widget_host_view_android.cc
@@ -650,8 +650,7 @@ bool RenderWidgetHostViewAndroid::TransformPointToCoordSpaceForView( const gfx::PointF& point, RenderWidgetHostViewBase* target_view, - gfx::PointF* transformed_point, - viz::EventSource source) { + gfx::PointF* transformed_point) { if (target_view == this) { *transformed_point = point; return true; @@ -664,8 +663,8 @@ // In TransformPointToLocalCoordSpace() there is a Point-to-Pixel conversion, // but it is not necessary here because the final target view is responsible // for converting before computing the final transform. - return target_view->TransformPointToLocalCoordSpace( - point, surface_id, transformed_point, source); + return target_view->TransformPointToLocalCoordSpace(point, surface_id, + transformed_point); } base::WeakPtr<RenderWidgetHostViewAndroid>
diff --git a/content/browser/renderer_host/render_widget_host_view_android.h b/content/browser/renderer_host/render_widget_host_view_android.h index 3d0c77d..69e1feea 100644 --- a/content/browser/renderer_host/render_widget_host_view_android.h +++ b/content/browser/renderer_host/render_widget_host_view_android.h
@@ -174,8 +174,7 @@ bool TransformPointToCoordSpaceForView( const gfx::PointF& point, RenderWidgetHostViewBase* target_view, - gfx::PointF* transformed_point, - viz::EventSource source = viz::EventSource::ANY) override; + gfx::PointF* transformed_point) override; TouchSelectionControllerClientManager* GetTouchSelectionControllerClientManager() override; const viz::LocalSurfaceIdAllocation& GetLocalSurfaceIdAllocation()
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.cc b/content/browser/renderer_host/render_widget_host_view_aura.cc index 7d0c4e3..c272f6a 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura.cc +++ b/content/browser/renderer_host/render_widget_host_view_aura.cc
@@ -1749,8 +1749,7 @@ bool RenderWidgetHostViewAura::TransformPointToCoordSpaceForView( const gfx::PointF& point, RenderWidgetHostViewBase* target_view, - gfx::PointF* transformed_point, - viz::EventSource source) { + gfx::PointF* transformed_point) { if (target_view == this || !delegated_frame_host_) { *transformed_point = point; return true; @@ -1760,7 +1759,7 @@ // but it is not necessary here because the final target view is responsible // for converting before computing the final transform. return target_view->TransformPointToLocalCoordSpace( - point, GetCurrentSurfaceId(), transformed_point, source); + point, GetCurrentSurfaceId(), transformed_point); } viz::FrameSinkId RenderWidgetHostViewAura::GetRootFrameSinkId() {
diff --git a/content/browser/renderer_host/render_widget_host_view_aura.h b/content/browser/renderer_host/render_widget_host_view_aura.h index 3c3bd1c..126be50 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura.h +++ b/content/browser/renderer_host/render_widget_host_view_aura.h
@@ -192,8 +192,7 @@ bool TransformPointToCoordSpaceForView( const gfx::PointF& point, RenderWidgetHostViewBase* target_view, - gfx::PointF* transformed_point, - viz::EventSource source = viz::EventSource::ANY) override; + gfx::PointF* transformed_point) override; viz::FrameSinkId GetRootFrameSinkId() override; viz::SurfaceId GetCurrentSurfaceId() const override;
diff --git a/content/browser/renderer_host/render_widget_host_view_base.cc b/content/browser/renderer_host/render_widget_host_view_base.cc index 68d55c2..2672a26d 100644 --- a/content/browser/renderer_host/render_widget_host_view_base.cc +++ b/content/browser/renderer_host/render_widget_host_view_base.cc
@@ -703,11 +703,10 @@ bool RenderWidgetHostViewBase::TransformPointToLocalCoordSpace( const gfx::PointF& point, const viz::SurfaceId& original_surface, - gfx::PointF* transformed_point, - viz::EventSource source) { + gfx::PointF* transformed_point) { if (use_viz_hit_test_) { return TransformPointToLocalCoordSpaceViz(point, original_surface, - transformed_point, source); + transformed_point); } return TransformPointToLocalCoordSpaceLegacy(point, original_surface, transformed_point); @@ -724,8 +723,7 @@ bool RenderWidgetHostViewBase::TransformPointToCoordSpaceForView( const gfx::PointF& point, RenderWidgetHostViewBase* target_view, - gfx::PointF* transformed_point, - viz::EventSource source) { + gfx::PointF* transformed_point) { NOTREACHED(); return true; } @@ -900,8 +898,7 @@ RenderWidgetHostViewBase* original_view, RenderWidgetHostViewBase* target_view, const gfx::PointF& point, - gfx::PointF* transformed_point, - viz::EventSource source) const { + gfx::PointF* transformed_point) const { DCHECK(use_viz_hit_test_); viz::FrameSinkId root_frame_sink_id = original_view->GetRootFrameSinkId(); if (!root_frame_sink_id.is_valid()) @@ -951,9 +948,8 @@ &transform_root_to_original); if (!transform_root_to_original.TransformPointReverse(&point_in_pixels)) return false; - if (!query->TransformLocationForTarget(source, target_ancestors, - point_in_pixels.AsPointF(), - transformed_point)) { + if (!query->TransformLocationForTarget( + target_ancestors, point_in_pixels.AsPointF(), transformed_point)) { return false; } *transformed_point = @@ -1022,8 +1018,7 @@ bool RenderWidgetHostViewBase::TransformPointToLocalCoordSpaceViz( const gfx::PointF& point, const viz::SurfaceId& original_surface, - gfx::PointF* transformed_point, - viz::EventSource source) { + gfx::PointF* transformed_point) { DCHECK(use_viz_hit_test_); viz::FrameSinkId original_frame_sink_id = original_surface.frame_sink_id(); viz::FrameSinkId target_frame_sink_id = GetFrameSinkId(); @@ -1040,7 +1035,7 @@ return TransformPointToTargetCoordSpace( router->FindViewFromFrameSinkId(original_frame_sink_id), router->FindViewFromFrameSinkId(target_frame_sink_id), point, - transformed_point, source); + transformed_point); } } // namespace content
diff --git a/content/browser/renderer_host/render_widget_host_view_base.h b/content/browser/renderer_host/render_widget_host_view_base.h index 148c980..8cdb72a 100644 --- a/content/browser/renderer_host/render_widget_host_view_base.h +++ b/content/browser/renderer_host/render_widget_host_view_base.h
@@ -363,11 +363,9 @@ // spaces of surfaces where one does not contain the other. To transform // between sibling surfaces, the point must be transformed to the root's // coordinate space as an intermediate step. - bool TransformPointToLocalCoordSpace( - const gfx::PointF& point, - const viz::SurfaceId& original_surface, - gfx::PointF* transformed_point, - viz::EventSource source = viz::EventSource::ANY); + bool TransformPointToLocalCoordSpace(const gfx::PointF& point, + const viz::SurfaceId& original_surface, + gfx::PointF* transformed_point); // This is deprecated, and will be removed once Viz hit-test is the default. virtual bool TransformPointToLocalCoordSpaceLegacy( @@ -382,8 +380,7 @@ virtual bool TransformPointToCoordSpaceForView( const gfx::PointF& point, RenderWidgetHostViewBase* target_view, - gfx::PointF* transformed_point, - viz::EventSource source = viz::EventSource::ANY); + gfx::PointF* transformed_point); // On success, returns true and modifies |*transform| to represent the // transformation mapping a point in the coordinate space of this view @@ -706,16 +703,14 @@ bool TransformPointToTargetCoordSpace(RenderWidgetHostViewBase* original_view, RenderWidgetHostViewBase* target_view, const gfx::PointF& point, - gfx::PointF* transformed_point, - viz::EventSource source) const; + gfx::PointF* transformed_point) const; // Used to transform |point| when Viz hit-test is enabled. // TransformPointToLocalCoordSpaceLegacy is used in non-Viz hit-testing. bool TransformPointToLocalCoordSpaceViz( const gfx::PointF& point, const viz::SurfaceId& original_surface, - gfx::PointF* transformed_point, - viz::EventSource source); + gfx::PointF* transformed_point); bool view_stopped_flinging_for_test() const { return view_stopped_flinging_for_test_;
diff --git a/content/browser/renderer_host/render_widget_host_view_child_frame.cc b/content/browser/renderer_host/render_widget_host_view_child_frame.cc index a563592..5492855a 100644 --- a/content/browser/renderer_host/render_widget_host_view_child_frame.cc +++ b/content/browser/renderer_host/render_widget_host_view_child_frame.cc
@@ -773,8 +773,7 @@ bool RenderWidgetHostViewChildFrame::TransformPointToCoordSpaceForView( const gfx::PointF& point, RenderWidgetHostViewBase* target_view, - gfx::PointF* transformed_point, - viz::EventSource source) { + gfx::PointF* transformed_point) { viz::SurfaceId surface_id = GetCurrentSurfaceId(); // LocalSurfaceId is not needed in Viz hit-test. if (!frame_connector_ || (!use_viz_hit_test_ && !surface_id.is_valid())) { @@ -787,7 +786,7 @@ } return frame_connector_->TransformPointToCoordSpaceForView( - point, target_view, surface_id, transformed_point, source); + point, target_view, surface_id, transformed_point); } gfx::PointF RenderWidgetHostViewChildFrame::TransformRootPointToViewCoordSpace(
diff --git a/content/browser/renderer_host/render_widget_host_view_child_frame.h b/content/browser/renderer_host/render_widget_host_view_child_frame.h index 2e92b3e..78fcdd04 100644 --- a/content/browser/renderer_host/render_widget_host_view_child_frame.h +++ b/content/browser/renderer_host/render_widget_host_view_child_frame.h
@@ -158,8 +158,7 @@ bool TransformPointToCoordSpaceForView( const gfx::PointF& point, RenderWidgetHostViewBase* target_view, - gfx::PointF* transformed_point, - viz::EventSource source = viz::EventSource::ANY) override; + gfx::PointF* transformed_point) override; void DidNavigate() override; gfx::PointF TransformRootPointToViewCoordSpace( const gfx::PointF& point) override;
diff --git a/content/browser/renderer_host/render_widget_host_view_mac.h b/content/browser/renderer_host/render_widget_host_view_mac.h index 88a2360..1b293c8 100644 --- a/content/browser/renderer_host/render_widget_host_view_mac.h +++ b/content/browser/renderer_host/render_widget_host_view_mac.h
@@ -209,8 +209,7 @@ bool TransformPointToCoordSpaceForView( const gfx::PointF& point, RenderWidgetHostViewBase* target_view, - gfx::PointF* transformed_point, - viz::EventSource source = viz::EventSource::ANY) override; + gfx::PointF* transformed_point) override; viz::FrameSinkId GetRootFrameSinkId() override; viz::SurfaceId GetCurrentSurfaceId() const override;
diff --git a/content/browser/renderer_host/render_widget_host_view_mac.mm b/content/browser/renderer_host/render_widget_host_view_mac.mm index 7bdf6790..9daf8d2 100644 --- a/content/browser/renderer_host/render_widget_host_view_mac.mm +++ b/content/browser/renderer_host/render_widget_host_view_mac.mm
@@ -1302,15 +1302,14 @@ bool RenderWidgetHostViewMac::TransformPointToCoordSpaceForView( const gfx::PointF& point, RenderWidgetHostViewBase* target_view, - gfx::PointF* transformed_point, - viz::EventSource source) { + gfx::PointF* transformed_point) { if (target_view == this) { *transformed_point = point; return true; } return target_view->TransformPointToLocalCoordSpace( - point, GetCurrentSurfaceId(), transformed_point, source); + point, GetCurrentSurfaceId(), transformed_point); } viz::FrameSinkId RenderWidgetHostViewMac::GetRootFrameSinkId() {
diff --git a/content/browser/site_per_process_hit_test_browsertest.cc b/content/browser/site_per_process_hit_test_browsertest.cc index 3387960..3daadc6 100644 --- a/content/browser/site_per_process_hit_test_browsertest.cc +++ b/content/browser/site_per_process_hit_test_browsertest.cc
@@ -900,7 +900,7 @@ parent_iframe_node->current_frame_host() ->GetRenderWidgetHost() ->GetView(), - &nested_in_parent, viz::EventSource::MOUSE); + &nested_in_parent); // Get original scroll position. double div_scroll_top_start; @@ -2758,6 +2758,16 @@ root->current_frame_host()->GetRenderWidgetHost()); observer.Wait(); } + { + MainThreadFrameObserver observer( + root->child_at(0)->current_frame_host()->GetRenderWidgetHost()); + observer.Wait(); + } + { + MainThreadFrameObserver observer( + root->child_at(1)->current_frame_host()->GetRenderWidgetHost()); + observer.Wait(); + } WaitForHitTestDataOrChildSurfaceReady(child_node1->current_frame_host()); WaitForHitTestDataOrChildSurfaceReady(child_node2->current_frame_host()); @@ -6403,17 +6413,27 @@ gfx::Rect(1, 1), device_scale_factor, device_scale_factor); expected_transform.Translate(-2 * device_scale_factor, -2 * device_scale_factor); + gfx::Rect expected_region2 = gfx::ScaleToEnclosingRect( + gfx::Rect(100, 100), device_scale_factor, device_scale_factor); + gfx::Transform expected_transform2; + expected_transform2.Translate(-52 * device_scale_factor, + -52 * device_scale_factor); - // We should not submit hit test region for iframes with pointer-events: none. - DCHECK(hit_test_data.size() == 3); - EXPECT_EQ(expected_region.ToString(), hit_test_data[2].rect.ToString()); - EXPECT_TRUE( - expected_transform.ApproximatelyEqual(hit_test_data[2].transform())); - // Non v2 hit-testing should still treat the second OOPIF as slow path. + // We should not submit hit test region for iframes with pointer-events: none + // in /2 hit-testing; we submit data in /1 but with Ignore flag set. if (features::IsVizHitTestingSurfaceLayerEnabled()) { + DCHECK(hit_test_data.size() == 3); + EXPECT_EQ(expected_region.ToString(), hit_test_data[2].rect.ToString()); + EXPECT_TRUE( + expected_transform.ApproximatelyEqual(hit_test_data[2].transform())); EXPECT_EQ(kFastHitTestFlags, hit_test_data[2].flags); - } else { - EXPECT_EQ(kSlowHitTestFlags, hit_test_data[2].flags); + } else if (features::IsVizHitTestingDrawQuadEnabled()) { + DCHECK(hit_test_data.size() == 4); + EXPECT_EQ(expected_region2.ToString(), hit_test_data[3].rect.ToString()); + EXPECT_TRUE( + expected_transform2.ApproximatelyEqual(hit_test_data[3].transform())); + EXPECT_EQ(kSlowHitTestFlags | viz::HitTestRegionFlags::kHitTestIgnore, + hit_test_data[3].flags); } // Check that an update on the css property can trigger an update in submitted @@ -6435,6 +6455,16 @@ root->current_frame_host()->GetRenderWidgetHost()); observer.Wait(); } + { + MainThreadFrameObserver observer( + root->child_at(0)->current_frame_host()->GetRenderWidgetHost()); + observer.Wait(); + } + { + MainThreadFrameObserver observer( + root->child_at(1)->current_frame_host()->GetRenderWidgetHost()); + observer.Wait(); + } WaitForHitTestDataOrChildSurfaceReady( root->child_at(0)->current_frame_host()); @@ -6446,12 +6476,6 @@ hit_test_data = observer.GetHitTestData(); MaybeStripHitTestData(&hit_test_data); - gfx::Rect expected_region2 = gfx::ScaleToEnclosingRect( - gfx::Rect(100, 100), device_scale_factor, device_scale_factor); - gfx::Transform expected_transform2; - expected_transform2.Translate(-52 * device_scale_factor, - -52 * device_scale_factor); - DCHECK(hit_test_data.size() == 4); EXPECT_EQ(expected_region.ToString(), hit_test_data[2].rect.ToString()); EXPECT_TRUE(
diff --git a/content/browser/speech/tts_win.cc b/content/browser/speech/tts_win.cc index ddddb25..e4eb7748 100644 --- a/content/browser/speech/tts_win.cc +++ b/content/browser/speech/tts_win.cc
@@ -139,8 +139,9 @@ stream_number_ = 0; if (IsSpeaking()) { - // Stop speech by speaking the empty string with the purge flag. - speech_synthesizer_->Speak(L"", SPF_ASYNC | SPF_PURGEBEFORESPEAK, NULL); + // Stop speech by speaking nullptr with the purge flag. + speech_synthesizer_->Speak(nullptr, SPF_ASYNC | SPF_PURGEBEFORESPEAK, + NULL); } if (paused_) { speech_synthesizer_->Resume();
diff --git a/content/browser/webrtc/webrtc_video_capture_service_enumeration_browsertest.cc b/content/browser/webrtc/webrtc_video_capture_service_enumeration_browsertest.cc index baf2e0e..725df9a 100644 --- a/content/browser/webrtc/webrtc_video_capture_service_enumeration_browsertest.cc +++ b/content/browser/webrtc/webrtc_video_capture_service_enumeration_browsertest.cc
@@ -20,6 +20,7 @@ #include "services/video_capture/public/mojom/constants.mojom.h" #include "services/video_capture/public/mojom/device_factory.mojom.h" #include "services/video_capture/public/mojom/device_factory_provider.mojom.h" +#include "services/video_capture/public/mojom/devices_changed_observer.mojom.h" #include "services/video_capture/public/mojom/virtual_device.mojom.h" namespace content {
diff --git a/content/browser/webrtc/webrtc_video_capture_shared_device_browsertest.cc b/content/browser/webrtc/webrtc_video_capture_shared_device_browsertest.cc new file mode 100644 index 0000000..bdad1dd --- /dev/null +++ b/content/browser/webrtc/webrtc_video_capture_shared_device_browsertest.cc
@@ -0,0 +1,174 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/command_line.h" +#include "base/run_loop.h" +#include "base/test/scoped_feature_list.h" +#include "content/public/common/content_features.h" +#include "content/public/common/content_switches.h" +#include "content/public/common/service_manager_connection.h" +#include "content/public/test/browser_test_utils.h" +#include "content/public/test/content_browser_test.h" +#include "content/public/test/content_browser_test_utils.h" +#include "media/base/media_switches.h" +#include "services/service_manager/public/cpp/connector.h" +#include "services/video_capture/public/cpp/mock_receiver.h" +#include "services/video_capture/public/mojom/constants.mojom.h" +#include "services/video_capture/public/mojom/device_factory_provider.mojom.h" +#include "services/video_capture/public/mojom/video_source.mojom.h" +#include "services/video_capture/public/mojom/video_source_provider.mojom.h" +#include "testing/gmock/include/gmock/gmock.h" + +using testing::_; +using testing::AtLeast; +using testing::InvokeWithoutArgs; +using testing::Return; + +namespace content { + +namespace { + +static const char kVideoCaptureHtmlFile[] = "/media/video_capture_test.html"; +static const char kStartVideoCaptureAndVerify[] = + "startVideoCaptureAndVerifySize(%d, %d)"; +static const gfx::Size kVideoSize(320, 200); + +} // namespace + +// Integration test sets up a single fake device and obtains a connection to the +// video capture service via the Browser process' service manager. It then +// opens the device from clients. One client is the test calling into the +// video capture service directly. The second client is the Browser, which the +// test exercises through JavaScript. +class WebRtcVideoCaptureSharedDeviceBrowserTest : public ContentBrowserTest { + public: + WebRtcVideoCaptureSharedDeviceBrowserTest() : weak_factory_(this) { + scoped_feature_list_.InitAndEnableFeature(features::kMojoVideoCapture); + } + + ~WebRtcVideoCaptureSharedDeviceBrowserTest() override {} + + void OpenDeviceViaService(base::OnceClosure done_cb) { + connector_->BindInterface(video_capture::mojom::kServiceName, + &device_factory_provider_); + device_factory_provider_->ConnectToVideoSourceProvider( + mojo::MakeRequest(&video_source_provider_)); + + video_source_provider_->GetSourceInfos(base::BindOnce( + &WebRtcVideoCaptureSharedDeviceBrowserTest::OnSourceInfosReceived, + weak_factory_.GetWeakPtr(), std::move(done_cb))); + } + + void OpenDeviceInRendererAndWaitForPlaying() { + DCHECK(main_task_runner_->RunsTasksInCurrentSequence()); + embedded_test_server()->StartAcceptingConnections(); + GURL url(embedded_test_server()->GetURL(kVideoCaptureHtmlFile)); + NavigateToURL(shell(), url); + + const std::string javascript_to_execute = base::StringPrintf( + kStartVideoCaptureAndVerify, kVideoSize.width(), kVideoSize.height()); + std::string result; + // Start video capture and wait until it started rendering + ASSERT_TRUE( + ExecuteScriptAndExtractString(shell(), javascript_to_execute, &result)); + ASSERT_EQ("OK", result); + } + + protected: + void SetUpCommandLine(base::CommandLine* command_line) override { + command_line->AppendSwitch(switches::kUseFakeDeviceForMediaStream); + command_line->AppendSwitch(switches::kUseFakeUIForMediaStream); + } + + void SetUp() override { + ASSERT_TRUE(embedded_test_server()->InitializeAndListen()); + EnablePixelOutput(); + ContentBrowserTest::SetUp(); + } + + void Initialize() { + DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); + main_task_runner_ = base::ThreadTaskRunnerHandle::Get(); + + auto* connection = content::ServiceManagerConnection::GetForProcess(); + ASSERT_TRUE(connection); + auto* connector = connection->GetConnector(); + ASSERT_TRUE(connector); + // We need to clone it so that we can use the clone on a different thread. + connector_ = connector->Clone(); + + mock_receiver_ = std::make_unique<video_capture::MockReceiver>( + mojo::MakeRequest(&receiver_proxy_)); + } + + scoped_refptr<base::TaskRunner> main_task_runner_; + std::unique_ptr<service_manager::Connector> connector_; + std::unique_ptr<video_capture::MockReceiver> mock_receiver_; + + private: + void OnSourceInfosReceived( + base::OnceClosure done_cb, + const std::vector<media::VideoCaptureDeviceInfo>& infos) { + ASSERT_FALSE(infos.empty()); + video_source_provider_->GetVideoSource(infos[0].descriptor.device_id, + mojo::MakeRequest(&video_source_)); + + media::VideoCaptureParams requestable_settings; + ASSERT_FALSE(infos[0].supported_formats.empty()); + requestable_settings.requested_format = infos[0].supported_formats[0]; + requestable_settings.requested_format.frame_size = kVideoSize; + + video_capture::mojom::PushVideoStreamSubscriptionPtr subscription; + video_source_->CreatePushSubscription( + std::move(receiver_proxy_), requestable_settings, + false /*force_reopen_with_new_settings*/, + mojo::MakeRequest(&subscription_), + base::BindOnce(&WebRtcVideoCaptureSharedDeviceBrowserTest:: + OnCreatePushSubscriptionCallback, + weak_factory_.GetWeakPtr(), std::move(done_cb))); + } + + void OnCreatePushSubscriptionCallback( + base::OnceClosure done_cb, + video_capture::mojom::CreatePushSubscriptionResultCode result_code, + const media::VideoCaptureParams& params) { + ASSERT_EQ(video_capture::mojom::CreatePushSubscriptionResultCode:: + kCreatedWithRequestedSettings, + result_code); + subscription_->Activate(); + std::move(done_cb).Run(); + } + + base::test::ScopedFeatureList scoped_feature_list_; + video_capture::mojom::DeviceFactoryProviderPtr device_factory_provider_; + video_capture::mojom::VideoSourceProviderPtr video_source_provider_; + video_capture::mojom::VideoSourcePtr video_source_; + video_capture::mojom::PushVideoStreamSubscriptionPtr subscription_; + video_capture::mojom::ReceiverPtr receiver_proxy_; + base::WeakPtrFactory<WebRtcVideoCaptureSharedDeviceBrowserTest> weak_factory_; + + DISALLOW_COPY_AND_ASSIGN(WebRtcVideoCaptureSharedDeviceBrowserTest); +}; + +IN_PROC_BROWSER_TEST_F(WebRtcVideoCaptureSharedDeviceBrowserTest, + ReceiveFrameFromServiceAndInRenderer) { + Initialize(); + + base::RunLoop receive_frame_from_service_wait_loop; + EXPECT_CALL(*mock_receiver_, DoOnFrameReadyInBuffer(_, _, _, _)) + .WillOnce(InvokeWithoutArgs([&receive_frame_from_service_wait_loop]() { + receive_frame_from_service_wait_loop.Quit(); + })) + .WillRepeatedly(Return()); + + base::RunLoop open_device_via_service_run_loop; + OpenDeviceViaService(open_device_via_service_run_loop.QuitClosure()); + open_device_via_service_run_loop.Run(); + + OpenDeviceInRendererAndWaitForPlaying(); + + receive_frame_from_service_wait_loop.Run(); +} + +} // namespace content
diff --git a/content/child/dwrite_font_proxy/dwrite_font_proxy_win.cc b/content/child/dwrite_font_proxy/dwrite_font_proxy_win.cc index 1a5e02e..02a70ce 100644 --- a/content/child/dwrite_font_proxy/dwrite_font_proxy_win.cc +++ b/content/child/dwrite_font_proxy/dwrite_font_proxy_win.cc
@@ -92,7 +92,7 @@ DCHECK(family_name); DCHECK(index); DCHECK(exists); - TRACE_EVENT0("dwrite", "FontProxy::FindFamilyName"); + TRACE_EVENT0("dwrite,fonts", "FontProxy::FindFamilyName"); uint32_t family_index = 0; base::string16 name(family_name); @@ -145,7 +145,7 @@ if (family_count_ != UINT_MAX) return family_count_; - TRACE_EVENT0("dwrite", "FontProxy::GetFontFamilyCount"); + TRACE_EVENT0("dwrite,fonts", "FontProxy::GetFontFamilyCount"); uint32_t family_count = 0; if (!GetFontProxy().GetFamilyCount(&family_count)) { @@ -185,7 +185,7 @@ return E_INVALIDARG; } - TRACE_EVENT0("dwrite", "FontProxy::LoadingFontFiles"); + TRACE_EVENT0("dwrite,fonts", "FontProxy::LoadingFontFiles"); const uint32_t* family_index = reinterpret_cast<const uint32_t*>(collection_key); @@ -241,7 +241,7 @@ return E_FAIL; } - TRACE_EVENT0("dwrite", "FontFileEnumerator::CreateStreamFromKey"); + TRACE_EVENT0("dwrite,fonts", "FontFileEnumerator::CreateStreamFromKey"); HANDLE file_handle = *reinterpret_cast<const HANDLE*>(font_file_reference_key); @@ -287,7 +287,7 @@ bool DWriteFontCollectionProxy::LoadFamily( UINT32 family_index, IDWriteFontCollection** containing_collection) { - TRACE_EVENT0("dwrite", "FontProxy::LoadFamily"); + TRACE_EVENT0("dwrite,fonts", "FontProxy::LoadFamily"); uint32_t index = family_index; // CreateCustomFontCollection ends up calling @@ -318,7 +318,7 @@ bool DWriteFontCollectionProxy::LoadFamilyNames( UINT32 family_index, IDWriteLocalizedStrings** localized_strings) { - TRACE_EVENT0("dwrite", "FontProxy::LoadFamilyNames"); + TRACE_EVENT0("dwrite,fonts", "FontProxy::LoadFamilyNames"); std::vector<blink::mojom::DWriteStringPairPtr> pairs; if (!GetFontProxy().GetFamilyNames(family_index, &pairs)) { @@ -434,7 +434,7 @@ return S_OK; } - TRACE_EVENT0("dwrite", "FontProxy::GetFamilyNames"); + TRACE_EVENT0("dwrite,fonts", "FontProxy::GetFamilyNames"); // Otherwise, do the IPC. if (!proxy_collection_->LoadFamilyNames(family_index_, &family_names_)) @@ -569,7 +569,7 @@ return E_FAIL; } - TRACE_EVENT0("dwrite", "FontFileEnumerator::GetCurrentFontFile"); + TRACE_EVENT0("dwrite,fonts", "FontFileEnumerator::GetCurrentFontFile"); // CreateCustomFontFileReference ends up calling // DWriteFontCollectionProxy::CreateStreamFromKey. @@ -584,7 +584,7 @@ HRESULT FontFileEnumerator::MoveNext(BOOL* has_current_file) { DCHECK(has_current_file); - TRACE_EVENT0("dwrite", "FontFileEnumerator::MoveNext"); + TRACE_EVENT0("dwrite,fonts", "FontFileEnumerator::MoveNext"); if (next_file_ >= files_.size()) { *has_current_file = FALSE; current_file_ = UINT_MAX;
diff --git a/content/child/dwrite_font_proxy/font_fallback_win.cc b/content/child/dwrite_font_proxy/font_fallback_win.cc index a2619d6..79e3af1 100644 --- a/content/child/dwrite_font_proxy/font_fallback_win.cc +++ b/content/child/dwrite_font_proxy/font_fallback_win.cc
@@ -87,7 +87,7 @@ return S_OK; } - TRACE_EVENT0("dwrite", "FontFallback::MapCharacters (IPC)"); + TRACE_EVENT0("dwrite,fonts", "FontFallback::MapCharacters (IPC)"); const WCHAR* locale = nullptr; // |locale_text_length| is actually the length of text with the locale, not @@ -168,7 +168,7 @@ if (it == fallback_family_cache_.end()) return false; - TRACE_EVENT0("dwrite", "FontFallback::GetCachedFont"); + TRACE_EVENT0("dwrite,fonts", "FontFallback::GetCachedFont"); std::list<mswr::ComPtr<IDWriteFontFamily>>& family_list = it->second; std::list<mswr::ComPtr<IDWriteFontFamily>>::iterator family_iterator;
diff --git a/content/renderer/accessibility/render_accessibility_impl.cc b/content/renderer/accessibility/render_accessibility_impl.cc index bdcfe2c..4ecbd4a 100644 --- a/content/renderer/accessibility/render_accessibility_impl.cc +++ b/content/renderer/accessibility/render_accessibility_impl.cc
@@ -713,8 +713,12 @@ case ax::mojom::Action::kAnnotatePageImages: // Ensure we aren't already labeling images, in which case this should // not change. - if (!ax_image_annotator_) + if (!ax_image_annotator_) { CreateAXImageAnnotator(); + // Walk the tree to discover images, and mark them dirty so that + // they get added to the annotator. + MarkAllAXObjectsDirty(ax::mojom::Role::kImage); + } break; } } @@ -881,6 +885,24 @@ } } +void RenderAccessibilityImpl::MarkAllAXObjectsDirty(ax::mojom::Role role) { + ScopedFreezeBlinkAXTreeSource freeze(&tree_source_); + base::queue<WebAXObject> objs_to_explore; + objs_to_explore.push(tree_source_.GetRoot()); + while (objs_to_explore.size()) { + WebAXObject obj = objs_to_explore.front(); + objs_to_explore.pop(); + + if (obj.Role() == role) + MarkWebAXObjectDirty(obj, /* subtree */ false); + + std::vector<blink::WebAXObject> children; + tree_source_.GetChildren(obj, &children); + for (size_t i = 0; i < children.size(); ++i) + objs_to_explore.push(children[i]); + } +} + void RenderAccessibilityImpl::Scroll(const WebAXObject& target, ax::mojom::Action scroll_action) { WebAXObject offset_container;
diff --git a/content/renderer/accessibility/render_accessibility_impl.h b/content/renderer/accessibility/render_accessibility_impl.h index 7ae0682..3e0e89df 100644 --- a/content/renderer/accessibility/render_accessibility_impl.h +++ b/content/renderer/accessibility/render_accessibility_impl.h
@@ -149,6 +149,9 @@ // any automatic annotations that might have been added before. void StartOrStopLabelingImages(ui::AXMode old_mode, ui::AXMode new_mode); + // Marks all AXObjects with the given role in the current tree dirty. + void MarkAllAXObjectsDirty(ax::mojom::Role role); + void Scroll(const blink::WebAXObject& target, ax::mojom::Action scroll_action); void ScrollPlugin(int id_to_make_visible);
diff --git a/content/renderer/input/frame_input_handler_impl.cc b/content/renderer/input/frame_input_handler_impl.cc index ec3f18c..3e1a0a5 100644 --- a/content/renderer/input/frame_input_handler_impl.cc +++ b/content/renderer/input/frame_input_handler_impl.cc
@@ -7,7 +7,6 @@ #include <utility> #include "base/bind.h" -#include "base/debug/stack_trace.h" #include "base/logging.h" #include "content/common/input/ime_text_span_conversions.h" #include "content/renderer/compositor/layer_tree_view.h"
diff --git a/content/renderer/loader/resource_dispatcher.cc b/content/renderer/loader/resource_dispatcher.cc index 469d36f..ff6102c 100644 --- a/content/renderer/loader/resource_dispatcher.cc +++ b/content/renderer/loader/resource_dispatcher.cc
@@ -12,7 +12,6 @@ #include "base/bind.h" #include "base/compiler_specific.h" #include "base/debug/alias.h" -#include "base/debug/stack_trace.h" #include "base/files/file_path.h" #include "base/metrics/histogram_macros.h" #include "base/rand_util.h"
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn index 6b176a19..f684bf4f 100644 --- a/content/test/BUILD.gn +++ b/content/test/BUILD.gn
@@ -935,6 +935,7 @@ "../browser/webrtc/webrtc_video_capture_browsertest.cc", "../browser/webrtc/webrtc_video_capture_service_browsertest.cc", "../browser/webrtc/webrtc_video_capture_service_enumeration_browsertest.cc", + "../browser/webrtc/webrtc_video_capture_shared_device_browsertest.cc", "../browser/webrtc/webrtc_webcam_browsertest.cc", "../browser/webrtc/webrtc_webcam_browsertest.h", "../browser/webui/web_ui_mojo_browsertest.cc", @@ -1030,6 +1031,7 @@ "//services/service_manager/public/cpp", "//services/test/echo/public/mojom", "//services/video_capture/public/cpp", + "//services/video_capture/public/cpp:mocks", "//services/video_capture/public/mojom:constants", "//services/viz/privileged/interfaces", "//services/ws/public/cpp/gpu",
diff --git a/content/test/content_test_launcher.cc b/content/test/content_test_launcher.cc index 5bbbbb0..8e9076f 100644 --- a/content/test/content_test_launcher.cc +++ b/content/test/content_test_launcher.cc
@@ -6,7 +6,6 @@ #include "base/base_paths.h" #include "base/command_line.h" -#include "base/debug/stack_trace.h" #include "base/i18n/icu_util.h" #include "base/logging.h" #include "base/macros.h"
diff --git a/content/test/data/accessibility/html/table-headers-empty-first-cell-expected-blink.txt b/content/test/data/accessibility/html/table-headers-empty-first-cell-expected-blink.txt new file mode 100644 index 0000000..f4b32d0 --- /dev/null +++ b/content/test/data/accessibility/html/table-headers-empty-first-cell-expected-blink.txt
@@ -0,0 +1,98 @@ +rootWebArea name='Table example - headers with empty first cell' +++table name='Delivery slots:' +++++caption +++++++staticText name='Delivery slots:' +++++++++inlineTextBox name='Delivery slots:' +++++row +++++++cell +++++++columnHeader name='Monday' +++++++++staticText name='Monday' +++++++++++inlineTextBox name='Monday' +++++++columnHeader name='Tuesday' +++++++++staticText name='Tuesday' +++++++++++inlineTextBox name='Tuesday' +++++++columnHeader name='Wednesday' +++++++++staticText name='Wednesday' +++++++++++inlineTextBox name='Wednesday' +++++++columnHeader name='Thursday' +++++++++staticText name='Thursday' +++++++++++inlineTextBox name='Thursday' +++++++columnHeader name='Friday' +++++++++staticText name='Friday' +++++++++++inlineTextBox name='Friday' +++++row +++++++rowHeader name='09:00 - 11:00' +++++++++staticText name='09:00 - 11:00' +++++++++++inlineTextBox name='09:00 - 11:00' +++++++cell name='Closed' +++++++++staticText name='Closed' +++++++++++inlineTextBox name='Closed' +++++++cell name='Open' +++++++++staticText name='Open' +++++++++++inlineTextBox name='Open' +++++++cell name='Open' +++++++++staticText name='Open' +++++++++++inlineTextBox name='Open' +++++++cell name='Closed' +++++++++staticText name='Closed' +++++++++++inlineTextBox name='Closed' +++++++cell name='Closed' +++++++++staticText name='Closed' +++++++++++inlineTextBox name='Closed' +++++row +++++++rowHeader name='11:00 - 13:00' +++++++++staticText name='11:00 - 13:00' +++++++++++inlineTextBox name='11:00 - 13:00' +++++++cell name='Open' +++++++++staticText name='Open' +++++++++++inlineTextBox name='Open' +++++++cell name='Open' +++++++++staticText name='Open' +++++++++++inlineTextBox name='Open' +++++++cell name='Closed' +++++++++staticText name='Closed' +++++++++++inlineTextBox name='Closed' +++++++cell name='Closed' +++++++++staticText name='Closed' +++++++++++inlineTextBox name='Closed' +++++++cell name='Closed' +++++++++staticText name='Closed' +++++++++++inlineTextBox name='Closed' +++++row +++++++rowHeader name='13:00 - 15:00' +++++++++staticText name='13:00 - 15:00' +++++++++++inlineTextBox name='13:00 - 15:00' +++++++cell name='Open' +++++++++staticText name='Open' +++++++++++inlineTextBox name='Open' +++++++cell name='Open' +++++++++staticText name='Open' +++++++++++inlineTextBox name='Open' +++++++cell name='Open' +++++++++staticText name='Open' +++++++++++inlineTextBox name='Open' +++++++cell name='Closed' +++++++++staticText name='Closed' +++++++++++inlineTextBox name='Closed' +++++++cell name='Closed' +++++++++staticText name='Closed' +++++++++++inlineTextBox name='Closed' +++++row +++++++rowHeader name='15:00 - 17:00' +++++++++staticText name='15:00 - 17:00' +++++++++++inlineTextBox name='15:00 - 17:00' +++++++cell name='Closed' +++++++++staticText name='Closed' +++++++++++inlineTextBox name='Closed' +++++++cell name='Closed' +++++++++staticText name='Closed' +++++++++++inlineTextBox name='Closed' +++++++cell name='Closed' +++++++++staticText name='Closed' +++++++++++inlineTextBox name='Closed' +++++++cell name='Open' +++++++++staticText name='Open' +++++++++++inlineTextBox name='Open' +++++++cell name='Open' +++++++++staticText name='Open' +++++++++++inlineTextBox name='Open'
diff --git a/content/test/data/accessibility/html/table-headers-empty-first-cell.html b/content/test/data/accessibility/html/table-headers-empty-first-cell.html new file mode 100644 index 0000000..a043d58 --- /dev/null +++ b/content/test/data/accessibility/html/table-headers-empty-first-cell.html
@@ -0,0 +1,52 @@ +<!DOCTYPE html> +<html> +<head> + <title>Table example - headers with empty first cell</title> +</head> +<body> +<table border="1"> + <caption>Delivery slots:</caption> + <tbody> + <tr> + <td></td> + <th>Monday</th> + <th>Tuesday</th> + <th>Wednesday</th> + <th>Thursday</th> + <th>Friday</th> + </tr> + <tr> + <th>09:00 - 11:00</th> + <td>Closed</td> + <td>Open</td> + <td>Open</td> + <td>Closed</td> + <td>Closed</td> + </tr> + <tr> + <th>11:00 - 13:00</th> + <td>Open</td> + <td>Open</td> + <td>Closed</td> + <td>Closed</td> + <td>Closed</td> + </tr> + <tr> + <th>13:00 - 15:00</th> + <td>Open</td> + <td>Open</td> + <td>Open</td> + <td>Closed</td> + <td>Closed</td> + </tr> + <tr> + <th>15:00 - 17:00</th> + <td>Closed</td> + <td>Closed</td> + <td>Closed</td> + <td>Open</td> + <td>Open</td> + </tr> + </tbody> +</table> +</html>
diff --git a/content/test/data/accessibility/html/table-headers-on-all-sides-expected-blink.txt b/content/test/data/accessibility/html/table-headers-on-all-sides-expected-blink.txt new file mode 100644 index 0000000..4197d8c --- /dev/null +++ b/content/test/data/accessibility/html/table-headers-on-all-sides-expected-blink.txt
@@ -0,0 +1,46 @@ +rootWebArea name='Table example - headers on all sides' +++table +++++row +++++++cell +++++++columnHeader name='Red' +++++++++staticText name='Red' +++++++++++inlineTextBox name='Red' +++++++columnHeader name='Green' +++++++++staticText name='Green' +++++++++++inlineTextBox name='Green' +++++++cell +++++row +++++++rowHeader name='Fruit' +++++++++staticText name='Fruit' +++++++++++inlineTextBox name='Fruit' +++++++cell name='strawberry' +++++++++staticText name='strawberry' +++++++++++inlineTextBox name='strawberry' +++++++cell name='lime' +++++++++staticText name='lime' +++++++++++inlineTextBox name='lime' +++++++rowHeader name='Fruit' +++++++++staticText name='Fruit' +++++++++++inlineTextBox name='Fruit' +++++row +++++++rowHeader name='Veggies' +++++++++staticText name='Veggies' +++++++++++inlineTextBox name='Veggies' +++++++cell name='radish' +++++++++staticText name='radish' +++++++++++inlineTextBox name='radish' +++++++cell name='spinach' +++++++++staticText name='spinach' +++++++++++inlineTextBox name='spinach' +++++++rowHeader name='Veggies' +++++++++staticText name='Veggies' +++++++++++inlineTextBox name='Veggies' +++++row +++++++cell +++++++columnHeader name='Red' +++++++++staticText name='Red' +++++++++++inlineTextBox name='Red' +++++++columnHeader name='Green' +++++++++staticText name='Green' +++++++++++inlineTextBox name='Green' +++++++cell
diff --git a/content/test/data/accessibility/html/table-headers-on-all-sides.html b/content/test/data/accessibility/html/table-headers-on-all-sides.html new file mode 100644 index 0000000..0f4bb487 --- /dev/null +++ b/content/test/data/accessibility/html/table-headers-on-all-sides.html
@@ -0,0 +1,33 @@ +<!DOCTYPE html> +<html> +<head> + <title>Table example - headers on all sides</title> +</head> +<body> +<table border=1> + <tr> + <td></td> + <th>Red</th> + <th>Green</th> + <td></td> + </tr> + <tr> + <th>Fruit</th> + <td>strawberry</td> + <td>lime</td> + <th>Fruit</th> + </tr> + <tr> + <th>Veggies</th> + <td>radish</td> + <td>spinach</td> + <th>Veggies</th> + </tr> + <tr> + <td></td> + <th>Red</th> + <th>Green</th> + <td></td> + </tr> +</table> +</html>
diff --git a/content/test/data/accessibility/html/table-multiple-row-and-column-headers-expected-blink.txt b/content/test/data/accessibility/html/table-multiple-row-and-column-headers-expected-blink.txt new file mode 100644 index 0000000..fb22679 --- /dev/null +++ b/content/test/data/accessibility/html/table-multiple-row-and-column-headers-expected-blink.txt
@@ -0,0 +1,93 @@ +rootWebArea name='Table example - multiple row and column headers' +++table +++++row +++++++cell +++++++columnHeader name='Mars' +++++++++staticText name='Mars' +++++++++++inlineTextBox name='Mars' +++++++columnHeader name='Venus' +++++++++staticText name='Venus' +++++++++++inlineTextBox name='Venus' +++++row +++++++columnHeader name='Produced' +++++++++staticText name='Produced' +++++++++++inlineTextBox name='Produced' +++++++columnHeader name='Sold' +++++++++staticText name='Sold' +++++++++++inlineTextBox name='Sold' +++++++columnHeader name='Produced' +++++++++staticText name='Produced' +++++++++++inlineTextBox name='Produced' +++++++columnHeader name='Sold' +++++++++staticText name='Sold' +++++++++++inlineTextBox name='Sold' +++++row +++++++rowHeader name='For Toddlers' +++++++++staticText name='For Toddlers' +++++++++++inlineTextBox name='For Toddlers' +++++++rowHeader name='Teddy Bears' +++++++++staticText name='Teddy Bears' +++++++++++inlineTextBox name='Teddy Bears' +++++++cell name='50,000' +++++++++staticText name='50,000' +++++++++++inlineTextBox name='50,000' +++++++cell name='30,000' +++++++++staticText name='30,000' +++++++++++inlineTextBox name='30,000' +++++++cell name='100,000' +++++++++staticText name='100,000' +++++++++++inlineTextBox name='100,000' +++++++cell name='80,000' +++++++++staticText name='80,000' +++++++++++inlineTextBox name='80,000' +++++row +++++++rowHeader name='Action Figures' +++++++++staticText name='Action Figures' +++++++++++inlineTextBox name='Action Figures' +++++++cell name='25,000' +++++++++staticText name='25,000' +++++++++++inlineTextBox name='25,000' +++++++cell name='15,000' +++++++++staticText name='15,000' +++++++++++inlineTextBox name='15,000' +++++++cell name='50,000' +++++++++staticText name='50,000' +++++++++++inlineTextBox name='50,000' +++++++cell name='40,000' +++++++++staticText name='40,000' +++++++++++inlineTextBox name='40,000' +++++row +++++++rowHeader name='For Teens' +++++++++staticText name='For Teens' +++++++++++inlineTextBox name='For Teens' +++++++rowHeader name='Board Games' +++++++++staticText name='Board Games' +++++++++++inlineTextBox name='Board Games' +++++++cell name='5,000' +++++++++staticText name='5,000' +++++++++++inlineTextBox name='5,000' +++++++cell name='2,000' +++++++++staticText name='2,000' +++++++++++inlineTextBox name='2,000' +++++++cell name='6,000' +++++++++staticText name='6,000' +++++++++++inlineTextBox name='6,000' +++++++cell name='4,000' +++++++++staticText name='4,000' +++++++++++inlineTextBox name='4,000' +++++row +++++++rowHeader name='Video Games' +++++++++staticText name='Video Games' +++++++++++inlineTextBox name='Video Games' +++++++cell name='10,000' +++++++++staticText name='10,000' +++++++++++inlineTextBox name='10,000' +++++++cell name='5,000' +++++++++staticText name='5,000' +++++++++++inlineTextBox name='5,000' +++++++cell name='12,000' +++++++++staticText name='12,000' +++++++++++inlineTextBox name='12,000' +++++++cell name='9,000' +++++++++staticText name='9,000' +++++++++++inlineTextBox name='9,000'
diff --git a/content/test/data/accessibility/html/table-multiple-row-and-column-headers.html b/content/test/data/accessibility/html/table-multiple-row-and-column-headers.html new file mode 100644 index 0000000..ced62e2 --- /dev/null +++ b/content/test/data/accessibility/html/table-multiple-row-and-column-headers.html
@@ -0,0 +1,51 @@ +<!DOCTYPE html> +<html> +<head> + <title>Table example - multiple row and column headers</title> +</head> +<body> +<table border=1> + <tr> + <td rowspan="2" colspan="2"></td> + <th colspan="2">Mars</th> + <th colspan="2">Venus</th> + </tr> + <tr> + <th>Produced</th> + <th>Sold</th> + <th>Produced</th> + <th>Sold</th> + </tr> + <tr> + <th rowspan="2">For Toddlers</th> + <th>Teddy Bears</th> + <td>50,000</td> + <td>30,000</td> + <td>100,000</td> + <td>80,000</td> + </tr> + <tr> + <th>Action Figures</th> + <td>25,000</td> + <td>15,000</td> + <td>50,000</td> + <td>40,000</td> + </tr> + <tr> + <th rowspan="2">For Teens</th> + <th>Board Games</th> + <td>5,000</td> + <td>2,000</td> + <td>6,000</td> + <td>4,000</td> + </tr> + <tr> + <th>Video Games</th> + <td>10,000</td> + <td>5,000</td> + <td>12,000</td> + <td>9,000</td> + </tr> +</table> +</body> +</html>
diff --git a/content/test/gpu/gpu_tests/webgl_conformance_expectations.py b/content/test/gpu/gpu_tests/webgl_conformance_expectations.py index 70edbd0..fb67954 100644 --- a/content/test/gpu/gpu_tests/webgl_conformance_expectations.py +++ b/content/test/gpu/gpu_tests/webgl_conformance_expectations.py
@@ -467,8 +467,6 @@ ['win', 'passthrough', 'vulkan'], bug=2887) # ANGLE bug ID self.Fail('WebglExtension_EXT_shader_texture_lod', ['win', 'passthrough', 'vulkan'], bug=2899) # ANGLE bug ID - self.Fail('WebglExtension_EXT_sRGB', - ['win', 'passthrough', 'vulkan'], bug=2900) # ANGLE bug ID self.Fail('WebglExtension_OES_element_index_uint', ['win', 'passthrough', 'vulkan'], bug=2902) # ANGLE bug ID self.Fail('WebglExtension_OES_standard_derivatives',
diff --git a/content/test/test_render_frame.cc b/content/test/test_render_frame.cc index dc51c77..6f60b98 100644 --- a/content/test/test_render_frame.cc +++ b/content/test/test_render_frame.cc
@@ -9,7 +9,6 @@ #include <vector> #include "base/bind_helpers.h" -#include "base/debug/stack_trace.h" #include "base/threading/thread_task_runner_handle.h" #include "build/build_config.h" #include "content/common/frame_messages.h"
diff --git a/docs/infra/cq_builders.md b/docs/infra/cq_builders.md index 65a4bb3c3..8c7833f 100644 --- a/docs/infra/cq_builders.md +++ b/docs/infra/cq_builders.md
@@ -82,6 +82,22 @@ `android_optional_gpu_tests_rel`, due to the `location_regexp` values for that builder. +* [android_compile_x64_dbg](https://ci.chromium.org/p/chromium/builders/luci.chromium.try/android_compile_x64_dbg) ([`commit-queue.cfg` entry](https://cs.chromium.org/search/?q=package:%5Echromium$+file:commit-queue.cfg+chromium/try/android_compile_x64_dbg)) ([matching builders](https://cs.chromium.org/search/?q=file:trybots.py+android_compile_x64_dbg)) + + Path regular expressions: + * [`//sandbox/linux/seccomp-bpf/.+`](https://cs.chromium.org/chromium/src/sandbox/linux/seccomp-bpf/) + * [`//sandbox/linux/seccomp-bpf-helpers/.+`](https://cs.chromium.org/chromium/src/sandbox/linux/seccomp-bpf-helpers/) + * [`//sandbox/linux/system_headers/.+`](https://cs.chromium.org/chromium/src/sandbox/linux/system_headers/) + * [`//sandbox/linux/tests/.+`](https://cs.chromium.org/chromium/src/sandbox/linux/tests/) + +* [android_compile_x86_dbg](https://ci.chromium.org/p/chromium/builders/luci.chromium.try/android_compile_x86_dbg) ([`commit-queue.cfg` entry](https://cs.chromium.org/search/?q=package:%5Echromium$+file:commit-queue.cfg+chromium/try/android_compile_x86_dbg)) ([matching builders](https://cs.chromium.org/search/?q=file:trybots.py+android_compile_x86_dbg)) + + Path regular expressions: + * [`//sandbox/linux/seccomp-bpf/.+`](https://cs.chromium.org/chromium/src/sandbox/linux/seccomp-bpf/) + * [`//sandbox/linux/seccomp-bpf-helpers/.+`](https://cs.chromium.org/chromium/src/sandbox/linux/seccomp-bpf-helpers/) + * [`//sandbox/linux/system_headers/.+`](https://cs.chromium.org/chromium/src/sandbox/linux/system_headers/) + * [`//sandbox/linux/tests/.+`](https://cs.chromium.org/chromium/src/sandbox/linux/tests/) + * [android_optional_gpu_tests_rel](https://ci.chromium.org/p/chromium/builders/luci.chromium.try/android_optional_gpu_tests_rel) ([`commit-queue.cfg` entry](https://cs.chromium.org/search/?q=package:%5Echromium$+file:commit-queue.cfg+chromium/try/android_optional_gpu_tests_rel)) ([matching builders](https://cs.chromium.org/search/?q=file:trybots.py+android_optional_gpu_tests_rel)) Path regular expressions:
diff --git a/extensions/browser/api/declarative_net_request/rules_monitor_service.cc b/extensions/browser/api/declarative_net_request/rules_monitor_service.cc index 9ecf4e2..eae1c27 100644 --- a/extensions/browser/api/declarative_net_request/rules_monitor_service.cc +++ b/extensions/browser/api/declarative_net_request/rules_monitor_service.cc
@@ -62,6 +62,79 @@ info_map->GetRulesetManager()->RemoveRuleset(extension_id); } +// A helper class to hold the data relating to the loading of a single ruleset. +class RulesetInfo { + public: + explicit RulesetInfo(RulesetSource source) : source_(std::move(source)) {} + ~RulesetInfo() = default; + RulesetInfo(RulesetInfo&&) = default; + RulesetInfo& operator=(RulesetInfo&&) = default; + + const RulesetSource& source() const { return source_; } + + // Returns the ownership of the ruleset matcher to the caller. Must only be + // called for a successful load. + std::unique_ptr<RulesetMatcher> TakeMatcher() { + DCHECK(did_load_successfully()); + return std::move(matcher_); + } + + // Clients should set a new checksum if the checksum stored in prefs should + // be updated. + void set_new_checksum(int new_checksum) { new_checksum_ = new_checksum; } + base::Optional<int> new_checksum() const { return new_checksum_; } + + // The expected checksum for the indexed ruleset. + void set_expected_checksum(int checksum) { expected_checksum_ = checksum; } + int expected_checksum() const { + DCHECK(expected_checksum_); + return *expected_checksum_; + } + + // Must be called after CreateVerifiedMatcher. + RulesetMatcher::LoadRulesetResult load_ruleset_result() const { + DCHECK(load_ruleset_result_); + // |matcher_| is valid only on success. + DCHECK_EQ(load_ruleset_result_ == RulesetMatcher::kLoadSuccess, !!matcher_); + return *load_ruleset_result_; + } + + // Must be called after CreateVerifiedMatcher. + bool did_load_successfully() const { + return load_ruleset_result() == RulesetMatcher::kLoadSuccess; + } + + // Must be invoked on the file sequence. Must only be called after the + // expected checksum is set. + void CreateVerifiedMatcher() { + DCHECK(expected_checksum_); + DCHECK(GetExtensionFileTaskRunner()->RunsTasksInCurrentSequence()); + + load_ruleset_result_ = RulesetMatcher::CreateVerifiedMatcher( + source_.indexed_path, *expected_checksum_, &matcher_); + + UMA_HISTOGRAM_ENUMERATION( + "Extensions.DeclarativeNetRequest.LoadRulesetResult", + load_ruleset_result(), RulesetMatcher::kLoadResultMax); + } + + private: + RulesetSource source_; + + // The expected checksum of the indexed ruleset. + base::Optional<int> expected_checksum_; + + // Stores the result of creating a verified matcher from the |source_|. + std::unique_ptr<RulesetMatcher> matcher_; + base::Optional<RulesetMatcher::LoadRulesetResult> load_ruleset_result_; + + // The new checksum to be persisted to prefs. A new checksum should only be + // set in case of flatbuffer version mismatch. + base::Optional<int> new_checksum_; + + DISALLOW_COPY_AND_ASSIGN(RulesetInfo); +}; + } // namespace // static @@ -91,28 +164,19 @@ } // Helper to pass information related to the ruleset being loaded. -struct RulesMonitorService::LoadRulesetInfo { - LoadRulesetInfo(ExtensionId extension_id, - int expected_ruleset_checksum, - RulesetSource source) - : extension_id(std::move(extension_id)), - expected_ruleset_checksum(expected_ruleset_checksum), - source(std::move(source)) {} +struct RulesMonitorService::LoadRequestData { + LoadRequestData(ExtensionId extension_id, RulesetInfo ruleset) + : extension_id(std::move(extension_id)), ruleset(std::move(ruleset)) {} - ~LoadRulesetInfo() = default; - LoadRulesetInfo(LoadRulesetInfo&&) = default; - LoadRulesetInfo& operator=(LoadRulesetInfo&&) = default; + ~LoadRequestData() = default; + LoadRequestData(LoadRequestData&&) = default; + LoadRequestData& operator=(LoadRequestData&&) = default; ExtensionId extension_id; - int expected_ruleset_checksum; - RulesetSource source; + RulesetInfo ruleset; - // True in case the checksum of the indexed ruleset changed. If true, - // |expected_ruleset_checksum| contains the updated checksum. This can only - // happen in case of an incorrect indexed ruleset format version. - bool checksum_updated_due_to_version_mismatch = false; - - DISALLOW_COPY_AND_ASSIGN(LoadRulesetInfo); + private: + DISALLOW_COPY_AND_ASSIGN(LoadRequestData); }; // Maintains state needed on |file_task_runner_|. Created on the UI thread, but @@ -131,82 +195,45 @@ DCHECK(GetExtensionFileTaskRunner()->RunsTasksInCurrentSequence()); } - using LoadRulesetUICallback = - base::OnceCallback<void(LoadRulesetInfo, - std::unique_ptr<RulesetMatcher>)>; - // Loads ruleset for |info|. Invokes |ui_callback| with the RulesetMatcher - // instance created, passing null on failure. - void LoadRuleset(LoadRulesetInfo info, + using LoadRulesetUICallback = base::OnceCallback<void(LoadRequestData)>; + // Loads ruleset for |load_data|. Invokes |ui_callback| with the + // RulesetMatcher instance created, passing null on failure. + void LoadRuleset(LoadRequestData load_data, LoadRulesetUICallback ui_callback) const { - LoadRulesetInternal(std::move(info), std::move(ui_callback), - LoadFailedAction::kReindex); - } - - private: - // Describes the action to take if ruleset loading fails. - enum class LoadFailedAction { - kReindex, // Reindexes the JSON ruleset. - kSignalFailure, // Signals failure on the UI thread. - }; - - // Internal helper to load the ruleset for |info|. - void LoadRulesetInternal(LoadRulesetInfo info, - LoadRulesetUICallback ui_callback, - LoadFailedAction failed_action) const { DCHECK(GetExtensionFileTaskRunner()->RunsTasksInCurrentSequence()); - std::unique_ptr<RulesetMatcher> matcher; - RulesetMatcher::LoadRulesetResult result = - RulesetMatcher::CreateVerifiedMatcher( - info.source.indexed_path, info.expected_ruleset_checksum, &matcher); - UMA_HISTOGRAM_ENUMERATION( - "Extensions.DeclarativeNetRequest.LoadRulesetResult", result, - RulesetMatcher::kLoadResultMax); + load_data.ruleset.CreateVerifiedMatcher(); - // |matcher| is valid only on success. - DCHECK_EQ(result == RulesetMatcher::kLoadSuccess, !!matcher); - - const bool reindex_ruleset = result != RulesetMatcher::kLoadSuccess && - failed_action == LoadFailedAction::kReindex; - - if (!reindex_ruleset) { + if (load_data.ruleset.did_load_successfully()) { base::PostTaskWithTraits( FROM_HERE, {content::BrowserThread::UI}, - base::BindOnce(std::move(ui_callback), std::move(info), - std::move(matcher))); + base::BindOnce(std::move(ui_callback), std::move(load_data))); return; } - // Clone the RulesetSource before moving |info|. - RulesetSource source_copy = info.source.Clone(); + // Clone the RulesetSource before moving |load_data|. + RulesetSource source_copy = load_data.ruleset.source().Clone(); // Attempt to reindex the extension ruleset. // Using a weak pointer here is safe since |ruleset_reindexed_callback| will // be called on this sequence itself. IndexAndPersistRulesCallback ruleset_reindexed_callback = base::BindOnce( &FileSequenceState::OnRulesetReindexed, weak_factory_.GetWeakPtr(), - std::move(info), result, std::move(ui_callback)); + std::move(load_data), std::move(ui_callback)); IndexAndPersistRules(connector_.get(), base::nullopt /* decoder_batch_id */, std::move(source_copy), std::move(ruleset_reindexed_callback)); } + private: // Callback invoked when the JSON ruleset is reindexed. - void OnRulesetReindexed( - LoadRulesetInfo info, - RulesetMatcher::LoadRulesetResult initial_failure_reason, - LoadRulesetUICallback ui_callback, - IndexAndPersistRulesResult result) const { + void OnRulesetReindexed(LoadRequestData load_data, + LoadRulesetUICallback ui_callback, + IndexAndPersistRulesResult result) const { DCHECK(GetExtensionFileTaskRunner()->RunsTasksInCurrentSequence()); - // In case of updates to the ruleset version, the ruleset checksum can - // change. - if (result.success && - initial_failure_reason == - RulesetMatcher::LoadRulesetResult::kLoadErrorVersionMismatch) { - info.expected_ruleset_checksum = result.ruleset_checksum; - info.checksum_updated_due_to_version_mismatch = true; - } + // Only ruleset which can't be loaded are reindexed. + DCHECK(!load_data.ruleset.did_load_successfully()); // The checksum of the reindexed ruleset should have been the same as the // expected checksum obtained from prefs, in all cases except when the @@ -216,23 +243,32 @@ // these is beyond our scope here, so simply signal a failure. bool reindexing_success = result.success && - info.expected_ruleset_checksum == result.ruleset_checksum; + load_data.ruleset.expected_checksum() == result.ruleset_checksum; + + // In case of updates to the ruleset version, the change of ruleset checksum + // is expected. + if (result.success && + load_data.ruleset.load_ruleset_result() == + RulesetMatcher::LoadRulesetResult::kLoadErrorVersionMismatch) { + load_data.ruleset.set_new_checksum(result.ruleset_checksum); + // Also change the |expected_checksum| so that the subsequent load + // succeeds. + load_data.ruleset.set_expected_checksum(result.ruleset_checksum); + reindexing_success = true; + } + UMA_HISTOGRAM_BOOLEAN( "Extensions.DeclarativeNetRequest.RulesetReindexSuccessful", reindexing_success); - if (!reindexing_success) { - base::PostTaskWithTraits( - FROM_HERE, {content::BrowserThread::UI}, - base::BindOnce(std::move(ui_callback), std::move(info), - nullptr /* matcher */)); - return; - } - // We already reindexed the extension ruleset once and it succeeded. If the - // ruleset load fails again, there is some other issue. To prevent a cycle, - // don't reindex on failure again. - LoadRulesetInternal(std::move(info), std::move(ui_callback), - LoadFailedAction::kSignalFailure); + // If the reindexing was successful, try to load the ruleset again. + if (reindexing_success) + load_data.ruleset.CreateVerifiedMatcher(); + + // The UI thread will handle success or failure. + base::PostTaskWithTraits( + FROM_HERE, {content::BrowserThread::UI}, + base::BindOnce(std::move(ui_callback), std::move(load_data))); } const std::unique_ptr<service_manager::Connector> connector_; @@ -256,7 +292,7 @@ } void LoadRuleset( - LoadRulesetInfo info, + LoadRequestData load_data, FileSequenceState::LoadRulesetUICallback load_ruleset_callback) const { // base::Unretained is safe here because we trigger the destruction of // |file_sequence_state_| on |file_task_runner_| from our destructor. Hence @@ -264,7 +300,7 @@ base::OnceClosure load_ruleset_task = base::BindOnce(&FileSequenceState::LoadRuleset, base::Unretained(file_sequence_state_.get()), - std::move(info), std::move(load_ruleset_callback)); + std::move(load_data), std::move(load_ruleset_callback)); file_task_runner_->PostTask(FROM_HERE, std::move(load_ruleset_task)); } @@ -314,14 +350,16 @@ &expected_ruleset_checksum); DCHECK(has_checksum); - LoadRulesetInfo info(extension->id(), expected_ruleset_checksum, - RulesetSource::Create(*extension)); + RulesetInfo ruleset(RulesetSource::Create(*extension)); + ruleset.set_expected_checksum(expected_ruleset_checksum); + + LoadRequestData load_data(extension->id(), std::move(ruleset)); FileSequenceState::LoadRulesetUICallback load_ruleset_callback = base::BindOnce(&RulesMonitorService::OnRulesetLoaded, weak_factory_.GetWeakPtr()); - file_sequence_bridge_->LoadRuleset(std::move(info), + file_sequence_bridge_->LoadRuleset(std::move(load_data), std::move(load_ruleset_callback)); } @@ -341,35 +379,35 @@ std::move(unload_ruleset_on_io_task)); } -void RulesMonitorService::OnRulesetLoaded( - LoadRulesetInfo info, - std::unique_ptr<RulesetMatcher> matcher) { +void RulesMonitorService::OnRulesetLoaded(LoadRequestData load_data) { // Update the ruleset checksum if needed. - if (info.checksum_updated_due_to_version_mismatch) { - prefs_->SetDNRRulesetChecksum(info.extension_id, - info.expected_ruleset_checksum); - } - - if (!matcher) { - // The ruleset failed to load. Notify the user. - warning_service_->AddWarnings( - {Warning::CreateRulesetFailedToLoadWarning(info.extension_id)}); - return; + if (load_data.ruleset.new_checksum()) { + prefs_->SetDNRRulesetChecksum(load_data.extension_id, + *load_data.ruleset.new_checksum()); } // It's possible that the extension has been disabled since the initial load // ruleset request. If it's disabled, do nothing. - if (!extension_registry_->enabled_extensions().Contains(info.extension_id)) + if (!extension_registry_->enabled_extensions().Contains( + load_data.extension_id)) return; - extensions_with_rulesets_.insert(info.extension_id); + if (!load_data.ruleset.did_load_successfully()) { + // The ruleset failed to load. Notify the user. + warning_service_->AddWarnings( + {Warning::CreateRulesetFailedToLoadWarning(load_data.extension_id)}); + return; + } + + extensions_with_rulesets_.insert(load_data.extension_id); for (auto& observer : observers_) observer.OnRulesetLoaded(); - base::OnceClosure load_ruleset_on_io = base::BindOnce( - &LoadRulesetOnIOThread, info.extension_id, std::move(matcher), - prefs_->GetDNRAllowedPages(info.extension_id), - base::RetainedRef(info_map_)); + base::OnceClosure load_ruleset_on_io = + base::BindOnce(&LoadRulesetOnIOThread, load_data.extension_id, + load_data.ruleset.TakeMatcher(), + prefs_->GetDNRAllowedPages(load_data.extension_id), + base::RetainedRef(info_map_)); base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::IO}, std::move(load_ruleset_on_io)); }
diff --git a/extensions/browser/api/declarative_net_request/rules_monitor_service.h b/extensions/browser/api/declarative_net_request/rules_monitor_service.h index 76196378..3e2437cf 100644 --- a/extensions/browser/api/declarative_net_request/rules_monitor_service.h +++ b/extensions/browser/api/declarative_net_request/rules_monitor_service.h
@@ -27,7 +27,6 @@ class WarningService; namespace declarative_net_request { -class RulesetMatcher; // Observes loading and unloading of extensions to load and unload their // rulesets for the Declarative Net Request API. Lives on the UI thread. Note: A @@ -60,7 +59,7 @@ void RemoveObserver(Observer* observer); private: - struct LoadRulesetInfo; + struct LoadRequestData; class FileSequenceState; class FileSequenceBridge; @@ -83,10 +82,8 @@ const Extension* extension, UnloadedExtensionReason reason) override; - // Callback invoked when we have loaded the ruleset for |info| on - // |file_task_runner_|. |matcher| is null iff the ruleset loading failed. - void OnRulesetLoaded(LoadRulesetInfo info, - std::unique_ptr<RulesetMatcher> matcher); + // Invoked when we have loaded the ruleset on |file_task_runner_|. + void OnRulesetLoaded(LoadRequestData load_data); ScopedObserver<ExtensionRegistry, ExtensionRegistryObserver> registry_observer_;
diff --git a/extensions/browser/api/lock_screen_data/lock_screen_item_storage_unittest.cc b/extensions/browser/api/lock_screen_data/lock_screen_item_storage_unittest.cc index 0c8d3f97..f36bdce8 100644 --- a/extensions/browser/api/lock_screen_data/lock_screen_item_storage_unittest.cc +++ b/extensions/browser/api/lock_screen_data/lock_screen_item_storage_unittest.cc
@@ -1524,7 +1524,7 @@ // Update the local state so it seems that lock screen notes have previously // been used by the extension, but currently, no items are recorded to exist - // for the extnesion. + // for the extension. InitExtensionLocalState( {{extension()->id(), 1 /*storage_version*/, 0 /*item_count*/}});
diff --git a/extensions/browser/updater/OWNERS b/extensions/browser/updater/OWNERS index f9d52138..7421bdb 100644 --- a/extensions/browser/updater/OWNERS +++ b/extensions/browser/updater/OWNERS
@@ -1,4 +1,5 @@ -mxnguyen@chromium.org +sorin@chromium.org +waffles@chromium.org # TEAM: extensions-dev@chromium.org # COMPONENT: Platform>Extensions
diff --git a/extensions/common/extension_set.h b/extensions/common/extension_set.h index 54405ea7..8f3111d 100644 --- a/extensions/common/extension_set.h +++ b/extensions/common/extension_set.h
@@ -85,7 +85,7 @@ bool InsertAll(const ExtensionSet& extensions); // Removes the specified extension. - // Returns true if the set contained the specified extnesion. + // Returns true if the set contained the specified extension. bool Remove(const std::string& id); // Removes all extensions.
diff --git a/gpu/command_buffer/service/buffer_manager.h b/gpu/command_buffer/service/buffer_manager.h index 7f1f3af..86c35611 100644 --- a/gpu/command_buffer/service/buffer_manager.h +++ b/gpu/command_buffer/service/buffer_manager.h
@@ -14,7 +14,6 @@ #include <unordered_map> #include <vector> -#include "base/debug/stack_trace.h" #include "base/logging.h" #include "base/macros.h" #include "base/memory/ref_counted.h"
diff --git a/gpu/command_buffer/tests/fuzzer_main.cc b/gpu/command_buffer/tests/fuzzer_main.cc index 2ea310f..fe4bff0 100644 --- a/gpu/command_buffer/tests/fuzzer_main.cc +++ b/gpu/command_buffer/tests/fuzzer_main.cc
@@ -21,6 +21,7 @@ #include "build/build_config.h" #include "gpu/command_buffer/common/constants.h" #include "gpu/command_buffer/common/context_creation_attribs.h" +#include "gpu/command_buffer/common/shared_image_usage.h" #include "gpu/command_buffer/service/buffer_manager.h" #include "gpu/command_buffer/service/command_buffer_direct.h" #include "gpu/command_buffer/service/context_group.h" @@ -34,6 +35,7 @@ #include "gpu/command_buffer/service/raster_decoder.h" #include "gpu/command_buffer/service/service_discardable_manager.h" #include "gpu/command_buffer/service/shared_context_state.h" +#include "gpu/command_buffer/service/shared_image_factory.h" #include "gpu/command_buffer/service/shared_image_manager.h" #include "gpu/command_buffer/service/transfer_buffer_manager.h" #include "ui/gfx/geometry/size.h" @@ -359,19 +361,37 @@ new gles2::FeatureInfo(config_.workarounds, gpu_feature_info); command_buffer_.reset(new CommandBufferDirect()); -#if defined(GPU_FUZZER_USE_RASTER_DECODER) - CHECK(feature_info->feature_flags().chromium_raster_transport); scoped_refptr<SharedContextState> context_state = base::MakeRefCounted<SharedContextState>( share_group_, surface_, context_, config_.workarounds.use_virtualized_gl_contexts, base::DoNothing()); context_state->InitializeGrContext(config_.workarounds, nullptr); context_state->InitializeGL(gpu_preferences_, feature_info); + + shared_image_manager_ = std::make_unique<SharedImageManager>(); + shared_image_factory_ = std::make_unique<SharedImageFactory>( + gpu_preferences_, config_.workarounds, gpu_feature_info, + context_state.get(), &mailbox_manager_, shared_image_manager_.get(), + nullptr /* image_factory */, nullptr /* memory_tracker */); + for (uint32_t usage = SHARED_IMAGE_USAGE_GLES2; + usage <= SHARED_IMAGE_USAGE_RGB_EMULATION; usage <<= 1) { + Mailbox::Name name; + memset(name, 0, sizeof(name)); + name[base::size(name) - 1] = usage; + Mailbox mailbox; + mailbox.SetName(name); + shared_image_factory_->CreateSharedImage( + mailbox, viz::RGBA_8888, gfx::Size(256, 256), + gfx::ColorSpace::CreateSRGB(), usage); + } + +#if defined(GPU_FUZZER_USE_RASTER_DECODER) + CHECK(feature_info->feature_flags().chromium_raster_transport); auto* context = context_state->context(); decoder_.reset(raster::RasterDecoder::Create( command_buffer_.get(), command_buffer_->service(), &outputter_, gpu_feature_info, gpu_preferences_, nullptr /* memory_tracker */, - &shared_image_manager_, std::move(context_state))); + shared_image_manager_.get(), std::move(context_state))); #else scoped_refptr<gles2::ContextGroup> context_group = new gles2::ContextGroup( gpu_preferences_, true, &mailbox_manager_, nullptr /* memory_tracker */, @@ -379,7 +399,7 @@ config_.attrib_helper.bind_generates_resource, &image_manager_, nullptr /* image_factory */, nullptr /* progress_reporter */, gpu_feature_info, discardable_manager_.get(), - passthrough_discardable_manager_.get(), &shared_image_manager_); + passthrough_discardable_manager_.get(), shared_image_manager_.get()); auto* context = context_.get(); decoder_.reset(gles2::GLES2Decoder::Create( command_buffer_.get(), command_buffer_->service(), &outputter_, @@ -423,6 +443,9 @@ decoder_->WasContextLost() || !decoder_->CheckResetStatus(); decoder_->Destroy(!context_lost); decoder_.reset(); + + shared_image_factory_.reset(); + shared_image_manager_.reset(); } if (context_) { @@ -541,7 +564,8 @@ std::unique_ptr<ServiceDiscardableManager> discardable_manager_; std::unique_ptr<PassthroughDiscardableManager> passthrough_discardable_manager_; - SharedImageManager shared_image_manager_; + std::unique_ptr<SharedImageManager> shared_image_manager_; + std::unique_ptr<SharedImageFactory> shared_image_factory_; bool recreate_context_ = false; scoped_refptr<gl::GLSurface> surface_;
diff --git a/infra/config/commit-queue.cfg b/infra/config/commit-queue.cfg index 5ea580a..e17e658b 100644 --- a/infra/config/commit-queue.cfg +++ b/infra/config/commit-queue.cfg
@@ -152,6 +152,20 @@ ###################### builders { + name: "chromium/try/android_compile_x64_dbg" + location_regexp: ".+/[+]/sandbox/linux/seccomp-bpf/.+" + location_regexp: ".+/[+]/sandbox/linux/seccomp-bpf-helpers/.+" + location_regexp: ".+/[+]/sandbox/linux/system_headers/.+" + location_regexp: ".+/[+]/sandbox/linux/tests/.+" + } + builders { + name: "chromium/try/android_compile_x86_dbg" + location_regexp: ".+/[+]/sandbox/linux/seccomp-bpf/.+" + location_regexp: ".+/[+]/sandbox/linux/seccomp-bpf-helpers/.+" + location_regexp: ".+/[+]/sandbox/linux/system_headers/.+" + location_regexp: ".+/[+]/sandbox/linux/tests/.+" + } + builders { name: "chromium/try/android_optional_gpu_tests_rel" location_regexp: ".+/[+]/cc/.+" location_regexp: ".+/[+]/chrome/browser/vr/.+" @@ -309,20 +323,6 @@ } builders { - name: "*/master.tryserver.chromium.android/android_compile_x64_dbg" - location_regexp: ".+/[+]/sandbox/linux/seccomp-bpf/.+" - location_regexp: ".+/[+]/sandbox/linux/seccomp-bpf-helpers/.+" - location_regexp: ".+/[+]/sandbox/linux/system_headers/.+" - location_regexp: ".+/[+]/sandbox/linux/tests/.+" - } - builders { - name: "*/master.tryserver.chromium.android/android_compile_x86_dbg" - location_regexp: ".+/[+]/sandbox/linux/seccomp-bpf/.+" - location_regexp: ".+/[+]/sandbox/linux/seccomp-bpf-helpers/.+" - location_regexp: ".+/[+]/sandbox/linux/system_headers/.+" - location_regexp: ".+/[+]/sandbox/linux/tests/.+" - } - builders { name: "*/master.tryserver.chromium.android/android_cronet_tester" location_regexp: ".+/[+]/components/cronet/.+" location_regexp: ".+/[+]/components/grpc_support/.+"
diff --git a/ios/chrome/app/application_delegate/app_state_unittest.mm b/ios/chrome/app/application_delegate/app_state_unittest.mm index e074f46..61fd49d 100644 --- a/ios/chrome/app/application_delegate/app_state_unittest.mm +++ b/ios/chrome/app/application_delegate/app_state_unittest.mm
@@ -375,7 +375,7 @@ base::Lock* lock = new base::Lock; base::PostTaskWithTraits(FROM_HERE, {web::WebThread::IO}, - base::Bind(&createTracker, &created, lock)); + base::BindOnce(&createTracker, &created, lock)); CFTimeInterval start = CACurrentMediaTime();
diff --git a/ios/chrome/app/application_delegate/metrics_mediator.mm b/ios/chrome/app/application_delegate/metrics_mediator.mm index 668247c..339e02b 100644 --- a/ios/chrome/app/application_delegate/metrics_mediator.mm +++ b/ios/chrome/app/application_delegate/metrics_mediator.mm
@@ -250,7 +250,7 @@ app_group::main_app::RecordWidgetUsage(); base::PostTaskWithTraits( FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT}, - base::Bind(&app_group::main_app::ProcessPendingLogs, callback)); + base::BindOnce(&app_group::main_app::ProcessPendingLogs, callback)); } - (void)processCrashReportsPresentAtStartup {
diff --git a/ios/chrome/browser/browser_state/chrome_browser_state_impl_io_data.mm b/ios/chrome/browser/browser_state/chrome_browser_state_impl_io_data.mm index 511c50d..a6744ce1 100644 --- a/ios/chrome/browser/browser_state/chrome_browser_state_impl_io_data.mm +++ b/ios/chrome/browser/browser_state/chrome_browser_state_impl_io_data.mm
@@ -133,7 +133,7 @@ base::PostTaskWithTraits( FROM_HERE, {web::WebThread::IO}, - base::Bind( + base::BindOnce( &ChromeBrowserStateImplIOData::ClearNetworkingHistorySinceOnIOThread, base::Unretained(io_data_), time, completion)); }
diff --git a/ios/chrome/browser/browser_state/chrome_browser_state_io_data.mm b/ios/chrome/browser/browser_state/chrome_browser_state_io_data.mm index d1e33329..d2228f2 100644 --- a/ios/chrome/browser/browser_state/chrome_browser_state_io_data.mm +++ b/ios/chrome/browser/browser_state/chrome_browser_state_io_data.mm
@@ -456,9 +456,10 @@ if (!context_getters->empty()) { if (web::WebThread::IsThreadInitialized(web::WebThread::IO)) { - base::PostTaskWithTraits(FROM_HERE, {web::WebThread::IO}, - base::Bind(&NotifyContextGettersOfShutdownOnIO, - base::Passed(&context_getters))); + base::PostTaskWithTraits( + FROM_HERE, {web::WebThread::IO}, + base::BindOnce(&NotifyContextGettersOfShutdownOnIO, + std::move(context_getters))); } }
diff --git a/ios/chrome/browser/browser_state/chrome_browser_state_manager_impl.cc b/ios/chrome/browser/browser_state/chrome_browser_state_manager_impl.cc index ec084619..915a6f1 100644 --- a/ios/chrome/browser/browser_state/chrome_browser_state_manager_impl.cc +++ b/ios/chrome/browser/browser_state/chrome_browser_state_manager_impl.cc
@@ -196,7 +196,7 @@ FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT, base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN}, - base::Bind(&BrowserStateSizeTask, path), + base::BindOnce(&BrowserStateSizeTask, path), base::TimeDelta::FromSeconds(112)); LogNumberOfBrowserStates(
diff --git a/ios/chrome/browser/infobars/infobar_badge_tab_helper.h b/ios/chrome/browser/infobars/infobar_badge_tab_helper.h index d0715b7..d29cf1e0 100644 --- a/ios/chrome/browser/infobars/infobar_badge_tab_helper.h +++ b/ios/chrome/browser/infobars/infobar_badge_tab_helper.h
@@ -26,6 +26,9 @@ static void CreateForWebState(web::WebState* web_state); // Sets the InfobarBadgeTabHelperDelegate to |delegate|. void SetDelegate(id<InfobarBadgeTabHelperDelegate> delegate); + // Returns wheter an Infobar badge is being displayed for the TabHelper + // Webstate. + bool IsInfobarBadgeDisplaying(); ~InfobarBadgeTabHelper() override; private: @@ -35,8 +38,6 @@ // InfoBarManagerObserver implementation. void OnInfoBarAdded(infobars::InfoBar* infobar) override; void OnInfoBarRemoved(infobars::InfoBar* infobar, bool animate) override; - void OnInfoBarReplaced(infobars::InfoBar* old_infobar, - infobars::InfoBar* new_infobar) override; void OnManagerShuttingDown(infobars::InfoBarManager* manager) override; // Updates the badge delegate for |infobar|. void UpdateBadgeForInfobar(infobars::InfoBar* infobar, bool display); @@ -46,6 +47,8 @@ infobar_observer_; // Delegate which displays the Infobar badge. __weak id<InfobarBadgeTabHelperDelegate> delegate_ = nil; + // Returns wheter an Infobar is being displayed. + bool is_infobar_displaying_; WEB_STATE_USER_DATA_KEY_DECL(); DISALLOW_COPY_AND_ASSIGN(InfobarBadgeTabHelper);
diff --git a/ios/chrome/browser/infobars/infobar_badge_tab_helper.mm b/ios/chrome/browser/infobars/infobar_badge_tab_helper.mm index 813643b..2053764 100644 --- a/ios/chrome/browser/infobars/infobar_badge_tab_helper.mm +++ b/ios/chrome/browser/infobars/infobar_badge_tab_helper.mm
@@ -31,12 +31,16 @@ delegate_ = delegate; } +bool InfobarBadgeTabHelper::IsInfobarBadgeDisplaying() { + return is_infobar_displaying_; +} + InfobarBadgeTabHelper::~InfobarBadgeTabHelper() = default; #pragma mark - Private InfobarBadgeTabHelper::InfobarBadgeTabHelper(web::WebState* web_state) - : infobar_observer_(this) { + : infobar_observer_(this), is_infobar_displaying_(false) { infobars::InfoBarManager* infoBarManager = InfoBarManagerImpl::FromWebState(web_state); if (infoBarManager) { @@ -55,9 +59,6 @@ this->UpdateBadgeForInfobar(infobar, false); } -void InfobarBadgeTabHelper::OnInfoBarReplaced(infobars::InfoBar* old_infobar, - infobars::InfoBar* new_infobar) {} - void InfobarBadgeTabHelper::OnManagerShuttingDown( infobars::InfoBarManager* manager) { infobar_observer_.Remove(manager); @@ -67,6 +68,7 @@ void InfobarBadgeTabHelper::UpdateBadgeForInfobar(infobars::InfoBar* infobar, bool display) { + is_infobar_displaying_ = display; InfoBarIOS* infobar_ios = static_cast<InfoBarIOS*>(infobar); id<InfobarUIDelegate> controller_ = infobar_ios->InfobarUIDelegate(); if (IsInfobarUIRebootEnabled() && [controller_ isPresented]) {
diff --git a/ios/chrome/browser/omaha/omaha_service.mm b/ios/chrome/browser/omaha/omaha_service.mm index 3d94c71b..a8b2463 100644 --- a/ios/chrome/browser/omaha/omaha_service.mm +++ b/ios/chrome/browser/omaha/omaha_service.mm
@@ -309,8 +309,8 @@ result->url_loader_factory_info_ = std::move(url_loader_factory_info); result->locale_lang_ = GetApplicationContext()->GetApplicationLocale(); base::PostTaskWithTraits(FROM_HERE, {web::WebThread::IO}, - base::Bind(&OmahaService::SendOrScheduleNextPing, - base::Unretained(result))); + base::BindOnce(&OmahaService::SendOrScheduleNextPing, + base::Unretained(result))); } OmahaService::OmahaService() @@ -392,8 +392,8 @@ const base::Callback<void(base::DictionaryValue*)> callback) { base::PostTaskWithTraits( FROM_HERE, {web::WebThread::IO}, - base::Bind(&OmahaService::GetDebugInformationOnIOThread, - base::Unretained(GetInstance()), callback)); + base::BindOnce(&OmahaService::GetDebugInformationOnIOThread, + base::Unretained(GetInstance()), callback)); } // static @@ -653,7 +653,7 @@ if (details) { base::PostTaskWithTraits( FROM_HERE, {web::WebThread::UI}, - base::Bind(upgrade_recommended_callback_, *details)); + base::BindOnce(upgrade_recommended_callback_, *details)); } } @@ -682,8 +682,9 @@ (timer_.desired_run_time() - base::TimeTicks::Now()))); // Sending the value to the callback. - base::PostTaskWithTraits(FROM_HERE, {web::WebThread::UI}, - base::Bind(callback, base::Owned(result.release()))); + base::PostTaskWithTraits( + FROM_HERE, {web::WebThread::UI}, + base::BindOnce(callback, base::Owned(result.release()))); } bool OmahaService::IsNextPingInstallRetry() {
diff --git a/ios/chrome/browser/reading_list/offline_page_tab_helper.mm b/ios/chrome/browser/reading_list/offline_page_tab_helper.mm index d5f4f8ad..4a511b2 100644 --- a/ios/chrome/browser/reading_list/offline_page_tab_helper.mm +++ b/ios/chrome/browser/reading_list/offline_page_tab_helper.mm
@@ -88,6 +88,7 @@ ReadingListModel* model) : web_state_(web_state), reading_list_model_(model) { web_state_->AddObserver(this); + reading_list_model_->AddObserver(this); } OfflinePageTabHelper::~OfflinePageTabHelper() {
diff --git a/ios/chrome/browser/sync/glue/sync_start_util.cc b/ios/chrome/browser/sync/glue/sync_start_util.cc index 4f211db..ee5393a 100644 --- a/ios/chrome/browser/sync/glue/sync_start_util.cc +++ b/ios/chrome/browser/sync/glue/sync_start_util.cc
@@ -49,7 +49,7 @@ syncer::ModelType type) { base::PostTaskWithTraits( FROM_HERE, {web::WebThread::UI}, - base::Bind(&StartSyncOnUIThread, browser_state_path, type)); + base::BindOnce(&StartSyncOnUIThread, browser_state_path, type)); } } // namespace
diff --git a/ios/chrome/browser/sync/profile_sync_service_factory.cc b/ios/chrome/browser/sync/profile_sync_service_factory.cc index 6e3c021..a83393b 100644 --- a/ios/chrome/browser/sync/profile_sync_service_factory.cc +++ b/ios/chrome/browser/sync/profile_sync_service_factory.cc
@@ -62,8 +62,8 @@ const base::TimeDelta& latency) { base::PostTaskWithTraits( FROM_HERE, {web::WebThread::UI}, - base::Bind(&UpdateNetworkTimeOnUIThread, network_time, resolution, - latency, base::TimeTicks::Now())); + base::BindOnce(&UpdateNetworkTimeOnUIThread, network_time, resolution, + latency, base::TimeTicks::Now())); } } // namespace
diff --git a/ios/chrome/browser/tabs/BUILD.gn b/ios/chrome/browser/tabs/BUILD.gn index 397b8cd7..957d779 100644 --- a/ios/chrome/browser/tabs/BUILD.gn +++ b/ios/chrome/browser/tabs/BUILD.gn
@@ -101,6 +101,7 @@ "//ios/chrome/browser/history", "//ios/chrome/browser/history:tab_helper", "//ios/chrome/browser/infobars", + "//ios/chrome/browser/infobars:badge", "//ios/chrome/browser/itunes_urls", "//ios/chrome/browser/language", "//ios/chrome/browser/metrics", @@ -124,6 +125,7 @@ "//ios/chrome/browser/ui:ui_internal", "//ios/chrome/browser/ui/alert_coordinator", "//ios/chrome/browser/ui/commands", + "//ios/chrome/browser/ui/infobars:feature_flags", "//ios/chrome/browser/ui/overscroll_actions", "//ios/chrome/browser/ui/util", "//ios/chrome/browser/voice",
diff --git a/ios/chrome/browser/tabs/tab_helper_util.mm b/ios/chrome/browser/tabs/tab_helper_util.mm index 91d62f0..97a2fc6 100644 --- a/ios/chrome/browser/tabs/tab_helper_util.mm +++ b/ios/chrome/browser/tabs/tab_helper_util.mm
@@ -24,6 +24,7 @@ #include "ios/chrome/browser/history/history_service_factory.h" #include "ios/chrome/browser/history/history_tab_helper.h" #include "ios/chrome/browser/history/top_sites_factory.h" +#include "ios/chrome/browser/infobars/infobar_badge_tab_helper.h" #import "ios/chrome/browser/infobars/infobar_manager_impl.h" #import "ios/chrome/browser/itunes_urls/itunes_urls_handler_tab_helper.h" #import "ios/chrome/browser/metrics/ukm_url_recorder.h" @@ -44,6 +45,7 @@ #import "ios/chrome/browser/tabs/legacy_tab_helper.h" #import "ios/chrome/browser/tabs/tab.h" #import "ios/chrome/browser/translate/chrome_ios_translate_client.h" +#import "ios/chrome/browser/ui/infobars/infobar_feature.h" #import "ios/chrome/browser/ui/ui_feature_flags.h" #import "ios/chrome/browser/voice/voice_search_navigations_tab_helper.h" #import "ios/chrome/browser/web/blocked_popup_tab_helper.h" @@ -149,6 +151,9 @@ SnapshotTabHelper::CreateForWebState(web_state, tab_id); PagePlaceholderTabHelper::CreateForWebState(web_state); PrintTabHelper::CreateForWebState(web_state); + if (IsInfobarUIRebootEnabled()) { + InfobarBadgeTabHelper::CreateForWebState(web_state); + } } // Allow the embedder to attach tab helpers.
diff --git a/ios/chrome/browser/ui/infobars/coordinators/infobar_confirm_coordinator.mm b/ios/chrome/browser/ui/infobars/coordinators/infobar_confirm_coordinator.mm index 35ba678..e2203ce 100644 --- a/ios/chrome/browser/ui/infobars/coordinators/infobar_confirm_coordinator.mm +++ b/ios/chrome/browser/ui/infobars/coordinators/infobar_confirm_coordinator.mm
@@ -66,9 +66,6 @@ [self.bannerViewController.presentingViewController dismissViewControllerAnimated:YES completion:nil]; - // RemoveInfoBar() will delete the InfobarIOS that owns this Coordinator - // from memory. - self.delegate->RemoveInfoBar(); } } @@ -80,6 +77,9 @@ - (void)detachView { [self stop]; + // RemoveInfoBar() will delete the InfobarIOS that owns this Coordinator + // from memory. + self.delegate->RemoveInfoBar(); } #pragma mark - InfobarBannerDelegate
diff --git a/ios/chrome/browser/ui/infobars/coordinators/infobar_password_coordinator.mm b/ios/chrome/browser/ui/infobars/coordinators/infobar_password_coordinator.mm index 9d58f51..92f15f0 100644 --- a/ios/chrome/browser/ui/infobars/coordinators/infobar_password_coordinator.mm +++ b/ios/chrome/browser/ui/infobars/coordinators/infobar_password_coordinator.mm
@@ -69,9 +69,6 @@ [self.bannerViewController.presentingViewController dismissViewControllerAnimated:YES completion:nil]; - // RemoveInfoBar() will delete the InfobarIOS that owns this Coordinator - // from memory. - self.delegate->RemoveInfoBar(); } } @@ -83,6 +80,9 @@ - (void)detachView { [self stop]; + // RemoveInfoBar() will delete the InfobarIOS that owns this Coordinator + // from memory. + self.delegate->RemoveInfoBar(); } #pragma mark - InfobarBannerDelegate
diff --git a/ios/chrome/browser/ui/infobars/infobar_ui_delegate.h b/ios/chrome/browser/ui/infobars/infobar_ui_delegate.h index dede13d..a7fda975 100644 --- a/ios/chrome/browser/ui/infobars/infobar_ui_delegate.h +++ b/ios/chrome/browser/ui/infobars/infobar_ui_delegate.h
@@ -15,10 +15,8 @@ // Removes the view from the View Hierarchy. - (void)removeView; -// Detaches view from its delegate. After this function is called, no user -// interaction can be handled. -// TODO(crbug.com/927064): Nils the View's delegate, once we -// start using ViewControllers it might not be needed. +// Removes the view from the View Hierarchy, and deletes the backing Infobar +// object. - (void)detachView; // The InfobarControllerDelegate.
diff --git a/ios/chrome/browser/ui/location_bar/BUILD.gn b/ios/chrome/browser/ui/location_bar/BUILD.gn index e8762d4..1a32fb7a 100644 --- a/ios/chrome/browser/ui/location_bar/BUILD.gn +++ b/ios/chrome/browser/ui/location_bar/BUILD.gn
@@ -40,6 +40,7 @@ "//ios/chrome/browser/autocomplete", "//ios/chrome/browser/browser_state:browser_state", "//ios/chrome/browser/geolocation:geolocation_internal", + "//ios/chrome/browser/infobars:badge", "//ios/chrome/browser/ntp", "//ios/chrome/browser/search_engines", "//ios/chrome/browser/ssl",
diff --git a/ios/chrome/browser/ui/location_bar/location_bar_consumer.h b/ios/chrome/browser/ui/location_bar/location_bar_consumer.h index 010afc3..47f89b4 100644 --- a/ios/chrome/browser/ui/location_bar/location_bar_consumer.h +++ b/ios/chrome/browser/ui/location_bar/location_bar_consumer.h
@@ -30,6 +30,11 @@ // changes. (This is usually when the default search engine changes). - (void)updateSearchByImageSupported:(BOOL)searchByImageSupported; +// Notifies the consumer to display or hide the Infobar badge. +// TODO(crbug.com/935804): This method is currently only being used in the +// Infobar redesign. +- (void)displayInfobarBadge:(BOOL)display; + @end #endif // IOS_CHROME_BROWSER_UI_LOCATION_BAR_LOCATION_BAR_CONSUMER_H_
diff --git a/ios/chrome/browser/ui/location_bar/location_bar_coordinator.mm b/ios/chrome/browser/ui/location_bar/location_bar_coordinator.mm index 8d91a9f..74d83953 100644 --- a/ios/chrome/browser/ui/location_bar/location_bar_coordinator.mm +++ b/ios/chrome/browser/ui/location_bar/location_bar_coordinator.mm
@@ -376,6 +376,10 @@ self.viewController.searchByImageEnabled = searchByImageSupported; } +- (void)displayInfobarBadge:(BOOL)display { + [self.viewController displayInfobarButton:display]; +} + #pragma mark - private // Returns a dictionary with variation headers for qualified URLs. Can be empty.
diff --git a/ios/chrome/browser/ui/location_bar/location_bar_mediator.mm b/ios/chrome/browser/ui/location_bar/location_bar_mediator.mm index 59e1171..b44e25bc 100644 --- a/ios/chrome/browser/ui/location_bar/location_bar_mediator.mm +++ b/ios/chrome/browser/ui/location_bar/location_bar_mediator.mm
@@ -8,9 +8,12 @@ #include "base/strings/sys_string_conversions.h" #include "components/omnibox/browser/location_bar_model.h" #include "ios/chrome/browser/chrome_url_constants.h" +#include "ios/chrome/browser/infobars/infobar_badge_tab_helper.h" +#include "ios/chrome/browser/infobars/infobar_badge_tab_helper_delegate.h" #import "ios/chrome/browser/search_engines/search_engine_observer_bridge.h" #import "ios/chrome/browser/search_engines/search_engines_util.h" #include "ios/chrome/browser/ssl/ios_security_state_tab_helper.h" +#import "ios/chrome/browser/ui/infobars/infobar_feature.h" #import "ios/chrome/browser/ui/location_bar/location_bar_consumer.h" #import "ios/chrome/browser/ui/ntp/ntp_util.h" #import "ios/chrome/browser/ui/omnibox/omnibox_util.h" @@ -31,8 +34,10 @@ #endif @interface LocationBarMediator () <CRWWebStateObserver, - WebStateListObserving, - SearchEngineObserving> + InfobarBadgeTabHelperDelegate, + SearchEngineObserving, + WebStateListObserving> + // The current web state associated with the toolbar. @property(nonatomic, assign) web::WebState* webState; @@ -153,6 +158,13 @@ search_engines::SupportsSearchByImage(self.templateURLService); } +#pragma mark - InfobarBadgeTabHelper + +- (void)displayBadge:(BOOL)display { + DCHECK(IsInfobarUIRebootEnabled()); + [self.consumer displayInfobarBadge:display]; +} + #pragma mark - Setters - (void)setWebState:(web::WebState*)webState { @@ -165,6 +177,19 @@ if (_webState) { _webState->AddObserver(_webStateObserver.get()); + if (IsInfobarUIRebootEnabled()) { + InfobarBadgeTabHelper* infobarBadgeTabHelper = + InfobarBadgeTabHelper::FromWebState(_webState); + DCHECK(infobarBadgeTabHelper); + infobarBadgeTabHelper->SetDelegate(self); + if (self.consumer) { + // Whenever the WebState changes ask the corresponding + // InfobarBadgeTabHelper if a badge should be displayed. + [self.consumer displayInfobarBadge:infobarBadgeTabHelper + ->IsInfobarBadgeDisplaying()]; + } + } + if (self.consumer) { [self notifyConsumerOfChangedLocation]; [self notifyConsumerOfChangedSecurityIcon];
diff --git a/ios/chrome/browser/ui/location_bar/location_bar_view_controller.h b/ios/chrome/browser/ui/location_bar/location_bar_view_controller.h index 469c422..76436f9 100644 --- a/ios/chrome/browser/ui/location_bar/location_bar_view_controller.h +++ b/ios/chrome/browser/ui/location_bar/location_bar_view_controller.h
@@ -71,6 +71,10 @@ - (void)updateForNTP:(BOOL)isNTP; // Sets |enabled| of the share button. - (void)setShareButtonEnabled:(BOOL)enabled; +// Displays or hides the InfobarButton. +// TODO(crbug.com/935804): This method is currently only being used in the +// Infobar redesign. +- (void)displayInfobarButton:(BOOL)display; // Displays the voice search button instead of the share button in steady state, // and adds the voice search button to the empty textfield.
diff --git a/ios/chrome/browser/ui/location_bar/location_bar_view_controller.mm b/ios/chrome/browser/ui/location_bar/location_bar_view_controller.mm index 5b60e4ae..7aaf050 100644 --- a/ios/chrome/browser/ui/location_bar/location_bar_view_controller.mm +++ b/ios/chrome/browser/ui/location_bar/location_bar_view_controller.mm
@@ -243,6 +243,10 @@ } } +- (void)displayInfobarButton:(BOOL)display { + self.locationBarSteadyView.leadingButton.hidden = !display; +} + #pragma mark - LocationBarAnimatee - (void)offsetEditViewToMatchSteadyView { @@ -434,6 +438,8 @@ imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] forState:UIControlStateNormal]; self.locationBarSteadyView.leadingButton.tintColor = [UIColor lightGrayColor]; + // Set as hidden as it should only be shown by |displayInfobarButton:| + self.locationBarSteadyView.leadingButton.hidden = YES; } #pragma mark - UIMenu
diff --git a/ios/chrome/browser/ui/settings/google_services/google_services_settings_egtest.mm b/ios/chrome/browser/ui/settings/google_services/google_services_settings_egtest.mm index 7d61d4d..0985c68 100644 --- a/ios/chrome/browser/ui/settings/google_services/google_services_settings_egtest.mm +++ b/ios/chrome/browser/ui/settings/google_services/google_services_settings_egtest.mm
@@ -40,7 +40,8 @@ @synthesize scrollViewMatcher = _scrollViewMatcher; // Opens the Google services settings view, and closes it. -- (void)testOpenGoogleServicesSettings { +// TODO(crbug.com/937855):reenable this test. +- (void)DISABLED_testOpenGoogleServicesSettings { [self openGoogleServicesSettings]; // Assert title and accessibility. @@ -54,7 +55,8 @@ } // Tests the Google Services settings. -- (void)testOpeningServices { +// TODO(crbug.com/937855):reenable this test. +- (void)DISABLED_testOpeningServices { [self openGoogleServicesSettings]; [self assertNonPersonalizedServices]; }
diff --git a/ios/chrome/browser/ui/side_swipe/BUILD.gn b/ios/chrome/browser/ui/side_swipe/BUILD.gn index 009ea90..0cd14b9c 100644 --- a/ios/chrome/browser/ui/side_swipe/BUILD.gn +++ b/ios/chrome/browser/ui/side_swipe/BUILD.gn
@@ -58,6 +58,7 @@ "//base/test:test_support", "//ios/chrome/browser", "//ios/chrome/browser/browser_state:test_support", + "//ios/chrome/browser/web_state_list", "//ios/web/public/test", "//testing/gtest", "//third_party/ocmock",
diff --git a/ios/chrome/browser/ui/side_swipe/side_swipe_controller.mm b/ios/chrome/browser/ui/side_swipe/side_swipe_controller.mm index 73214dac..8c70695 100644 --- a/ios/chrome/browser/ui/side_swipe/side_swipe_controller.mm +++ b/ios/chrome/browser/ui/side_swipe/side_swipe_controller.mm
@@ -30,6 +30,7 @@ #import "ios/chrome/browser/web/tab_id_tab_helper.h" #import "ios/chrome/browser/web/web_navigation_util.h" #import "ios/chrome/browser/web_state_list/web_state_list.h" +#import "ios/chrome/browser/web_state_list/web_state_list_observer_bridge.h" #import "ios/web/public/navigation_item.h" #import "ios/web/public/web_client.h" #import "ios/web/public/web_state/web_state_observer_bridge.h" @@ -57,9 +58,10 @@ const NSUInteger kIpadGreySwipeTabCount = 8; } -@interface SideSwipeController ()<CRWWebStateObserver, - TabModelObserver, - UIGestureRecognizerDelegate> { +@interface SideSwipeController () <CRWWebStateObserver, + TabModelObserver, + UIGestureRecognizerDelegate, + WebStateListObserving> { @private __weak TabModel* model_; @@ -87,6 +89,9 @@ // Bridge to observe the web state from Objective-C. std::unique_ptr<web::WebStateObserverBridge> webStateObserverBridge_; + // Bridge to observe the WebStateList from Objective-C. + std::unique_ptr<WebStateListObserverBridge> webStateListObserver_; + // Scoped observer used to track registration of the WebStateObserverBridge. std::unique_ptr<ScopedObserver<web::WebState, web::WebStateObserver>> scopedWebStateObserver_; @@ -110,6 +115,8 @@ @property(nonatomic, assign) BOOL leadingEdgeNavigationEnabled; // Whether to allow navigating from the trailing edge. @property(nonatomic, assign) BOOL trailingEdgeNavigationEnabled; +// The WebStateList that is being observed by this controller. +@property(nonatomic, assign, readonly) WebStateList* webStateList; // Load grey snapshots for the next |kIpadGreySwipeTabCount| tabs in // |direction|. @@ -139,6 +146,7 @@ _secondaryToolbarSnapshotProvider; @synthesize snapshotDelegate = snapshotDelegate_; @synthesize tabStripDelegate = tabStripDelegate_; +@synthesize webStateList = webStateList_; - (id)initWithTabModel:(TabModel*)model browserState:(ios::ChromeBrowserState*)browserState { @@ -147,6 +155,9 @@ if (self) { model_ = model; [model_ addObserver:self]; + webStateList_ = model_.webStateList; + webStateListObserver_ = std::make_unique<WebStateListObserverBridge>(self); + webStateList_->AddObserver(webStateListObserver_.get()); webStateObserverBridge_ = std::make_unique<web::WebStateObserverBridge>(self); scopedWebStateObserver_ = @@ -159,6 +170,7 @@ } - (void)dealloc { + webStateList_->RemoveObserver(webStateListObserver_.get()); [model_ removeObserver:self]; scopedWebStateObserver_.reset(); @@ -337,7 +349,7 @@ fullscreenDisabler_ = std::make_unique<ScopedFullscreenDisabler>( FullscreenControllerFactory::GetInstance()->GetForBrowserState( browserState_)); - SnapshotTabHelper::FromWebState([model_ currentTab].webState) + SnapshotTabHelper::FromWebState(webStateList_->GetActiveWebState()) ->UpdateSnapshotWithCallback(nil); [[NSNotificationCenter defaultCenter] postNotificationName:kSideSwipeWillStartNotification @@ -393,7 +405,7 @@ ->CancelPlaceholderForNextNavigation(); [model_ setCurrentTab:tab]; } - PagePlaceholderTabHelper::FromWebState([model_ currentTab].webState) + PagePlaceholderTabHelper::FromWebState(webStateList_->GetActiveWebState()) ->CancelPlaceholderForNextNavigation(); // Redisplay the view if it was in overlay preview mode. @@ -410,10 +422,9 @@ } - (BOOL)canNavigate:(BOOL)goBack { - WebStateList* webStateList = model_.webStateList; - if (!webStateList || !webStateList->GetActiveWebState()) + if (!webStateList_ || !webStateList_->GetActiveWebState()) return NO; - web::WebState* webState = webStateList->GetActiveWebState(); + web::WebState* webState = webStateList_->GetActiveWebState(); if (goBack && webState->GetNavigationManager()->CanGoBack()) { return YES; } @@ -503,7 +514,8 @@ // Show horizontal swipe stack view for iPhone. - (void)handleiPhoneTabSwipe:(SideSwipeGestureRecognizer*)gesture { if (gesture.state == UIGestureRecognizerStateBegan) { - Tab* currentTab = [model_ currentTab]; + DCHECK(webStateList_); + web::WebState* currentWebState = webStateList_->GetActiveWebState(); inSwipe_ = YES; @@ -513,11 +525,10 @@ // TODO(crbug.com/904992): Do not use SnapshotGeneratorDelegate from // SideSwipeController. CGFloat headerHeight = 0; - if (currentTab.webState) { - headerHeight = - [self.snapshotDelegate snapshotGenerator:nil - snapshotEdgeInsetsForWebState:currentTab.webState] - .top; + if (currentWebState) { + headerHeight = [self.snapshotDelegate snapshotGenerator:nil + snapshotEdgeInsetsForWebState:currentWebState] + .top; } if (tabSideSwipeView_) { @@ -539,8 +550,8 @@ } // Ensure that there's an up-to-date snapshot of the current tab. - if (currentTab.webState) { - SnapshotTabHelper::FromWebState(currentTab.webState) + if (currentWebState) { + SnapshotTabHelper::FromWebState(currentWebState) ->UpdateSnapshotWithCallback(nil); } @@ -652,20 +663,23 @@ #pragma mark - TabModelObserver Methods -- (void)tabModel:(TabModel*)model - didChangeActiveTab:(Tab*)newTab - previousTab:(Tab*)previousTab - atIndex:(NSUInteger)index { +- (void)tabModel:(TabModel*)model didChangeTab:(Tab*)tab { + [self updateNavigationEdgeSwipeForWebState:tab.webState]; +} + +#pragma mark - WebStateListObserving Methods + +- (void)webStateList:(WebStateList*)webStateList + didChangeActiveWebState:(web::WebState*)newWebState + oldWebState:(web::WebState*)oldWebState + atIndex:(int)atIndex + reason:(int)reason { // Toggling the gesture's enabled state off and on will effectively cancel // the gesture recognizer. [swipeGestureRecognizer_ setEnabled:NO]; [swipeGestureRecognizer_ setEnabled:YES]; - [self updateNavigationEdgeSwipeForWebState:newTab.webState]; -} - -- (void)tabModel:(TabModel*)model didChangeTab:(Tab*)tab { - [self updateNavigationEdgeSwipeForWebState:tab.webState]; + [self updateNavigationEdgeSwipeForWebState:newWebState]; } @end
diff --git a/ios/chrome/browser/ui/side_swipe/side_swipe_controller_unittest.mm b/ios/chrome/browser/ui/side_swipe/side_swipe_controller_unittest.mm index ebf411b0..ad32babd 100644 --- a/ios/chrome/browser/ui/side_swipe/side_swipe_controller_unittest.mm +++ b/ios/chrome/browser/ui/side_swipe/side_swipe_controller_unittest.mm
@@ -6,6 +6,9 @@ #include "base/test/scoped_feature_list.h" #include "ios/chrome/browser/browser_state/test_chrome_browser_state.h" #include "ios/chrome/browser/chrome_url_constants.h" +#import "ios/chrome/browser/web_state_list/web_state_list.h" +#import "ios/chrome/browser/web_state_list/web_state_list_delegate.h" +#import "ios/chrome/browser/web_state_list/web_state_opener.h" #include "ios/web/public/features.h" #import "ios/web/public/navigation_item.h" #import "ios/web/public/test/fakes/test_navigation_manager.h" @@ -28,11 +31,27 @@ namespace { +class TestWebStateListDelegate : public WebStateListDelegate { + void WillAddWebState(web::WebState* web_state) override {} + void WebStateDetached(web::WebState* web_state) override {} +}; + class SideSwipeControllerTest : public PlatformTest { public: void SetUp() override { // Create a mock for the TabModel that owns the object under test. tab_model_ = [OCMockObject niceMockForClass:[TabModel class]]; + std::unique_ptr<web::TestWebState> original_web_state( + std::make_unique<web::TestWebState>()); + + web_state_list_ = std::make_unique<WebStateList>(&web_state_list_delegate_); + web_state_list_->InsertWebState(0, std::move(original_web_state), + WebStateList::INSERT_NO_FLAGS, + WebStateOpener()); + + WebStateList* web_state_list = web_state_list_.get(); + [[[tab_model_ stub] andReturnValue:OCMOCK_VALUE(web_state_list)] + webStateList]; TestChromeBrowserState::Builder builder; browser_state_ = builder.Build(); @@ -48,8 +67,11 @@ web::TestWebThreadBundle thread_bundle_; std::unique_ptr<TestChromeBrowserState> browser_state_; + TestWebStateListDelegate web_state_list_delegate_; + std::unique_ptr<WebStateList> web_state_list_; + UIView* view_; - TabModel* tab_model_; + id tab_model_; SideSwipeController* side_swipe_controller_; base::test::ScopedFeatureList feature_list_; }; @@ -108,6 +130,19 @@ updateNavigationEdgeSwipeForWebState:testWebState.get()]; EXPECT_FALSE(side_swipe_controller_.leadingEdgeNavigationEnabled); EXPECT_FALSE(side_swipe_controller_.trailingEdgeNavigationEnabled); + + // Tests that when webstate is nil calling + // updateNavigationEdgeSwipeForWebState doesn't change the edge navigation + // state. + item->SetURL(GURL("http://wwww.test.com")); + [side_swipe_controller_ updateNavigationEdgeSwipeForWebState:nil]; + EXPECT_FALSE(side_swipe_controller_.leadingEdgeNavigationEnabled); + EXPECT_FALSE(side_swipe_controller_.trailingEdgeNavigationEnabled); + side_swipe_controller_.leadingEdgeNavigationEnabled = YES; + side_swipe_controller_.trailingEdgeNavigationEnabled = YES; + [side_swipe_controller_ updateNavigationEdgeSwipeForWebState:nil]; + EXPECT_TRUE(side_swipe_controller_.leadingEdgeNavigationEnabled); + EXPECT_TRUE(side_swipe_controller_.trailingEdgeNavigationEnabled); } } // anonymous namespace
diff --git a/ios/components/io_thread/ios_io_thread.mm b/ios/components/io_thread/ios_io_thread.mm index 514d5900..d1d5f57 100644 --- a/ios/components/io_thread/ios_io_thread.mm +++ b/ios/components/io_thread/ios_io_thread.mm
@@ -213,8 +213,8 @@ DCHECK_CURRENTLY_ON(web::WebThread::UI); base::PostTaskWithTraits( FROM_HERE, {web::WebThread::IO}, - base::Bind(&IOSIOThread::ChangedToOnTheRecordOnIOThread, - base::Unretained(this))); + base::BindOnce(&IOSIOThread::ChangedToOnTheRecordOnIOThread, + base::Unretained(this))); } net::URLRequestContextGetter* IOSIOThread::system_url_request_context_getter() {
diff --git a/ios/third_party/earl_grey2/BUILD.gn b/ios/third_party/earl_grey2/BUILD.gn index 0d8f4051..52aeeb6 100644 --- a/ios/third_party/earl_grey2/BUILD.gn +++ b/ios/third_party/earl_grey2/BUILD.gn
@@ -31,6 +31,9 @@ "src/CommonLib/Additions/NSString+GREYCommon.m", "src/CommonLib/Additions/UIView+GREYCommon.h", "src/CommonLib/Additions/UIView+GREYCommon.m", + "src/CommonLib/Assertion/GREYAssertion.h", + "src/CommonLib/Assertion/GREYAssertionBlock.h", + "src/CommonLib/Assertion/GREYAssertionBlock.m", "src/CommonLib/Config/GREYAppState.h", "src/CommonLib/Config/GREYConfigKey.h", "src/CommonLib/Config/GREYConfigKey.m", @@ -62,7 +65,11 @@ "src/CommonLib/GREYStopwatch.m", "src/CommonLib/GREYSwizzler.h", "src/CommonLib/GREYSwizzler.m", + "src/CommonLib/Matcher/GREYBaseMatcher.h", + "src/CommonLib/Matcher/GREYBaseMatcher.m", "src/CommonLib/Matcher/GREYDescription.h", + "src/CommonLib/Matcher/GREYElementMatcherBlock.h", + "src/CommonLib/Matcher/GREYElementMatcherBlock.m", "src/CommonLib/Matcher/GREYLayoutConstraint.h", "src/CommonLib/Matcher/GREYLayoutConstraint.m", "src/CommonLib/Matcher/GREYStringDescription.h", @@ -157,7 +164,9 @@ testonly = true sources = [ + "src/AppFramework/Action/GREYAction.h", "src/AppFramework/Action/GREYActions.h", + "src/AppFramework/Action/GREYActionsShorthand.h", "src/AppFramework/Config/GREYAppConfiguration.h", "src/AppFramework/Core/GREYElementInteraction.h", "src/AppFramework/DistantObject/GREYHostApplicationDistantObject+GREYTestHelper.h", @@ -186,6 +195,8 @@ "src/AppFramework/Action/GREYActionBlock.m", "src/AppFramework/Action/GREYActions+Internal.h", "src/AppFramework/Action/GREYActions.m", + "src/AppFramework/Action/GREYActionsShorthand.h", + "src/AppFramework/Action/GREYActionsShorthand.m", "src/AppFramework/Action/GREYBaseAction.h", "src/AppFramework/Action/GREYBaseAction.m", "src/AppFramework/Action/GREYChangeStepperAction.h", @@ -248,9 +259,6 @@ "src/AppFramework/Additions/UIWindow+GREYApp.m", "src/AppFramework/Additions/__NSCFLocalDataTask_GREYApp.h", "src/AppFramework/Additions/__NSCFLocalDataTask_GREYApp.m", - "src/AppFramework/Assertion/GREYAssertion.h", - "src/AppFramework/Assertion/GREYAssertionBlock.h", - "src/AppFramework/Assertion/GREYAssertionBlock.m", "src/AppFramework/Assertion/GREYAssertions.h", "src/AppFramework/Assertion/GREYAssertions.m", "src/AppFramework/AutomationSetup/GREYAutomationSetup.h", @@ -298,10 +306,6 @@ "src/AppFramework/Keyboard/GREYKeyboard.m", "src/AppFramework/Matcher/GREYAllOf.m", "src/AppFramework/Matcher/GREYAnyOf.m", - "src/AppFramework/Matcher/GREYBaseMatcher.h", - "src/AppFramework/Matcher/GREYBaseMatcher.m", - "src/AppFramework/Matcher/GREYElementMatcherBlock.h", - "src/AppFramework/Matcher/GREYElementMatcherBlock.m", "src/AppFramework/Matcher/GREYMatchers.m", "src/AppFramework/Matcher/GREYMatchersShorthand.m", "src/AppFramework/Matcher/GREYNot.m", @@ -371,10 +375,9 @@ testonly = true sources = [ + "src/AppFramework/Action/GREYActionsShorthand.m", "src/AppFramework/Error/GREYFailureScreenshotterStub.m", "src/AppFramework/Matcher/GREYMatchersShorthand.m", - "src/TestLib/Action/GREYActionsShorthand.h", - "src/TestLib/Action/GREYActionsShorthand.m", "src/TestLib/AlertHandling/XCTestCase+GREYSystemAlertHandler.h", "src/TestLib/AlertHandling/XCTestCase+GREYSystemAlertHandler.m", "src/TestLib/Analytics/GREYAnalytics.h",
diff --git a/ios/web/app/web_main_loop.mm b/ios/web/app/web_main_loop.mm index 87d630cf..89eb975 100644 --- a/ios/web/app/web_main_loop.mm +++ b/ios/web/app/web_main_loop.mm
@@ -164,8 +164,8 @@ base::ThreadRestrictions::SetIOAllowed(true); base::PostTaskWithTraits( FROM_HERE, {WebThread::IO}, - base::Bind(base::IgnoreResult(&base::ThreadRestrictions::SetIOAllowed), - true)); + base::BindOnce( + base::IgnoreResult(&base::ThreadRestrictions::SetIOAllowed), true)); // Also allow waiting to join threads. // TODO(crbug.com/800808): Ideally this (and the above SetIOAllowed()
diff --git a/ios/web/net/cookie_notification_bridge.mm b/ios/web/net/cookie_notification_bridge.mm index ff3a7a4..27715762 100644 --- a/ios/web/net/cookie_notification_bridge.mm +++ b/ios/web/net/cookie_notification_bridge.mm
@@ -40,7 +40,7 @@ isEqualToString:NSHTTPCookieManagerCookiesChangedNotification]); base::PostTaskWithTraits( FROM_HERE, {web::WebThread::IO}, - base::Bind(&net::CookieStoreIOS::NotifySystemCookiesChanged)); + base::BindOnce(&net::CookieStoreIOS::NotifySystemCookiesChanged)); } } // namespace web
diff --git a/ios/web/net/request_tracker_impl.mm b/ios/web/net/request_tracker_impl.mm index 413f326..57742a43 100644 --- a/ios/web/net/request_tracker_impl.mm +++ b/ios/web/net/request_tracker_impl.mm
@@ -187,9 +187,9 @@ DCHECK(policy_cache); // Take care of the IO-thread init. - base::PostTaskWithTraits( - FROM_HERE, {web::WebThread::IO}, - base::Bind(&RequestTrackerImpl::InitOnIOThread, tracker, policy_cache)); + base::PostTaskWithTraits(FROM_HERE, {web::WebThread::IO}, + base::BindOnce(&RequestTrackerImpl::InitOnIOThread, + tracker, policy_cache)); RegisterTracker(tracker.get(), request_group_id); return tracker; } @@ -197,23 +197,23 @@ void RequestTrackerImpl::StartPageLoad(const GURL& url, id user_info) { DCHECK_CURRENTLY_ON(web::WebThread::UI); id scoped_user_info = user_info; - base::PostTaskWithTraits( - FROM_HERE, {web::WebThread::IO}, - base::Bind(&RequestTrackerImpl::TrimToURL, this, url, scoped_user_info)); + base::PostTaskWithTraits(FROM_HERE, {web::WebThread::IO}, + base::BindOnce(&RequestTrackerImpl::TrimToURL, this, + url, scoped_user_info)); } void RequestTrackerImpl::FinishPageLoad(const GURL& url, bool load_success) { DCHECK_CURRENTLY_ON(web::WebThread::UI); - base::PostTaskWithTraits( - FROM_HERE, {web::WebThread::IO}, - base::Bind(&RequestTrackerImpl::StopPageLoad, this, url, load_success)); + base::PostTaskWithTraits(FROM_HERE, {web::WebThread::IO}, + base::BindOnce(&RequestTrackerImpl::StopPageLoad, + this, url, load_success)); } void RequestTrackerImpl::HistoryStateChange(const GURL& url) { DCHECK_CURRENTLY_ON(web::WebThread::UI); base::PostTaskWithTraits( FROM_HERE, {web::WebThread::IO}, - base::Bind(&RequestTrackerImpl::HistoryStateChangeToURL, this, url)); + base::BindOnce(&RequestTrackerImpl::HistoryStateChangeToURL, this, url)); } // Close is called when an owning object (a Tab or something that acts like @@ -228,7 +228,7 @@ // be set before destruction begins. base::PostTaskWithTraits( FROM_HERE, {web::WebThread::IO}, - base::Bind( + base::BindOnce( [](RequestTrackerImpl* tracker) { tracker->is_closing_ = true; }, base::RetainedRef(this))); @@ -264,7 +264,7 @@ g_waiting_on_io_thread = true; } base::PostTaskWithTraits(FROM_HERE, {web::WebThread::IO}, - base::Bind(&StopIOThreadWaiting)); + base::BindOnce(&StopIOThreadWaiting)); // Poll endlessly until the wait flag is unset on the IO thread by // StopIOThreadWaiting(). @@ -526,7 +526,7 @@ notification_depth_ += 1; base::PostTaskWithTraits( FROM_HERE, {web::WebThread::IO}, - base::Bind(&RequestTrackerImpl::StackNotification, this)); + base::BindOnce(&RequestTrackerImpl::StackNotification, this)); } void RequestTrackerImpl::StackNotification() {
diff --git a/ios/web/web_state/web_frame_impl_unittest.mm b/ios/web/web_state/web_frame_impl_unittest.mm index 4eefe8b..b5d5b915 100644 --- a/ios/web/web_state/web_frame_impl_unittest.mm +++ b/ios/web/web_state/web_frame_impl_unittest.mm
@@ -254,29 +254,30 @@ EXPECT_TRUE(aead.Open(decoded_ciphertext, decoded_iv, /*additional_data=*/nullptr, &plaintext)); - std::unique_ptr<base::Value> parsed_result( - base::JSONReader::ReadDeprecated(plaintext, false)); - EXPECT_TRUE(parsed_result.get()); + base::Optional<base::Value> parsed_result = + base::JSONReader::Read(plaintext, false); + EXPECT_TRUE(parsed_result.has_value()); + ASSERT_TRUE(parsed_result.value().is_dict()); - base::DictionaryValue* result_dict; - ASSERT_TRUE(parsed_result->GetAsDictionary(&result_dict)); + base::Optional<int> decrypted_message_id = + parsed_result.value().FindIntKey("messageId"); + ASSERT_TRUE(decrypted_message_id.has_value()); + EXPECT_EQ(decrypted_message_id.value(), initial_message_id); - int decrypted_message_id = 0; - EXPECT_TRUE(result_dict->GetInteger("messageId", &decrypted_message_id)); - EXPECT_EQ(initial_message_id, decrypted_message_id); + base::Optional<bool> decrypted_respond_with_result = + parsed_result.value().FindBoolKey("replyWithResult"); + ASSERT_TRUE(decrypted_respond_with_result.has_value()); + EXPECT_FALSE(decrypted_respond_with_result.value()); - bool decrypted_respond_with_result = true; - EXPECT_TRUE(result_dict->GetBoolean("replyWithResult", - &decrypted_respond_with_result)); - EXPECT_FALSE(decrypted_respond_with_result); + const std::string* decrypted_function_name = + parsed_result.value().FindStringKey("functionName"); + ASSERT_TRUE(decrypted_function_name); + EXPECT_EQ("functionName", *decrypted_function_name); - std::string decrypted_functionName; - EXPECT_TRUE(result_dict->GetString("functionName", &decrypted_functionName)); - EXPECT_STREQ("functionName", decrypted_functionName.c_str()); - - base::ListValue* decrypted_parameters; - EXPECT_TRUE(result_dict->GetList("parameters", &decrypted_parameters)); - EXPECT_EQ(function_params.size(), decrypted_parameters->GetList().size()); + base::Value* decrypted_parameters = parsed_result.value().FindKeyOfType( + "parameters", base::Value::Type::LIST); + ASSERT_TRUE(decrypted_parameters); + ASSERT_EQ(function_params.size(), decrypted_parameters->GetList().size()); EXPECT_EQ(plaintext_param, decrypted_parameters->GetList()[0].GetString()); } @@ -325,17 +326,15 @@ EXPECT_TRUE(aead.Open(decoded_ciphertext, decoded_iv, /*additional_data=*/nullptr, &plaintext)); - std::unique_ptr<base::Value> parsed_result( - base::JSONReader::ReadDeprecated(plaintext, false)); - EXPECT_TRUE(parsed_result.get()); + base::Optional<base::Value> parsed_result = + base::JSONReader::Read(plaintext, false); + EXPECT_TRUE(parsed_result.has_value()); + ASSERT_TRUE(parsed_result.value().is_dict()); - base::DictionaryValue* result_dict; - ASSERT_TRUE(parsed_result->GetAsDictionary(&result_dict)); - - bool decrypted_respond_with_result = false; - EXPECT_TRUE(result_dict->GetBoolean("replyWithResult", - &decrypted_respond_with_result)); - EXPECT_TRUE(decrypted_respond_with_result); + base::Optional<bool> decrypted_respond_with_result = + parsed_result.value().FindBoolKey("replyWithResult"); + ASSERT_TRUE(decrypted_respond_with_result.has_value()); + EXPECT_TRUE(decrypted_respond_with_result.value()); } // Tests that the WebFrame properly creates JavaScript for the main frame when
diff --git a/ios/web/webui/url_data_manager_ios.cc b/ios/web/webui/url_data_manager_ios.cc index 599336e..d619537 100644 --- a/ios/web/webui/url_data_manager_ios.cc +++ b/ios/web/webui/url_data_manager_ios.cc
@@ -69,8 +69,8 @@ DCHECK_CURRENTLY_ON(web::WebThread::UI); base::PostTaskWithTraits( FROM_HERE, {web::WebThread::IO}, - base::Bind(&AddDataSourceOnIOThread, base::Unretained(browser_state_), - base::WrapRefCounted(source))); + base::BindOnce(&AddDataSourceOnIOThread, base::Unretained(browser_state_), + base::WrapRefCounted(source))); } // static @@ -109,8 +109,9 @@ } if (schedule_delete) { // Schedule a task to delete the DataSource back on the UI thread. - base::PostTaskWithTraits(FROM_HERE, {web::WebThread::UI}, - base::Bind(&URLDataManagerIOS::DeleteDataSources)); + base::PostTaskWithTraits( + FROM_HERE, {web::WebThread::UI}, + base::BindOnce(&URLDataManagerIOS::DeleteDataSources)); } }
diff --git a/ios/web/webui/url_data_manager_ios_backend.mm b/ios/web/webui/url_data_manager_ios_backend.mm index 69fe8fe..b8dfc04 100644 --- a/ios/web/webui/url_data_manager_ios_backend.mm +++ b/ios/web/webui/url_data_manager_ios_backend.mm
@@ -394,8 +394,8 @@ std::string mime_type = source->source()->GetMimeType(path); base::PostTaskWithTraits( FROM_HERE, {WebThread::IO}, - base::Bind(&URLRequestChromeJob::MimeTypeAvailable, job, - base::RetainedRef(source), mime_type)); + base::BindOnce(&URLRequestChromeJob::MimeTypeAvailable, job, + base::RetainedRef(source), mime_type)); } } // namespace
diff --git a/ios/web/webui/url_data_source_ios_impl.cc b/ios/web/webui/url_data_source_ios_impl.cc index 9257cec2..33907b9 100644 --- a/ios/web/webui/url_data_source_ios_impl.cc +++ b/ios/web/webui/url_data_source_ios_impl.cc
@@ -44,8 +44,8 @@ } base::PostTaskWithTraits( FROM_HERE, {web::WebThread::IO}, - base::Bind(&URLDataSourceIOSImpl::SendResponseOnIOThread, this, - request_id, std::move(bytes))); + base::BindOnce(&URLDataSourceIOSImpl::SendResponseOnIOThread, this, + request_id, std::move(bytes))); } void URLDataSourceIOSImpl::SendResponseOnIOThread(
diff --git a/media/renderers/video_renderer_impl_unittest.cc b/media/renderers/video_renderer_impl_unittest.cc index d13692ed..a7cdc49 100644 --- a/media/renderers/video_renderer_impl_unittest.cc +++ b/media/renderers/video_renderer_impl_unittest.cc
@@ -11,7 +11,6 @@ #include "base/callback.h" #include "base/callback_helpers.h" #include "base/containers/circular_deque.h" -#include "base/debug/stack_trace.h" #include "base/macros.h" #include "base/memory/ptr_util.h" #include "base/run_loop.h"
diff --git a/net/dns/host_resolver_impl.cc b/net/dns/host_resolver_impl.cc index 7d54863e..6e38743 100644 --- a/net/dns/host_resolver_impl.cc +++ b/net/dns/host_resolver_impl.cc
@@ -31,7 +31,6 @@ #include "base/compiler_specific.h" #include "base/containers/linked_list.h" #include "base/debug/debugger.h" -#include "base/debug/stack_trace.h" #include "base/logging.h" #include "base/macros.h" #include "base/memory/ptr_util.h"
diff --git a/net/http/http_network_session.cc b/net/http/http_network_session.cc index 178292c..a8fd266 100644 --- a/net/http/http_network_session.cc +++ b/net/http/http_network_session.cc
@@ -10,7 +10,6 @@ #include "base/atomic_sequence_num.h" #include "base/compiler_specific.h" -#include "base/debug/stack_trace.h" #include "base/logging.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_util.h"
diff --git a/net/socket/client_socket_pool_base.cc b/net/socket/client_socket_pool_base.cc index 7a44766..e235a12 100644 --- a/net/socket/client_socket_pool_base.cc +++ b/net/socket/client_socket_pool_base.cc
@@ -560,10 +560,9 @@ } const Group& group = *group_it->second; - if (group.HasConnectJobForHandle(handle)) { - // Just return the state of the oldest ConnectJob. - return (*group.jobs().begin())->GetLoadState(); - } + ConnectJob* job = group.GetConnectJobForHandle(handle); + if (job) + return job->GetLoadState(); if (group.CanUseAdditionalSocketSlot(max_sockets_per_group_)) return LOAD_STATE_WAITING_FOR_STALLED_SOCKET_POOL; @@ -1459,12 +1458,12 @@ return bound_requests_.size() + jobs_.size(); } -bool ClientSocketPoolBaseHelper::Group::HasConnectJobForHandle( +ConnectJob* ClientSocketPoolBaseHelper::Group::GetConnectJobForHandle( const ClientSocketHandle* handle) const { // Search through bound requests for |handle|. for (const auto& bound_pair : bound_requests_) { if (handle == bound_pair.request->handle()) - return true; + return bound_pair.connect_job.get(); } // Search through the unbound requests that have corresponding jobs for a @@ -1473,10 +1472,10 @@ !pointer.is_null() && pointer.value()->job(); pointer = unbound_requests_.GetNextTowardsLastMin(pointer)) { if (pointer.value()->handle() == handle) - return true; + return pointer.value()->job(); } - return false; + return nullptr; } void ClientSocketPoolBaseHelper::Group::InsertUnboundRequest( @@ -1630,7 +1629,7 @@ bool ClientSocketPoolBaseHelper::Group::RequestWithHandleHasJobForTesting( const ClientSocketHandle* handle) const { SanityCheck(); - if (HasConnectJobForHandle(handle)) + if (GetConnectJobForHandle(handle)) return true; // There's no corresponding ConnectJob. Verify that the handle is at least
diff --git a/net/socket/client_socket_pool_base.h b/net/socket/client_socket_pool_base.h index 0c333af..ca59a42 100644 --- a/net/socket/client_socket_pool_base.h +++ b/net/socket/client_socket_pool_base.h
@@ -412,8 +412,10 @@ size_t ConnectJobCount() const; - // Returns true if there is a connect job for |handle|. - bool HasConnectJobForHandle(const ClientSocketHandle* handle) const; + // Returns the connect job correspding to |handle|. In particular, if + // |handle| is bound to a ConnectJob, returns that job. If |handle| is + // "assigned" a ConnectJob, return that job. Otherwise, returns nullptr. + ConnectJob* GetConnectJobForHandle(const ClientSocketHandle* handle) const; // Inserts the request into the queue based on priority // order. Older requests are prioritized over requests of equal
diff --git a/net/socket/client_socket_pool_base_unittest.cc b/net/socket/client_socket_pool_base_unittest.cc index cc3d9dc..16e52842 100644 --- a/net/socket/client_socket_pool_base_unittest.cc +++ b/net/socket/client_socket_pool_base_unittest.cc
@@ -473,15 +473,19 @@ return ret; } case kMockAuthChallengeOnceJob: + set_load_state(LOAD_STATE_CONNECTING); DoAdvanceAuthChallenge(1, true /* succeed_after_last_challenge */); return ERR_IO_PENDING; case kMockAuthChallengeTwiceJob: + set_load_state(LOAD_STATE_CONNECTING); DoAdvanceAuthChallenge(2, true /* succeed_after_last_challenge */); return ERR_IO_PENDING; case kMockAuthChallengeOnceFailingJob: + set_load_state(LOAD_STATE_CONNECTING); DoAdvanceAuthChallenge(1, false /* succeed_after_last_challenge */); return ERR_IO_PENDING; case kMockAuthChallengeTwiceFailingJob: + set_load_state(LOAD_STATE_CONNECTING); DoAdvanceAuthChallenge(2, false /* succeed_after_last_challenge */); return ERR_IO_PENDING; default: @@ -523,6 +527,7 @@ void InvokeNextProxyAuthCallback(int remaining_challenges, bool succeed_after_last_challenge) { + set_load_state(LOAD_STATE_ESTABLISHING_PROXY_TUNNEL); if (remaining_challenges == 0) { DoConnect(succeed_after_last_challenge, true /* was_async */, false /* cert_error */); @@ -2126,7 +2131,6 @@ } // Test GetLoadState in the case there are two socket requests. -// Only the first connection in the pool should affect the pool's load status. TEST_F(ClientSocketPoolBaseTest, LoadStateTwoRequests) { CreatePool(2, 2); connect_job_factory_->set_job_type(TestConnectJob::kMockWaitingJob); @@ -2149,48 +2153,29 @@ EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); client_socket_factory_.SetJobLoadState(1, LOAD_STATE_RESOLVING_HOST); - // Check that both handles report the state of the first job. + // Each handle should reflect the state of its own job. EXPECT_EQ(LOAD_STATE_RESOLVING_HOST, handle.GetLoadState()); EXPECT_EQ(LOAD_STATE_RESOLVING_HOST, handle2.GetLoadState()); + // Update the state of the first job. client_socket_factory_.SetJobLoadState(0, LOAD_STATE_CONNECTING); - // Check that both handles change to LOAD_STATE_CONNECTING. + // Only the state of the first request should have changed. EXPECT_EQ(LOAD_STATE_CONNECTING, handle.GetLoadState()); - EXPECT_EQ(LOAD_STATE_CONNECTING, handle2.GetLoadState()); -} - -// Test that the second connection request does not affect the pool's load -// status. -TEST_F(ClientSocketPoolBaseTest, LoadStateTwoRequestsChangeSecondRequestState) { - CreatePool(2, 2); - connect_job_factory_->set_job_type(TestConnectJob::kMockWaitingJob); - - ClientSocketHandle handle; - TestCompletionCallback callback; - int rv = handle.Init( - "a", params_, DEFAULT_PRIORITY, SocketTag(), - ClientSocketPool::RespectLimits::ENABLED, callback.callback(), - ClientSocketPool::ProxyAuthCallback(), pool_.get(), NetLogWithSource()); - EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); - - ClientSocketHandle handle2; - TestCompletionCallback callback2; - rv = handle2.Init("a", params_, DEFAULT_PRIORITY, SocketTag(), - ClientSocketPool::RespectLimits::ENABLED, - callback2.callback(), ClientSocketPool::ProxyAuthCallback(), - pool_.get(), NetLogWithSource()); - EXPECT_THAT(rv, IsError(ERR_IO_PENDING)); - client_socket_factory_.SetJobLoadState(1, LOAD_STATE_RESOLVING_HOST); - - EXPECT_EQ(LOAD_STATE_CONNECTING, handle.GetLoadState()); - EXPECT_EQ(LOAD_STATE_CONNECTING, handle2.GetLoadState()); - - // First job connects and the first request gets the socket. The - // second handle switches to the state of the remaining ConnectJob. - client_socket_factory_.SignalJob(0); - EXPECT_THAT(callback.WaitForResult(), IsOk()); EXPECT_EQ(LOAD_STATE_RESOLVING_HOST, handle2.GetLoadState()); + + // Update the state of the second job. + client_socket_factory_.SetJobLoadState(1, LOAD_STATE_SSL_HANDSHAKE); + + // Only the state of the second request should have changed. + EXPECT_EQ(LOAD_STATE_CONNECTING, handle.GetLoadState()); + EXPECT_EQ(LOAD_STATE_SSL_HANDSHAKE, handle2.GetLoadState()); + + // Second job connects and the first request gets the socket. The + // second handle switches to the state of the remaining ConnectJob. + client_socket_factory_.SignalJob(1); + EXPECT_THAT(callback.WaitForResult(), IsOk()); + EXPECT_EQ(LOAD_STATE_CONNECTING, handle2.GetLoadState()); } // Test GetLoadState in the case the per-group limit is reached. @@ -4821,12 +4806,18 @@ TestAuthHelper auth_helper; auth_helper.InitHandle(params_, pool_.get()); EXPECT_EQ(1u, pool_->NumConnectJobsInGroup("a")); + EXPECT_EQ(LOAD_STATE_CONNECTING, + pool_->GetLoadState("a", auth_helper.handle())); auth_helper.WaitForAuth(); EXPECT_EQ(1u, pool_->NumConnectJobsInGroup("a")); + EXPECT_EQ(LOAD_STATE_ESTABLISHING_PROXY_TUNNEL, + pool_->GetLoadState("a", auth_helper.handle())); auth_helper.RestartWithAuth(); EXPECT_EQ(1u, pool_->NumConnectJobsInGroup("a")); + EXPECT_EQ(LOAD_STATE_ESTABLISHING_PROXY_TUNNEL, + pool_->GetLoadState("a", auth_helper.handle())); EXPECT_THAT(auth_helper.WaitForResult(), IsOk()); EXPECT_EQ(1, auth_helper.auth_count()); @@ -4843,9 +4834,13 @@ TestAuthHelper auth_helper; auth_helper.InitHandle(params_, pool_.get()); EXPECT_EQ(1u, pool_->NumConnectJobsInGroup("a")); + EXPECT_EQ(LOAD_STATE_CONNECTING, + pool_->GetLoadState("a", auth_helper.handle())); auth_helper.WaitForAuthAndRestartSync(); EXPECT_EQ(1u, pool_->NumConnectJobsInGroup("a")); + EXPECT_EQ(LOAD_STATE_ESTABLISHING_PROXY_TUNNEL, + pool_->GetLoadState("a", auth_helper.handle())); EXPECT_THAT(auth_helper.WaitForResult(), IsOk()); EXPECT_EQ(1, auth_helper.auth_count()); @@ -4962,16 +4957,27 @@ TestAuthHelper auth_helper; auth_helper.InitHandle(params_, pool_.get()); EXPECT_EQ(1u, pool_->NumConnectJobsInGroup("a")); + EXPECT_EQ(LOAD_STATE_CONNECTING, + pool_->GetLoadState("a", auth_helper.handle())); auth_helper.WaitForAuth(); auth_helper.RestartWithAuth(); EXPECT_EQ(1u, pool_->NumConnectJobsInGroup("a")); EXPECT_EQ(1, auth_helper.auth_count()); + EXPECT_EQ(LOAD_STATE_ESTABLISHING_PROXY_TUNNEL, + pool_->GetLoadState("a", auth_helper.handle())); auth_helper.WaitForAuth(); + EXPECT_EQ(1u, pool_->NumConnectJobsInGroup("a")); + EXPECT_EQ(2, auth_helper.auth_count()); + EXPECT_EQ(LOAD_STATE_ESTABLISHING_PROXY_TUNNEL, + pool_->GetLoadState("a", auth_helper.handle())); + auth_helper.RestartWithAuth(); EXPECT_EQ(1u, pool_->NumConnectJobsInGroup("a")); EXPECT_EQ(2, auth_helper.auth_count()); + EXPECT_EQ(LOAD_STATE_ESTABLISHING_PROXY_TUNNEL, + pool_->GetLoadState("a", auth_helper.handle())); EXPECT_THAT(auth_helper.WaitForResult(), IsOk()); EXPECT_EQ(2, auth_helper.auth_count());
diff --git a/services/network/resource_scheduler.cc b/services/network/resource_scheduler.cc index 4d1e8b7..a44ebe4 100644 --- a/services/network/resource_scheduler.cc +++ b/services/network/resource_scheduler.cc
@@ -401,6 +401,10 @@ pending_requests_.Erase(request); DCHECK(!base::ContainsKey(in_flight_requests_, request)); } else { + // Record metrics. + if (!RequestAttributesAreSet(request->attributes(), kAttributeDelayable)) + last_non_delayable_request_end_ = tick_clock_->NowTicks(); + RecordNetworkContentionMetrics(*request); EraseInFlightRequest(request); // Removing this request may have freed up another to load. @@ -523,8 +527,6 @@ } void EraseInFlightRequest(ScheduledResourceRequestImpl* request) { - if (request) - RecordNetworkContentionMetrics(*request); size_t erased = in_flight_requests_.erase(request); DCHECK_EQ(1u, erased); // Clear any special state that we were tracking for this request. @@ -667,9 +669,55 @@ return false; } + void RecordMetricsOnStartRequest(const ScheduledResourceRequestImpl& request, + base::TimeTicks ticks_now) const { + // Record the number of delayable requests in-flight when a non-delayable + // request starts. + if (!RequestAttributesAreSet(request.attributes(), kAttributeDelayable)) { + UMA_HISTOGRAM_COUNTS_100( + "ResourceScheduler.NumDelayableRequestsInFlightAtStart.NonDelayable", + in_flight_delayable_count_); + if (last_non_delayable_request_start_.has_value()) { + UMA_HISTOGRAM_MEDIUM_TIMES( + "ResourceScheduler.NonDelayableLastStartToNonDelayableStart", + ticks_now - last_non_delayable_request_start_.value()); + } + if (last_non_delayable_request_end_.has_value()) { + UMA_HISTOGRAM_MEDIUM_TIMES( + "ResourceScheduler.NonDelayableLastEndToNonDelayableStart", + ticks_now - last_non_delayable_request_end_.value()); + } + + // Record time since last non-delayable request start or end, whichever + // happened later. + base::Optional<base::TimeTicks> last_non_delayable_request_start_or_end; + if (last_non_delayable_request_start_.has_value() && + !last_non_delayable_request_end_.has_value()) { + last_non_delayable_request_start_or_end = + last_non_delayable_request_start_; + } else if (!last_non_delayable_request_start_.has_value() && + last_non_delayable_request_end_.has_value()) { + last_non_delayable_request_start_or_end = + last_non_delayable_request_end_; + } else if (last_non_delayable_request_start_.has_value() && + last_non_delayable_request_end_.has_value()) { + last_non_delayable_request_start_or_end = + std::max(last_non_delayable_request_start_.value(), + last_non_delayable_request_end_.value()); + } + + if (last_non_delayable_request_start_or_end) { + UMA_HISTOGRAM_MEDIUM_TIMES( + "ResourceScheduler.NonDelayableLastStartOrEndToNonDelayableStart", + ticks_now - last_non_delayable_request_start_or_end.value()); + } + } + } + void StartRequest(ScheduledResourceRequestImpl* request, StartMode start_mode, RequestStartTrigger trigger) { + const base::TimeTicks ticks_now = tick_clock_->NowTicks(); // Only log on requests that were blocked by the ResourceScheduler. if (start_mode == START_ASYNC) { DCHECK_NE(RequestStartTrigger::NONE, trigger); @@ -678,17 +726,12 @@ net::NetLog::StringCallback("trigger", RequestStartTriggerString(trigger))); } - // Record the number of delayable requests in-flight when a non-delayable - // request starts. - if (!RequestAttributesAreSet(request->attributes(), kAttributeDelayable)) { - UMA_HISTOGRAM_COUNTS_100( - "ResourceScheduler.NumDelayableRequestsInFlightAtStart.NonDelayable", - in_flight_delayable_count_); - } + if (request) + RecordMetricsOnStartRequest(*request, ticks_now); DCHECK(!request->url_request()->creation_time().is_null()); base::TimeDelta queuing_duration = - tick_clock_->NowTicks() - request->url_request()->creation_time(); + ticks_now - request->url_request()->creation_time(); base::UmaHistogramMediumTimes( "ResourceScheduler.RequestQueuingDuration.Priority" + base::NumberToString( @@ -697,7 +740,7 @@ // Update the start time of the non-delayble request. if (!RequestAttributesAreSet(request->attributes(), kAttributeDelayable)) - last_non_delayable_request_start_ = tick_clock_->NowTicks(); + last_non_delayable_request_start_ = ticks_now; InsertInFlightRequest(request); request->Start(start_mode); @@ -955,6 +998,9 @@ // Time when the last non-delayble request started in this client. base::Optional<base::TimeTicks> last_non_delayable_request_start_; + // Time when the last non-delayble request ended in this client. + base::Optional<base::TimeTicks> last_non_delayable_request_end_; + base::WeakPtrFactory<ResourceScheduler::Client> weak_ptr_factory_; };
diff --git a/services/network/resource_scheduler_unittest.cc b/services/network/resource_scheduler_unittest.cc index 9e6ae53..e3e2e4a 100644 --- a/services/network/resource_scheduler_unittest.cc +++ b/services/network/resource_scheduler_unittest.cc
@@ -47,6 +47,36 @@ namespace { +// Verifies that (i) Exactly one sample is recorded in |histogram_name|; and, +// (ii) The sample value is at least |min_value|. +void ExpectSampleIsAtLeastSpecifiedValue( + const base::HistogramTester& histogram_tester, + const std::string& histogram_name, + int min_value) { + histogram_tester.ExpectTotalCount(histogram_name, 1); + + // Verify if the recorded unique sample is in the same bucket to which + // |min_value| belongs to. + if (histogram_tester.GetBucketCount(histogram_name, min_value) == 1) { + return; + } + + // Verify if the recorded unique sample is in a bucket that contains samples + // larger than |min_value|. + const std::vector<base::Bucket> buckets = + histogram_tester.GetAllSamples(histogram_name); + EXPECT_EQ(1u, buckets.size()); + bool sample_found = false; + for (const auto& bucket : buckets) { + if (bucket.count > 0) { + // Verify that the sample is at least |min_value|. + EXPECT_GE(bucket.min, min_value); + sample_found = true; + } + } + EXPECT_TRUE(sample_found); +} + class TestRequestFactory; const int kChildId = 30; @@ -1740,8 +1770,6 @@ base::TimeDelta max_queuing_time = base::TimeDelta::FromSeconds(15); InitializeMaxQueuingDelayExperiment(max_queuing_time); - network_quality_estimator_.SetAndNotifyObserversOfEffectiveConnectionType( - net::EFFECTIVE_CONNECTION_TYPE_SLOW_2G); InitializeScheduler(); @@ -1766,21 +1794,82 @@ // When the delayable request finishes, metrics should be recorded. low.reset(); - // Verify that (i) Exactly one sample is recorded; and, (ii) The sample value - // is at least |delay|. This is guaranteed because the delay between the start - // of |low| and |high| is guaranteed to be more than |delay|. - const std::vector<base::Bucket> buckets = histogram_tester.GetAllSamples( + ExpectSampleIsAtLeastSpecifiedValue( + histogram_tester, "ResourceScheduler.DelayableRequests." - "WaitTimeToAvoidContentionWithNonDelayableRequest"); - EXPECT_EQ(1u, buckets.size()); - bool non_zero_sample_found = false; - for (const auto& bucket : buckets) { - if (bucket.min > 0 and bucket.count > 0) { - non_zero_sample_found = true; - EXPECT_LE(bucket.min, delay.InMilliseconds()); - } - } - EXPECT_TRUE(non_zero_sample_found); + "WaitTimeToAvoidContentionWithNonDelayableRequest", + delay.InMilliseconds()); +} + +// Starts and ends non-delayable requests to verify that the duration between +// non-delayable requests is recorded correctly. +TEST_F(ResourceSchedulerTest, NonDelayableToNonDelayableMetrics) { + base::HistogramTester histogram_tester_1; + + base::TimeDelta max_queuing_time = base::TimeDelta::FromSeconds(15); + InitializeMaxQueuingDelayExperiment(max_queuing_time); + + InitializeScheduler(); + + // Throw in one low priority request. When the request finishes histograms + // should be recorded. + std::unique_ptr<TestRequest> high_1( + NewRequest("http://host/high_1", net::HIGHEST)); + EXPECT_TRUE(high_1->started()); + + const base::TimeDelta high1_start_to_high2_start = + base::TimeDelta::FromSeconds(5); + tick_clock_.SetNowTicks(base::TimeTicks::Now() + high1_start_to_high2_start); + + // Start a high priority request before |high_1| finishes. + std::unique_ptr<TestRequest> high_2( + NewRequest("http://host/high_2", net::HIGHEST)); + EXPECT_TRUE(high_2->started()); + + ExpectSampleIsAtLeastSpecifiedValue( + histogram_tester_1, + "ResourceScheduler.NonDelayableLastStartToNonDelayableStart", + high1_start_to_high2_start.InMilliseconds()); + + ExpectSampleIsAtLeastSpecifiedValue( + histogram_tester_1, + "ResourceScheduler.NonDelayableLastStartOrEndToNonDelayableStart", + high1_start_to_high2_start.InMilliseconds()); + + // No non-delayable request has ended yet. + histogram_tester_1.ExpectTotalCount( + "ResourceScheduler.NonDelayableLastEndToNonDelayableStart", 0); + + const base::TimeDelta high2_start_to_high2_end = + base::TimeDelta::FromSeconds(7); + tick_clock_.Advance(high2_start_to_high2_end); + + high_1.reset(); + high_2.reset(); + + base::HistogramTester histogram_tester_2; + + const base::TimeDelta high2_end_to_high3_start = + base::TimeDelta::FromSeconds(2); + tick_clock_.Advance(high2_end_to_high3_start); + // Start a high priority request after |high_1| and |high_2| finishes. + std::unique_ptr<TestRequest> high_3( + NewRequest("http://host/high_3", net::HIGHEST)); + EXPECT_TRUE(high_3->started()); + ExpectSampleIsAtLeastSpecifiedValue( + histogram_tester_2, + "ResourceScheduler.NonDelayableLastStartToNonDelayableStart", + (high2_start_to_high2_end + high2_end_to_high3_start).InMilliseconds()); + + ExpectSampleIsAtLeastSpecifiedValue( + histogram_tester_2, + "ResourceScheduler.NonDelayableLastEndToNonDelayableStart", + high2_end_to_high3_start.InMilliseconds()); + + ExpectSampleIsAtLeastSpecifiedValue( + histogram_tester_2, + "ResourceScheduler.NonDelayableLastStartOrEndToNonDelayableStart", + high2_end_to_high3_start.InMilliseconds()); } } // unnamed namespace
diff --git a/services/service_manager/public/cpp/service_executable/service_executable_environment.cc b/services/service_manager/public/cpp/service_executable/service_executable_environment.cc index 57d22fa0..0b7c58f 100644 --- a/services/service_manager/public/cpp/service_executable/service_executable_environment.cc +++ b/services/service_manager/public/cpp/service_executable/service_executable_environment.cc
@@ -5,7 +5,6 @@ #include "services/service_manager/public/cpp/service_executable/service_executable_environment.h" #include "base/command_line.h" -#include "base/debug/stack_trace.h" #include "base/logging.h" #include "base/message_loop/message_loop.h" #include "base/message_loop/message_loop_current.h"
diff --git a/services/service_manager/sandbox/linux/sandbox_linux.cc b/services/service_manager/sandbox/linux/sandbox_linux.cc index 253787b..6dab7b7 100644 --- a/services/service_manager/sandbox/linux/sandbox_linux.cc +++ b/services/service_manager/sandbox/linux/sandbox_linux.cc
@@ -21,7 +21,6 @@ #include "base/bind.h" #include "base/callback_helpers.h" #include "base/command_line.h" -#include "base/debug/stack_trace.h" #include "base/feature_list.h" #include "base/files/scoped_file.h" #include "base/logging.h"
diff --git a/services/video_capture/broadcasting_receiver.cc b/services/video_capture/broadcasting_receiver.cc index 64860cab..1f8efce 100644 --- a/services/video_capture/broadcasting_receiver.cc +++ b/services/video_capture/broadcasting_receiver.cc
@@ -49,7 +49,7 @@ if (on_started_using_gpu_decode_has_been_called_) return; on_started_using_gpu_decode_has_been_called_ = true; - client_->OnStarted(); + client_->OnStartedUsingGpuDecode(); } BroadcastingReceiver::BufferContext::BufferContext( @@ -156,8 +156,10 @@ if (status_ == Status::kOnStartedHasBeenCalled) { added_client_context.OnStarted(); } - if (status_ == Status::kOnStartedUsingGpuDecodeHasBeenCalled) + if (status_ == Status::kOnStartedUsingGpuDecodeHasBeenCalled) { + added_client_context.OnStarted(); added_client_context.OnStartedUsingGpuDecode(); + } for (auto& buffer_context : buffer_contexts_) { added_client_context.client()->OnNewBuffer(
diff --git a/services/video_capture/device_factory_media_to_mojo_adapter.h b/services/video_capture/device_factory_media_to_mojo_adapter.h index 0122958..ebdb1d41 100644 --- a/services/video_capture/device_factory_media_to_mojo_adapter.h +++ b/services/video_capture/device_factory_media_to_mojo_adapter.h
@@ -12,6 +12,7 @@ #include "mojo/public/cpp/bindings/binding.h" #include "services/service_manager/public/cpp/service_context_ref.h" #include "services/video_capture/device_factory.h" +#include "services/video_capture/public/mojom/devices_changed_observer.mojom.h" #if defined(OS_CHROMEOS) #include "media/capture/video/chromeos/mojo/cros_image_capture.mojom.h"
diff --git a/services/video_capture/device_factory_provider_impl.cc b/services/video_capture/device_factory_provider_impl.cc index c73f826..cbb9cfb 100644 --- a/services/video_capture/device_factory_provider_impl.cc +++ b/services/video_capture/device_factory_provider_impl.cc
@@ -110,8 +110,6 @@ mojom::DeviceFactoryRequest request) { DCHECK(service_ref_); LazyInitializeDeviceFactory(); - if (factory_bindings_.empty()) - device_factory_->SetServiceRef(service_ref_->Clone()); factory_bindings_.AddBinding(device_factory_.get(), std::move(request)); } @@ -156,6 +154,7 @@ &GpuDependenciesContext::CreateJpegDecodeAccelerator, gpu_dependencies_context_->GetWeakPtr()), gpu_dependencies_context_->GetTaskRunner())); + device_factory_->SetServiceRef(service_ref_->Clone()); } void DeviceFactoryProviderImpl::LazyInitializeVideoSourceProvider() {
diff --git a/services/video_capture/public/cpp/mock_device_factory.h b/services/video_capture/public/cpp/mock_device_factory.h index bfb3827..dcbbe01f 100644 --- a/services/video_capture/public/cpp/mock_device_factory.h +++ b/services/video_capture/public/cpp/mock_device_factory.h
@@ -6,6 +6,7 @@ #define SERVICES_VIDEO_CAPTURE_PUBLIC_CPP_MOCK_DEVICE_FACTORY_H_ #include "services/video_capture/public/mojom/device_factory.mojom.h" +#include "services/video_capture/public/mojom/devices_changed_observer.mojom.h" #include "services/video_capture/public/mojom/producer.mojom.h" #include "testing/gmock/include/gmock/gmock.h"
diff --git a/services/video_capture/public/cpp/mock_video_source_provider.h b/services/video_capture/public/cpp/mock_video_source_provider.h index 9b0282d..9e7977d 100644 --- a/services/video_capture/public/cpp/mock_video_source_provider.h +++ b/services/video_capture/public/cpp/mock_video_source_provider.h
@@ -5,6 +5,7 @@ #ifndef SERVICES_VIDEO_CAPTURE_PUBLIC_CPP_MOCK_VIDEO_SOURCE_PROVIDER_H_ #define SERVICES_VIDEO_CAPTURE_PUBLIC_CPP_MOCK_VIDEO_SOURCE_PROVIDER_H_ +#include "services/video_capture/public/mojom/devices_changed_observer.mojom.h" #include "services/video_capture/public/mojom/producer.mojom.h" #include "services/video_capture/public/mojom/video_source_provider.mojom.h" #include "testing/gmock/include/gmock/gmock.h" @@ -33,6 +34,11 @@ void AddTextureVirtualDevice(const media::VideoCaptureDeviceInfo& device_info, video_capture::mojom::TextureVirtualDeviceRequest virtual_device) override; + void RegisterVirtualDevicesChangedObserver( + video_capture::mojom::DevicesChangedObserverPtr observer, + bool raise_event_if_virtual_devices_already_present) override { + NOTIMPLEMENTED(); + } MOCK_METHOD1(DoGetSourceInfos, void(GetSourceInfosCallback& callback)); MOCK_METHOD2(DoGetVideoSource,
diff --git a/services/video_capture/public/mojom/BUILD.gn b/services/video_capture/public/mojom/BUILD.gn index 9691e3a4..a3dde4e 100644 --- a/services/video_capture/public/mojom/BUILD.gn +++ b/services/video_capture/public/mojom/BUILD.gn
@@ -9,6 +9,7 @@ "device.mojom", "device_factory.mojom", "device_factory_provider.mojom", + "devices_changed_observer.mojom", "producer.mojom", "receiver.mojom", "scoped_access_permission.mojom",
diff --git a/services/video_capture/public/mojom/device_factory.mojom b/services/video_capture/public/mojom/device_factory.mojom index 2e2dee6..e92b240 100644 --- a/services/video_capture/public/mojom/device_factory.mojom +++ b/services/video_capture/public/mojom/device_factory.mojom
@@ -6,6 +6,7 @@ import "media/capture/mojom/video_capture_types.mojom"; import "services/video_capture/public/mojom/device.mojom"; +import "services/video_capture/public/mojom/devices_changed_observer.mojom"; import "services/video_capture/public/mojom/producer.mojom"; import "services/video_capture/public/mojom/virtual_device.mojom"; @@ -15,10 +16,6 @@ ERROR_DEVICE_NOT_FOUND }; -interface DevicesChangedObserver { - OnDevicesChanged(); -}; - // Enables access to a set of video capture devices. // Typical operation is to first call GetDeviceInfos() to obtain // information about available devices. The |device_id| of the infos can
diff --git a/services/video_capture/public/mojom/devices_changed_observer.mojom b/services/video_capture/public/mojom/devices_changed_observer.mojom new file mode 100644 index 0000000..535aa09 --- /dev/null +++ b/services/video_capture/public/mojom/devices_changed_observer.mojom
@@ -0,0 +1,11 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +module video_capture.mojom; + +// Callback interface for clients who wnat to get notified when virtual devices +// are added or removed. +interface DevicesChangedObserver { + OnDevicesChanged(); +};
diff --git a/services/video_capture/public/mojom/video_source_provider.mojom b/services/video_capture/public/mojom/video_source_provider.mojom index 682182db..dbb1b65 100644 --- a/services/video_capture/public/mojom/video_source_provider.mojom +++ b/services/video_capture/public/mojom/video_source_provider.mojom
@@ -5,6 +5,7 @@ module video_capture.mojom; import "media/capture/mojom/video_capture_types.mojom"; +import "services/video_capture/public/mojom/devices_changed_observer.mojom"; import "services/video_capture/public/mojom/producer.mojom"; import "services/video_capture/public/mojom/video_source.mojom"; import "services/video_capture/public/mojom/virtual_device.mojom"; @@ -41,4 +42,12 @@ AddTextureVirtualDevice( media.mojom.VideoCaptureDeviceInfo device_info, TextureVirtualDevice& virtual_device); + + // Registered observers will get notified whenever a virtual device is added + // or removed. Note: Changes to non-virtual devices are currently being + // monitored outside the video capture service, and therefore the service + // does not offer such monitoring. + RegisterVirtualDevicesChangedObserver( + DevicesChangedObserver observer, + bool raise_event_if_virtual_devices_already_present); };
diff --git a/services/video_capture/test/mock_devices_changed_observer.h b/services/video_capture/test/mock_devices_changed_observer.h index 850dfc0..460fd84 100644 --- a/services/video_capture/test/mock_devices_changed_observer.h +++ b/services/video_capture/test/mock_devices_changed_observer.h
@@ -6,6 +6,7 @@ #define SERVICES_VIDEO_CAPTURE_TEST_MOCK_DEVICES_CHANGED_OBSERVER_H_ #include "services/video_capture/public/mojom/device_factory.mojom.h" +#include "services/video_capture/public/mojom/devices_changed_observer.mojom.h" #include "testing/gmock/include/gmock/gmock.h" namespace video_capture {
diff --git a/services/video_capture/video_source_provider_impl.cc b/services/video_capture/video_source_provider_impl.cc index 3c395a3c..a50404a 100644 --- a/services/video_capture/video_source_provider_impl.cc +++ b/services/video_capture/video_source_provider_impl.cc
@@ -64,6 +64,13 @@ std::move(virtual_device)); } +void VideoSourceProviderImpl::RegisterVirtualDevicesChangedObserver( + mojom::DevicesChangedObserverPtr observer, + bool raise_event_if_virtual_devices_already_present) { + device_factory_->RegisterVirtualDevicesChangedObserver( + std::move(observer), raise_event_if_virtual_devices_already_present); +} + void VideoSourceProviderImpl::OnVideoSourceLastClientDisconnected( const std::string& device_id) { sources_.erase(device_id);
diff --git a/services/video_capture/video_source_provider_impl.h b/services/video_capture/video_source_provider_impl.h index ad59231..5ee8588a 100644 --- a/services/video_capture/video_source_provider_impl.h +++ b/services/video_capture/video_source_provider_impl.h
@@ -34,6 +34,9 @@ void AddTextureVirtualDevice( const media::VideoCaptureDeviceInfo& device_info, mojom::TextureVirtualDeviceRequest virtual_device) override; + void RegisterVirtualDevicesChangedObserver( + mojom::DevicesChangedObserverPtr observer, + bool raise_event_if_virtual_devices_already_present) override; private: void OnVideoSourceLastClientDisconnected(const std::string& device_id);
diff --git a/services/video_capture/virtual_device_enabled_device_factory.h b/services/video_capture/virtual_device_enabled_device_factory.h index ac6a644..0d74f64 100644 --- a/services/video_capture/virtual_device_enabled_device_factory.h +++ b/services/video_capture/virtual_device_enabled_device_factory.h
@@ -12,6 +12,7 @@ #include "services/service_manager/public/cpp/service_context_ref.h" #include "services/video_capture/device_factory.h" #include "services/video_capture/public/mojom/device.mojom.h" +#include "services/video_capture/public/mojom/devices_changed_observer.mojom.h" #include "services/video_capture/public/mojom/virtual_device.mojom.h" #if defined(OS_CHROMEOS)
diff --git a/services/ws/client_root.cc b/services/ws/client_root.cc index 84b81d7..0401fbf 100644 --- a/services/ws/client_root.cc +++ b/services/ws/client_root.cc
@@ -239,6 +239,12 @@ } } +void ClientRoot::NotifyClientOfDisplayIdChange() { + window_tree_->window_tree_client_->OnWindowDisplayChanged( + window_tree_->TransportIdForWindow(window_), + window_->GetHost()->GetDisplayId()); +} + void ClientRoot::UpdateLocalSurfaceIdAndClientSurfaceEmbedder() { GenerateLocalSurfaceIdIfNecessary(); ProxyWindow* proxy_window = ProxyWindow::GetMayBeNull(window_); @@ -346,9 +352,7 @@ DCHECK_EQ(window, window_); DCHECK(window->GetHost()); window->GetHost()->AddObserver(this); - window_tree_->window_tree_client_->OnWindowDisplayChanged( - window_tree_->TransportIdForWindow(window), - window->GetHost()->GetDisplayId()); + NotifyClientOfDisplayIdChange(); // When the addition to a new root window isn't the result of moving across // displays (e.g. destruction of the current display), the window bounds in
diff --git a/services/ws/client_root.h b/services/ws/client_root.h index 21028822..d7d834b 100644 --- a/services/ws/client_root.h +++ b/services/ws/client_root.h
@@ -87,6 +87,9 @@ return parent_local_surface_id_allocator_.has_value(); } + // Called when the display id changes. + void NotifyClientOfDisplayIdChange(); + private: friend class ClientRootTestHelper;
diff --git a/services/ws/public/cpp/gpu/gpu.cc b/services/ws/public/cpp/gpu/gpu.cc index 36a96d4c..21a24959 100644 --- a/services/ws/public/cpp/gpu/gpu.cc +++ b/services/ws/public/cpp/gpu/gpu.cc
@@ -9,7 +9,6 @@ #include <utility> #include "base/bind.h" -#include "base/debug/stack_trace.h" #include "base/memory/ptr_util.h" #include "base/synchronization/waitable_event.h" #include "base/threading/thread_task_runner_handle.h"
diff --git a/services/ws/test_change_tracker.cc b/services/ws/test_change_tracker.cc index bc278399..7d2a9564 100644 --- a/services/ws/test_change_tracker.cc +++ b/services/ws/test_change_tracker.cc
@@ -553,12 +553,14 @@ void TestChangeTracker::OnTopLevelCreated( uint32_t change_id, mojom::WindowDataPtr window_data, + int64_t display_id, bool drawn, const viz::LocalSurfaceIdAllocation& local_surface_id_allocation) { Change change; change.type = CHANGE_TYPE_ON_TOP_LEVEL_CREATED; change.change_id = change_id; change.window_id = window_data->window_id; + change.display_id = display_id; change.bool_value = drawn; change.local_surface_id_allocation = local_surface_id_allocation; AddChange(change);
diff --git a/services/ws/test_change_tracker.h b/services/ws/test_change_tracker.h index 83e3545..80736184d 100644 --- a/services/ws/test_change_tracker.h +++ b/services/ws/test_change_tracker.h
@@ -223,6 +223,7 @@ void OnTopLevelCreated( uint32_t change_id, mojom::WindowDataPtr window_data, + int64_t display_id, bool drawn, const viz::LocalSurfaceIdAllocation& local_surface_id_allocation); void OnDragDropStart(
diff --git a/services/ws/test_window_tree_client.cc b/services/ws/test_window_tree_client.cc index 7b8f638..28befd27 100644 --- a/services/ws/test_window_tree_client.cc +++ b/services/ws/test_window_tree_client.cc
@@ -117,7 +117,7 @@ int64_t display_id, bool drawn, const viz::LocalSurfaceIdAllocation& local_surface_id_allocation) { - tracker_.OnTopLevelCreated(change_id, std::move(data), drawn, + tracker_.OnTopLevelCreated(change_id, std::move(data), display_id, drawn, local_surface_id_allocation); }
diff --git a/services/ws/window_service.cc b/services/ws/window_service.cc index 97b7c7a..66b71c8 100644 --- a/services/ws/window_service.cc +++ b/services/ws/window_service.cc
@@ -258,6 +258,15 @@ screen_provider_->DisplayMetricsChanged(display, changed_metrics); } +void WindowService::OnWindowTreeHostsSwappedDisplays( + aura::Window* new_primary_root, + aura::Window* old_primary_root) { + DCHECK(new_primary_root->IsRootWindow() && old_primary_root->IsRootWindow()); + for (WindowTree* tree : window_trees_) { + tree->OnWindowTreeHostsSwappedDisplays(new_primary_root, old_primary_root); + } +} + std::string WindowService::GetIdForDebugging(aura::Window* window) { ProxyWindow* proxy_window = ProxyWindow::GetMayBeNull(window); if (!proxy_window)
diff --git a/services/ws/window_service.h b/services/ws/window_service.h index e51e55a..fe36a9fb 100644 --- a/services/ws/window_service.h +++ b/services/ws/window_service.h
@@ -170,6 +170,13 @@ void OnDisplayMetricsChanged(const display::Display& display, uint32_t changed_metrics); + // Called when the primary display is changed to an existing display. This + // results in swapping the display ids the two WindowTreeHosts are + // associated with. Clients that have windows contained by the root windows + // needs to be updated with the new display ids. + void OnWindowTreeHostsSwappedDisplays(aura::Window* new_primary_root, + aura::Window* old_primary_root); + // Returns an id useful for debugging. See ProxyWindow::GetIdForDebugging() // for details. std::string GetIdForDebugging(aura::Window* window);
diff --git a/services/ws/window_tree.cc b/services/ws/window_tree.cc index d88fe98..ceeafe51 100644 --- a/services/ws/window_tree.cc +++ b/services/ws/window_tree.cc
@@ -759,6 +759,19 @@ window_tree_client_->OnOcclusionStatesChanged(occlusion_changes); } +void WindowTree::OnWindowTreeHostsSwappedDisplays( + aura::Window* new_primary_root, + aura::Window* old_primary_root) { + DCHECK(new_primary_root->IsRootWindow() && old_primary_root->IsRootWindow()); + for (auto& client_root : client_roots_) { + aura::Window* root_window = client_root->window()->GetRootWindow(); + if (root_window != new_primary_root && root_window != old_primary_root) + continue; + + client_root->NotifyClientOfDisplayIdChange(); + } +} + bool WindowTree::NewWindowImpl( const ClientWindowId& client_window_id, const std::map<std::string, std::vector<uint8_t>>& properties) {
diff --git a/services/ws/window_tree.h b/services/ws/window_tree.h index 62fd9db02..64fd27f 100644 --- a/services/ws/window_tree.h +++ b/services/ws/window_tree.h
@@ -125,6 +125,12 @@ // Notifies the client that the occlusion state of |windows| have changed. void SendOcclusionStates(const std::set<aura::Window*>& windows); + // Called from WindowService to update display id of ClientRoots contained + // by the root windows. See WindowService::OnWindowTreeHostsSwappedDisplays + // for details. + void OnWindowTreeHostsSwappedDisplays(aura::Window* new_primary_root, + aura::Window* old_primary_root); + WindowService* window_service() { return window_service_; } // Returns the ClientWindowId for the window the client previously supplied
diff --git a/services/ws/window_tree_client_unittest.cc b/services/ws/window_tree_client_unittest.cc index 95c31968..05159cf 100644 --- a/services/ws/window_tree_client_unittest.cc +++ b/services/ws/window_tree_client_unittest.cc
@@ -319,7 +319,7 @@ bool drawn, const viz::LocalSurfaceIdAllocation& local_surface_id_allocation) override { - tracker()->OnTopLevelCreated(change_id, std::move(data), drawn, + tracker()->OnTopLevelCreated(change_id, std::move(data), display_id, drawn, local_surface_id_allocation); } void OnWindowBoundsChanged(
diff --git a/testing/buildbot/chromium.clang.json b/testing/buildbot/chromium.clang.json index 9d7bfbc..e8c33d71 100644 --- a/testing/buildbot/chromium.clang.json +++ b/testing/buildbot/chromium.clang.json
@@ -13699,7 +13699,6 @@ } }, { - "experiment_percentage": 100, "isolate_name": "flatbuffers_unittests", "name": "flatbuffers_unittests", "swarming": {
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json index 23c6b45..1cbd9b8 100644 --- a/testing/buildbot/chromium.fyi.json +++ b/testing/buildbot/chromium.fyi.json
@@ -922,7 +922,6 @@ } }, { - "experiment_percentage": 100, "isolate_name": "flatbuffers_unittests", "name": "flatbuffers_unittests", "swarming": { @@ -2026,7 +2025,6 @@ "name": "network_service_in_process_browser_tests", "swarming": { "can_use_on_swarming_builders": true, - "priority_adjustment": 30, "shards": 15 }, "test": "browser_tests" @@ -2038,7 +2036,6 @@ "name": "network_service_web_request_proxy_browser_tests", "swarming": { "can_use_on_swarming_builders": true, - "priority_adjustment": 30, "shards": 15 }, "test": "browser_tests" @@ -2050,7 +2047,6 @@ "name": "network_service_in_process_content_browsertests", "swarming": { "can_use_on_swarming_builders": true, - "priority_adjustment": 30, "shards": 2 }, "test": "content_browsertests" @@ -2288,7 +2284,6 @@ } ], "hard_timeout": 900, - "priority_adjustment": 30, "shards": 12 } } @@ -6443,7 +6438,6 @@ } }, { - "experiment_percentage": 100, "isolate_name": "flatbuffers_unittests", "name": "flatbuffers_unittests", "swarming": { @@ -10523,7 +10517,6 @@ } }, { - "experiment_percentage": 100, "isolate_name": "flatbuffers_unittests", "name": "flatbuffers_unittests", "swarming": { @@ -11874,7 +11867,6 @@ } }, { - "experiment_percentage": 100, "isolate_name": "flatbuffers_unittests", "name": "flatbuffers_unittests", "swarming": {
diff --git a/testing/buildbot/chromium.linux.json b/testing/buildbot/chromium.linux.json index c3cfb030..d27d543 100644 --- a/testing/buildbot/chromium.linux.json +++ b/testing/buildbot/chromium.linux.json
@@ -1651,7 +1651,6 @@ } }, { - "experiment_percentage": 100, "isolate_name": "flatbuffers_unittests", "name": "flatbuffers_unittests", "swarming": { @@ -2375,7 +2374,6 @@ } }, { - "experiment_percentage": 100, "isolate_name": "flatbuffers_unittests", "name": "flatbuffers_unittests", "swarming": { @@ -3057,7 +3055,6 @@ } }, { - "experiment_percentage": 100, "isolate_name": "flatbuffers_unittests", "name": "flatbuffers_unittests", "swarming": { @@ -4227,7 +4224,6 @@ } }, { - "experiment_percentage": 100, "isolate_name": "flatbuffers_unittests", "name": "flatbuffers_unittests", "swarming": {
diff --git a/testing/buildbot/chromium.mac.json b/testing/buildbot/chromium.mac.json index 79580708..bd91093 100644 --- a/testing/buildbot/chromium.mac.json +++ b/testing/buildbot/chromium.mac.json
@@ -1044,7 +1044,6 @@ } }, { - "experiment_percentage": 100, "isolate_name": "flatbuffers_unittests", "name": "flatbuffers_unittests", "swarming": { @@ -2184,7 +2183,6 @@ } }, { - "experiment_percentage": 100, "isolate_name": "flatbuffers_unittests", "name": "flatbuffers_unittests", "swarming": { @@ -3324,7 +3322,6 @@ } }, { - "experiment_percentage": 100, "isolate_name": "flatbuffers_unittests", "name": "flatbuffers_unittests", "swarming": { @@ -4483,7 +4480,6 @@ } }, { - "experiment_percentage": 100, "isolate_name": "flatbuffers_unittests", "name": "flatbuffers_unittests", "swarming": { @@ -5584,7 +5580,6 @@ } }, { - "experiment_percentage": 100, "isolate_name": "flatbuffers_unittests", "name": "flatbuffers_unittests", "swarming": {
diff --git a/testing/buildbot/chromium.win.json b/testing/buildbot/chromium.win.json index 3ab95f4..375341a 100644 --- a/testing/buildbot/chromium.win.json +++ b/testing/buildbot/chromium.win.json
@@ -694,7 +694,6 @@ } }, { - "experiment_percentage": 100, "isolate_name": "flatbuffers_unittests", "name": "flatbuffers_unittests", "swarming": { @@ -3184,7 +3183,6 @@ } }, { - "experiment_percentage": 100, "isolate_name": "flatbuffers_unittests", "name": "flatbuffers_unittests", "swarming": { @@ -4027,7 +4025,6 @@ } }, { - "experiment_percentage": 100, "isolate_name": "flatbuffers_unittests", "name": "flatbuffers_unittests", "swarming": { @@ -4760,7 +4757,6 @@ } }, { - "experiment_percentage": 100, "isolate_name": "flatbuffers_unittests", "name": "flatbuffers_unittests", "swarming": {
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl index f1444abb..4f0d7f18 100644 --- a/testing/buildbot/test_suites.pyl +++ b/testing/buildbot/test_suites.pyl
@@ -2693,9 +2693,7 @@ 'desktop_chromium_isolated_scripts': { 'content_shell_crash_test': {}, - 'flatbuffers_unittests': { - 'experiment_percentage': 100, - }, + 'flatbuffers_unittests': {}, 'metrics_python_tests': {}, 'telemetry_gpu_unittests': { 'swarming': {
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl index 12f0ba7..aa503e10 100644 --- a/testing/buildbot/waterfalls.pyl +++ b/testing/buildbot/waterfalls.pyl
@@ -1193,13 +1193,6 @@ }, }, 'Mojo Linux': { - # Normally, FYI tests run with a lower priority than main CI tests. - # However, some optional CQ bots mirror FYI bots, so their tests need - # to run at the same priority as other non-optional CQ bots to avoid - # getting starved out. - 'swarming': { - 'priority_adjustment': 30, - }, 'test_suites': { 'gtest_tests': 'mojo_linux_gtests', }, @@ -1234,10 +1227,6 @@ }, }, 'WebKit Linux composite_after_paint Dummy Builder': { - # Normally, FYI tests run with a lower priority than main CI tests. - # However, some optional CQ bots mirror FYI bots, so their tests need - # to run at the same priority as other non-optional CQ bots to avoid - # getting starved out. 'swarming': { 'dimension_sets': [ { @@ -1245,7 +1234,6 @@ }, ], 'hard_timeout': 900, - 'priority_adjustment': 30, }, 'test_suites': { 'isolated_scripts': 'chromium_webkit_isolated_scripts',
diff --git a/third_party/android_crazy_linker/BUILD.gn b/third_party/android_crazy_linker/BUILD.gn index 135c1e7..8111614 100644 --- a/third_party/android_crazy_linker/BUILD.gn +++ b/third_party/android_crazy_linker/BUILD.gn
@@ -30,6 +30,7 @@ ":crazy_linker_test_dl_wrappers_recursive", ":crazy_linker_test_dl_wrappers_valid_handles", ":crazy_linker_test_dl_wrappers_with_system_handle", + ":crazy_linker_test_jni_hooks", ":crazy_linker_test_load_library", ":crazy_linker_test_load_library_depends", ":crazy_linker_test_load_library_with_gnu_hash_table", @@ -330,6 +331,12 @@ libs = [ "dl" ] } + crazy_linker_test_library("crazy_linker_tests_libjni_lib") { + sources = [ + "src/tests/jni_lib.cpp", + ] + } + # Integration tests are provided as standalone executables for now. executable("crazy_linker_bench_load_library") { @@ -344,6 +351,18 @@ ] } + executable("crazy_linker_test_jni_hooks") { + sources = [ + "src/tests/test_jni_hooks.cpp", + ] + data_deps = [ + ":crazy_linker_tests_libjni_lib", + ] + deps = [ + ":android_crazy_linker", + ] + } + executable("crazy_linker_test_load_library") { sources = [ "src/tests/test_load_library.cpp",
diff --git a/third_party/android_crazy_linker/src/include/crazy_linker.h b/third_party/android_crazy_linker/src/include/crazy_linker.h index 3afaed68..0ae27476 100644 --- a/third_party/android_crazy_linker/src/include/crazy_linker.h +++ b/third_party/android_crazy_linker/src/include/crazy_linker.h
@@ -66,7 +66,6 @@ typedef struct crazy_context_t crazy_context_t; // Create a new context object. -// Note that this calls crazy_context_reset_search_paths(). crazy_context_t* crazy_context_create(void) _CRAZY_PUBLIC; // Return current error string, or NULL if there was no error. @@ -83,31 +82,8 @@ // Return the current load address in a context. size_t crazy_context_get_load_address(crazy_context_t* context) _CRAZY_PUBLIC; -// Add one or more paths to the list of library search paths held -// by a given context. |path| is a string using a column (:) as a -// list separator. As with the PATH variable, an empty list item -// is equivalent to '.', the current directory. -// This can fail if too many paths are added to the context. -// -// NOTE: Calling this function appends new paths to the search list, -// but all paths added with this function will be searched before -// the ones listed in LD_LIBRARY_PATH. -crazy_status_t crazy_context_add_search_path( - crazy_context_t* context, - const char* file_path) _CRAZY_PUBLIC; - -// Find the ELF binary that contains |address|, and add its directory -// path to the context's list of search directories. This is useful to -// load libraries in the same directory than the current program itself. -crazy_status_t crazy_context_add_search_path_for_address( - crazy_context_t* context, - void* address) _CRAZY_PUBLIC; - -// Reset the search paths to the value of the LD_LIBRARY_PATH -// environment variable. This essentially removes any paths -// that were added with crazy_context_add_search_path() or -// crazy_context_add_search_path_for_address(). -void crazy_context_reset_search_paths(crazy_context_t* context) _CRAZY_PUBLIC; +// Destroy a given context object. +void crazy_context_destroy(crazy_context_t* context) _CRAZY_PUBLIC; // Record the value of |java_vm| inside of |context|. If this is not NULL, // which is the default, then after loading any library, the crazy linker @@ -118,18 +94,32 @@ // // The |java_vm| field is also saved in the crazy_library_t object, and // used at unload time to call JNI_OnUnload() if it exists. -void crazy_context_set_java_vm(crazy_context_t* context, - void* java_vm, - int minimum_jni_version); +void crazy_set_java_vm(void* java_vm, int minimum_jni_version); // Retrieves the last values set with crazy_context_set_java_vm(). // A value of NUMM in |*java_vm| means the feature is disabled. -void crazy_context_get_java_vm(crazy_context_t* context, - void** java_vm, - int* minimum_jni_version); +void crazy_get_java_vm(void** java_vm, int* minimum_jni_version); -// Destroy a given context object. -void crazy_context_destroy(crazy_context_t* context) _CRAZY_PUBLIC; +// Add one or more paths to the global list of library search paths. |path| is a +// string using a column (:) as a list separator. As with the PATH variable, +// an empty list item is equivalent to '.', the current directory. +// This can fail if too many paths are added to the context. +// +// NOTE: Calling this function appends new paths to the global search list, +// but all paths added with this function will be searched before +// the ones listed in LD_LIBRARY_PATH. +crazy_status_t crazy_add_search_path(const char* file_path) _CRAZY_PUBLIC; + +// Find the ELF binary that contains |address|, and add its directory +// path to the global list of search directories. This is useful to +// load libraries in the same directory as the current program itself. +crazy_status_t crazy_add_search_path_for_address(void* address) _CRAZY_PUBLIC; + +// Reset the search paths to the value of the LD_LIBRARY_PATH +// environment variable. This essentially removes any paths +// that were added with crazy_add_search_path() or +// crazy_context_add_search_path_for_address(). +void crazy_reset_search_paths(void) _CRAZY_PUBLIC; // Pass the platform's SDK build version to the crazy linker. The value is // from android.os.Build.VERSION.SDK_INT.
diff --git a/third_party/android_crazy_linker/src/run_tests.sh b/third_party/android_crazy_linker/src/run_tests.sh index 2271e9c..fb8ae0c8 100755 --- a/third_party/android_crazy_linker/src/run_tests.sh +++ b/third_party/android_crazy_linker/src/run_tests.sh
@@ -151,6 +151,7 @@ libcrazy_linker_tests_libfoo_with_static_constructor.so \ libcrazy_linker_tests_libfoo_with_gnu_hash_table.so \ libcrazy_linker_tests_libfoo2.so \ +libcrazy_linker_tests_libjni_lib.so \ libcrazy_linker_tests_libzoo.so \ libcrazy_linker_tests_libzoo_dlopen_in_initializer.so \ libcrazy_linker_tests_libzoo_dlopen_in_initializer_inner.so \ @@ -164,6 +165,7 @@ crazy_linker_test_dl_wrappers_recursive \ crazy_linker_test_dl_wrappers_with_system_handle \ crazy_linker_test_dl_wrappers_valid_handles \ +crazy_linker_test_jni_hooks \ crazy_linker_test_load_library \ crazy_linker_test_load_library_depends \ crazy_linker_test_load_library_with_gnu_hash_table \
diff --git a/third_party/android_crazy_linker/src/src/crazy_linker_api.cpp b/third_party/android_crazy_linker/src/src/crazy_linker_api.cpp index 3c85fd3..6d4cdcc 100644 --- a/third_party/android_crazy_linker/src/src/crazy_linker_api.cpp +++ b/third_party/android_crazy_linker/src/src/crazy_linker_api.cpp
@@ -31,16 +31,8 @@ // struct crazy_context_t { - public: - crazy_context_t() { ResetSearchPaths(); } - - void ResetSearchPaths() { search_paths.ResetFromEnv("LD_LIBRARY_PATH"); } - size_t load_address = 0; Error error; - SearchPathList search_paths; - void* java_vm = nullptr; - int minimum_jni_version = 0; }; // @@ -78,15 +70,28 @@ return context->load_address; } -crazy_status_t crazy_context_add_search_path(crazy_context_t* context, - const char* file_path) { - context->search_paths.AddPaths(file_path); +void crazy_context_destroy(crazy_context_t* context) { + delete context; +} + +void crazy_set_java_vm(void* java_vm, int minimum_jni_version) { + ScopedLockedGlobals globals; + globals->InitJavaVm(java_vm, minimum_jni_version); +} + +void crazy_get_java_vm(void** java_vm, int* minimum_jni_version) { + ScopedLockedGlobals globals; + *java_vm = globals->java_vm(); + *minimum_jni_version = globals->minimum_jni_version(); +} + +crazy_status_t crazy_add_search_path(const char* file_path) { + ScopedLockedGlobals globals; + globals->search_path_list()->AddPaths(file_path); return CRAZY_STATUS_SUCCESS; } -crazy_status_t crazy_context_add_search_path_for_address( - crazy_context_t* context, - void* address) { +crazy_status_t crazy_add_search_path_for_address(void* address) { uintptr_t load_address; char path[512]; char* p; @@ -95,53 +100,29 @@ address, &load_address, path, sizeof(path)) && (p = strrchr(path, '/')) != NULL && p[1]) { *p = '\0'; - return crazy_context_add_search_path(context, path); + return crazy_add_search_path(path); } - context->error.Format("Could not find ELF binary at address @%p", address); return CRAZY_STATUS_FAILURE; } -void crazy_context_reset_search_paths(crazy_context_t* context) { - context->ResetSearchPaths(); +void crazy_reset_search_paths(void) { + ScopedLockedGlobals globals; + globals->search_path_list()->ResetFromEnv("LD_LIBRARY_PATH"); } -void crazy_context_set_java_vm(crazy_context_t* context, - void* java_vm, - int minimum_jni_version) { - context->java_vm = java_vm; - context->minimum_jni_version = minimum_jni_version; -} - -void crazy_context_get_java_vm(crazy_context_t* context, - void** java_vm, - int* minimum_jni_version) { - *java_vm = context->java_vm; - *minimum_jni_version = context->minimum_jni_version; -} - -void crazy_context_destroy(crazy_context_t* context) { delete context; } - crazy_status_t crazy_library_open(crazy_library_t** library, const char* lib_name, crazy_context_t* context) { ScopedLockedGlobals globals; - LibraryView* wrap = globals->libraries()->LoadLibrary( - lib_name, context->load_address, &context->search_paths, &context->error); + LibraryView* view = globals->libraries()->LoadLibrary( + lib_name, context->load_address, globals->search_path_list(), + &context->error); - if (!wrap) + if (!view) return CRAZY_STATUS_FAILURE; - if (context->java_vm != NULL && wrap->IsCrazy()) { - crazy::SharedLibrary* lib = wrap->GetCrazy(); - if (!lib->SetJavaVM( - context->java_vm, context->minimum_jni_version, &context->error)) { - globals->libraries()->UnloadLibrary(wrap); - return CRAZY_STATUS_FAILURE; - } - } - - *library = reinterpret_cast<crazy_library_t*>(wrap); + *library = reinterpret_cast<crazy_library_t*>(view); return CRAZY_STATUS_SUCCESS; }
diff --git a/third_party/android_crazy_linker/src/src/crazy_linker_globals.h b/third_party/android_crazy_linker/src/src/crazy_linker_globals.h index 1954e80..6ac07cd6 100644 --- a/third_party/android_crazy_linker/src/src/crazy_linker_globals.h +++ b/third_party/android_crazy_linker/src/src/crazy_linker_globals.h
@@ -47,8 +47,24 @@ // Initialized from LD_LIBRARY_PATH when ::Get() creates the instance. SearchPathList* search_path_list() { return &search_paths_; } + // Save JavaVM instance pointer and minimum JNI version required by this + // client. If |java_vm| is not nullptr, it will be used to call JNI_OnLoad() + // on every library loaded through the crazy linker, if available, and + // JNI_UnLoad() when unloading them, respectively. + void InitJavaVm(void* java_vm, int min_jni_version) { + java_vm_ = java_vm; + min_jni_version_ = min_jni_version; + } + + // Return current JavaVM instance pointer. + void* java_vm() const { return java_vm_; } + + // Return current minimum JNI version number. + int minimum_jni_version() const { return min_jni_version_; } + // Android API level for the current device (if known). // This is static because it must be set before the first call to Get(). + // See LibraryList() constructor comment for details. static int sdk_build_version; // Convenience function to get the global RDebug instance. @@ -56,6 +72,8 @@ private: pthread_mutex_t lock_; + void* java_vm_ = nullptr; + int min_jni_version_ = 0; LibraryList libraries_; SearchPathList search_paths_; RDebug rdebug_;
diff --git a/third_party/android_crazy_linker/src/src/crazy_linker_library_list.cpp b/third_party/android_crazy_linker/src/src/crazy_linker_library_list.cpp index 691d896..256194b 100644 --- a/third_party/android_crazy_linker/src/src/crazy_linker_library_list.cpp +++ b/third_party/android_crazy_linker/src/src/crazy_linker_library_list.cpp
@@ -266,7 +266,9 @@ head_ = lib->list_next_; // Call JNI_OnUnload, if necessary, then the destructors. + LOG("Running JNI_OnUnload() for %s", wrap->GetName()); lib->CallJniOnUnload(); + LOG("Running destructors for %s", wrap->GetName()); lib->CallDestructors(); // Unload the dependencies recursively. @@ -324,17 +326,17 @@ // First check whether a library with the same base name was // already loaded. - LibraryView* wrap = FindKnownLibrary(base_name); - if (wrap) { + LibraryView* view = FindKnownLibrary(base_name); + if (view) { if (load_address) { // Check that this is a crazy library and that is was loaded at // the correct address. - if (!wrap->IsCrazy()) { + if (!view->IsCrazy()) { error->Format("System library can't be loaded at fixed address %08x", load_address); return nullptr; } - uintptr_t actual_address = wrap->GetCrazy()->load_address(); + uintptr_t actual_address = view->GetCrazy()->load_address(); if (actual_address != load_address) { error->Format("Library already loaded at @%08x, can't load it at @%08x", actual_address, @@ -342,8 +344,8 @@ return nullptr; } } - wrap->AddRef(); - return wrap; + view->AddRef(); + return view; } // Find the full library path. @@ -410,18 +412,25 @@ head_ = lib.Get(); // Then create a new LibraryView for it. - wrap = new LibraryView(lib.Get()); - known_libraries_.PushBack(wrap); + view = new LibraryView(lib.Release()); + known_libraries_.PushBack(view); LOG("Running constructors for %s", base_name); - // Now run the constructors. - lib->CallConstructors(); + view->GetCrazy()->CallConstructors(); + + // Then try to call JNI_OnLoad() if necessary. + LOG("Running JNI_OnLoad() for %s", base_name); + Globals* globals = Globals::Get(); + if (!view->GetCrazy()->CallJniOnLoad(globals->java_vm(), + globals->minimum_jni_version(), error)) { + LOG("Error on JNI_OnLoad(): %s", error->c_str()); + UnloadLibrary(view); + return nullptr; + } LOG("Done loading %s", base_name); - lib.Release(); - - return wrap; + return view; } void LibraryList::AddLibrary(LibraryView* wrap) {
diff --git a/third_party/android_crazy_linker/src/src/crazy_linker_shared_library.cpp b/third_party/android_crazy_linker/src/src/crazy_linker_shared_library.cpp index eff2102..f7b737b 100644 --- a/third_party/android_crazy_linker/src/src/crazy_linker_shared_library.cpp +++ b/third_party/android_crazy_linker/src/src/crazy_linker_shared_library.cpp
@@ -469,14 +469,14 @@ CallFunction(fini_func_, "DT_FINI"); } -bool SharedLibrary::SetJavaVM(void* java_vm, - int minimum_jni_version, - Error* error) { - if (java_vm == NULL) +bool SharedLibrary::CallJniOnLoad(void* java_vm, + int minimum_jni_version, + Error* error) { + if (!java_vm) return true; // Lookup for JNI_OnLoad, exit if it doesn't exist. - JNI_OnLoadFunctionPtr jni_onload = reinterpret_cast<JNI_OnLoadFunctionPtr>( + auto jni_onload = reinterpret_cast<JNI_OnLoadFunctionPtr>( FindAddressForSymbol("JNI_OnLoad")); if (!jni_onload) return true;
diff --git a/third_party/android_crazy_linker/src/src/crazy_linker_shared_library.h b/third_party/android_crazy_linker/src/src/crazy_linker_shared_library.h index d50dc04..fbc7f8e 100644 --- a/third_party/android_crazy_linker/src/src/crazy_linker_shared_library.h +++ b/third_party/android_crazy_linker/src/src/crazy_linker_shared_library.h
@@ -137,11 +137,10 @@ // function result is less than |minimum_jni_version|, fail with // a message in |error|. On success, return true, and record // |java_vm| to call 'JNI_OnUnload' at unload time, if present. - bool SetJavaVM(void* java_vm, int minimum_jni_version, Error* error); + bool CallJniOnLoad(void* java_vm, int minimum_jni_version, Error* error); // Call 'JNI_OnUnload()' is necessary, i.e. if there was a succesful call - // to SetJavaVM() before. This will pass the same |java_vm| value to the - // callback, if it is present in the library. + // to CallJniOnLoad() before, or nothing otherwise. void CallJniOnUnload(); // Release reserved memory mapping. Caller takes ownership. Used to delay
diff --git a/third_party/android_crazy_linker/src/tests/bench_load_library.cpp b/third_party/android_crazy_linker/src/tests/bench_load_library.cpp index 116e2381..e32e4573 100644 --- a/third_party/android_crazy_linker/src/tests/bench_load_library.cpp +++ b/third_party/android_crazy_linker/src/tests/bench_load_library.cpp
@@ -83,8 +83,7 @@ crazy_context_t* context = crazy_context_create(); // Ensure the program looks in its own directory too. - crazy_context_add_search_path_for_address(context, - reinterpret_cast<void*>(&main)); + crazy_add_search_path_for_address(reinterpret_cast<void*>(&main)); // Load the library with the crazy linker. drop_caches();
diff --git a/third_party/android_crazy_linker/src/tests/jni_lib.cpp b/third_party/android_crazy_linker/src/tests/jni_lib.cpp index 8fd12d6..2262d28 100644 --- a/third_party/android_crazy_linker/src/tests/jni_lib.cpp +++ b/third_party/android_crazy_linker/src/tests/jni_lib.cpp
@@ -8,6 +8,7 @@ #include <jni.h> #include <stdio.h> #include <stdlib.h> +#include <string.h> #define VARNAME "TEST_VAR"
diff --git a/third_party/android_crazy_linker/src/tests/test_jni_hooks.cpp b/third_party/android_crazy_linker/src/tests/test_jni_hooks.cpp index ad101c8..2dd3314 100644 --- a/third_party/android_crazy_linker/src/tests/test_jni_hooks.cpp +++ b/third_party/android_crazy_linker/src/tests/test_jni_hooks.cpp
@@ -13,7 +13,7 @@ #define VARNAME "TEST_VAR" -static const char kJniLibName[] = "libjni_lib.so"; +static const char kJniLibName[] = "libcrazy_linker_tests_libjni_lib.so"; static void* kJavaVM = (void*)0xdeadcafe; int main() { @@ -21,9 +21,9 @@ crazy_library_t* library; // Expect to find the library in the same directory than this executable. - crazy_context_add_search_path_for_address(context, (void*)&main); + crazy_add_search_path_for_address((void*)&main); - crazy_context_set_java_vm(context, kJavaVM, JNI_VERSION_1_2); + crazy_set_java_vm(kJavaVM, JNI_VERSION_1_2); // Load libjni_lib.so, this should invoke its JNI_OnLoad() function // automatically. @@ -42,7 +42,7 @@ // Now, change the minimum JNI version to JNI_VERSION_1_6, which should // prevent loading the library properly, since it only supports 1.2. - crazy_context_set_java_vm(context, kJavaVM, JNI_VERSION_1_6); + crazy_set_java_vm(kJavaVM, JNI_VERSION_1_6); setenv(VARNAME, "INIT", 1); if (crazy_library_open(&library, kJniLibName, context)) @@ -50,7 +50,7 @@ // Disable the feature, this shall load the library, but not call the // JNI_OnLoad() hook. - crazy_context_set_java_vm(context, NULL, 0); + crazy_set_java_vm(nullptr, 0); setenv(VARNAME, "INIT", 1); if (!crazy_library_open(&library, kJniLibName, context))
diff --git a/third_party/android_crazy_linker/src/tests/test_search_path_list.cpp b/third_party/android_crazy_linker/src/tests/test_search_path_list.cpp index e0f3b3e5..c66b1a8 100644 --- a/third_party/android_crazy_linker/src/tests/test_search_path_list.cpp +++ b/third_party/android_crazy_linker/src/tests/test_search_path_list.cpp
@@ -107,25 +107,25 @@ // Reset search paths to a non-existing directory. Check that the library // can't be loaded. setenv("LD_LIBRARY_PATH", "/this-directory-does-not-exist", 1); - crazy_context_reset_search_paths(context); + crazy_reset_search_paths(); CheckLibraryCantLoad(LIB_NAME, context); // Add the search path to the current executable, this should load the // original // libfoo.so. - crazy_context_add_search_path_for_address(context, (void*)&main); + crazy_add_search_path_for_address((void*)&main); CheckLibrary(LIB_NAME, kFooSymbols, kFoo2Symbols, context); // Reset search paths to use $TMPDIR2 then $TMPDIR1 setenv("LD_LIBRARY_PATH", temp_dir_1.path(), 1); - crazy_context_reset_search_paths(context); - crazy_context_add_search_path(context, temp_dir_2.path()); + crazy_reset_search_paths(); + crazy_add_search_path(temp_dir_2.path()); // Check that the copy of libfoo2.so is loaded. CheckLibrary(LIB_NAME, kFoo2Symbols, kFooSymbols, context); // Reset search paths to use only $TMPDIR1 - crazy_context_reset_search_paths(context); + crazy_reset_search_paths(); // Check that the copy of libfoo.so is loaded. CheckLibrary(LIB_NAME, kFooSymbols, kFoo2Symbols, context);
diff --git a/third_party/android_crazy_linker/src/tests/test_two_shared_relros.cpp b/third_party/android_crazy_linker/src/tests/test_two_shared_relros.cpp index 5234b9eb..d92745e 100644 --- a/third_party/android_crazy_linker/src/tests/test_two_shared_relros.cpp +++ b/third_party/android_crazy_linker/src/tests/test_two_shared_relros.cpp
@@ -31,7 +31,7 @@ RelroLibrary foo; RelroLibrary bar; - crazy_context_add_search_path_for_address(context, (void*)&main); + crazy_add_search_path_for_address((void*)&main); // Load libfoo_with_relro.so crazy_context_set_load_address(context, 0x20000000);
diff --git a/third_party/blink/PRESUBMIT.py b/third_party/blink/PRESUBMIT.py index dc710aa..6acac54 100644 --- a/third_party/blink/PRESUBMIT.py +++ b/third_party/blink/PRESUBMIT.py
@@ -25,8 +25,9 @@ _EXCLUDED_PATHS = ( - # This directory is created and updated via a script. + # These directories are created and updated via a script. r'^third_party[\\\/]blink[\\\/]tools[\\\/]blinkpy[\\\/]third_party[\\\/]wpt[\\\/]wpt[\\\/].*', + r'^third_party[\\\/]blink[\\\/]web_tests[\\\/]external[\\\/]wpt[\\\/]tools[\\\/].*', )
diff --git a/third_party/blink/renderer/bindings/core/v8/v8_embedder_graph_builder.cc b/third_party/blink/renderer/bindings/core/v8/v8_embedder_graph_builder.cc index 5a3e20af..f48d9bb 100644 --- a/third_party/blink/renderer/bindings/core/v8/v8_embedder_graph_builder.cc +++ b/third_party/blink/renderer/bindings/core/v8/v8_embedder_graph_builder.cc
@@ -14,19 +14,225 @@ namespace blink { -V8EmbedderGraphBuilder::V8EmbedderGraphBuilder(v8::Isolate* isolate, - Graph* graph) - : ScriptWrappableVisitor(ThreadState::Current()), - isolate_(isolate), - current_parent_(nullptr), - graph_(graph) {} +namespace { -void V8EmbedderGraphBuilder::BuildEmbedderGraphCallback( - v8::Isolate* isolate, - v8::EmbedderGraph* graph, - void* data) { - V8EmbedderGraphBuilder builder(isolate, graph); - builder.BuildEmbedderGraph(); +using Traceable = const void*; +using Graph = v8::EmbedderGraph; + +// Information about whether a node is attached to the main DOM tree +// or not. It is computed as follows: +// 1) A Document with IsContextDestroyed() = true is detached. +// 2) A Document with IsContextDestroyed() = false is attached. +// 3) A Node that is not connected to any Document is detached. +// 4) A Node that is connected to a detached Document is detached. +// 5) A Node that is connected to an attached Document is attached. +// 6) A ScriptWrappable that is reachable from an attached Node is +// attached. +// 7) A ScriptWrappable that is reachable from a detached Node is +// detached. +// 8) A ScriptWrappable that is not reachable from any Node is +// considered (conservatively) as attached. +// The unknown state applies to ScriptWrappables during graph +// traversal when we don't have reachability information yet. +enum class DomTreeState { kAttached, kDetached, kUnknown }; + +DomTreeState DomTreeStateFromWrapper(v8::Isolate* isolate, + uint16_t class_id, + v8::Local<v8::Object> v8_value) { + if (class_id != WrapperTypeInfo::kNodeClassId) + return DomTreeState::kUnknown; + Node* node = V8Node::ToImpl(v8_value); + Node* root = V8GCController::OpaqueRootForGC(isolate, node); + if (root->isConnected() && + !node->GetDocument().MasterDocument().IsContextDestroyed()) { + return DomTreeState::kAttached; + } + return DomTreeState::kDetached; +} + +class EmbedderNode : public Graph::Node { + public: + EmbedderNode(const char* name, + Graph::Node* wrapper, + DomTreeState dom_tree_state) + : name_(name), wrapper_(wrapper), dom_tree_state_(dom_tree_state) {} + + DomTreeState GetDomTreeState() { return dom_tree_state_; } + void UpdateDomTreeState(DomTreeState parent_dom_tree_state) { + // If the child's state is unknown, then take the parent's state. + // If the parent is attached, then the child is also attached. + if (dom_tree_state_ == DomTreeState::kUnknown || + parent_dom_tree_state == DomTreeState::kAttached) { + dom_tree_state_ = parent_dom_tree_state; + } + } + // Graph::Node overrides. + const char* Name() override { return name_; } + const char* NamePrefix() override { + return dom_tree_state_ == DomTreeState::kDetached ? "Detached" : nullptr; + } + size_t SizeInBytes() override { return 0; } + Graph::Node* WrapperNode() override { return wrapper_; } + + private: + const char* name_; + Graph::Node* wrapper_; + DomTreeState dom_tree_state_; +}; + +class EmbedderRootNode : public EmbedderNode { + public: + explicit EmbedderRootNode(const char* name) + : EmbedderNode(name, nullptr, DomTreeState::kUnknown) {} + // Graph::Node override. + bool IsRootNode() override { return true; } +}; + +class NodeBuilder final { + public: + explicit NodeBuilder(Graph* graph) : graph_(graph) {} + + Graph::Node* GraphNode(const v8::Local<v8::Value>&); + EmbedderNode* GraphNode(Traceable, + const char* name, + Graph::Node* wrapper, + DomTreeState); + bool Contains(Traceable traceable) const { + return graph_nodes_.Contains(traceable); + } + + private: + Graph* const graph_; + HashMap<Traceable, EmbedderNode*> graph_nodes_; +}; + +v8::EmbedderGraph::Node* NodeBuilder::GraphNode( + const v8::Local<v8::Value>& value) { + return graph_->V8Node(value); +} + +EmbedderNode* NodeBuilder::GraphNode(Traceable traceable, + const char* name, + v8::EmbedderGraph::Node* wrapper, + DomTreeState dom_tree_state) { + auto iter = graph_nodes_.find(traceable); + if (iter != graph_nodes_.end()) { + iter->value->UpdateDomTreeState(dom_tree_state); + return iter->value; + } + // Ownership of the new node is transferred to the graph_. + // graph_node_.at(tracable) is valid for all BuildEmbedderGraph execution. + auto* raw_node = new EmbedderNode(name, wrapper, dom_tree_state); + EmbedderNode* node = static_cast<EmbedderNode*>( + graph_->AddNode(std::unique_ptr<Graph::Node>(raw_node))); + graph_nodes_.insert(traceable, node); + return node; +} + +} // namespace + +class V8EmbedderGraphBuilder + : public Visitor, + public v8::PersistentHandleVisitor, + public v8::EmbedderHeapTracer::TracedGlobalHandleVisitor { + public: + V8EmbedderGraphBuilder(v8::Isolate*, Graph*, NodeBuilder*); + + void BuildEmbedderGraph(); + + // v8::PersistentHandleVisitor override. + void VisitPersistentHandle(v8::Persistent<v8::Value>*, + uint16_t class_id) override; + + // v8::EmbedderHeapTracer::TracedGlobalHandleVisitor override. + void VisitTracedGlobalHandle( + const v8::TracedGlobal<v8::Value>& value) override; + + // Visitor overrides. + void Visit(const TraceWrapperV8Reference<v8::Value>&) final; + void VisitWithWrappers(void*, TraceDescriptor) final; + void VisitBackingStoreStrongly(void* object, + void** object_slot, + TraceDescriptor desc) final; + + // Unused Visitor overrides. + void Visit(void* object, TraceDescriptor desc) final { + // TODO(mlippautz): Implement for unified heap snapshots. + } + void VisitWeak(void* object, + void** object_slot, + TraceDescriptor desc, + WeakCallback callback) final {} + void VisitBackingStoreWeakly(void*, + void**, + TraceDescriptor, + WeakCallback, + void*) final {} + void VisitBackingStoreOnly(void*, void**) final {} + void RegisterBackingStoreCallback(void**, MovingObjectCallback, void*) final { + } + void RegisterWeakCallback(void*, WeakCallback) final {} + + private: + class ParentScope { + STACK_ALLOCATED(); + + public: + ParentScope(V8EmbedderGraphBuilder* visitor, EmbedderNode* parent) + : visitor_(visitor) { + DCHECK_EQ(visitor->current_parent_, nullptr); + visitor->current_parent_ = parent; + } + ~ParentScope() { visitor_->current_parent_ = nullptr; } + + private: + V8EmbedderGraphBuilder* const visitor_; + }; + + struct WorklistItem { + EmbedderNode* node; + Traceable traceable; + TraceCallback trace_callback; + }; + + void VisitPersistentHandleInternal(v8::Local<v8::Object>, uint16_t); + + WorklistItem ToWorklistItem(EmbedderNode*, const TraceDescriptor&) const; + + void VisitPendingActivities(); + void VisitTransitiveClosure(); + + // Push the item to the default worklist if item.traceable was not + // already visited. + void PushToWorklist(WorklistItem); + + v8::Isolate* const isolate_; + Graph* const graph_; + NodeBuilder* const node_builder_; + + EmbedderNode* current_parent_ = nullptr; + + HashSet<Traceable> visited_; + // The default worklist that is used to visit transitive closure. + Deque<WorklistItem> worklist_; + // The worklist that collects detached Nodes during persistent handle + // iteration. + Deque<WorklistItem> detached_worklist_; + // The worklist that collects ScriptWrappables with unknown information + // about attached/detached state during persistent handle iteration. + Deque<WorklistItem> unknown_worklist_; +}; + +V8EmbedderGraphBuilder::V8EmbedderGraphBuilder(v8::Isolate* isolate, + Graph* graph, + NodeBuilder* node_builder) + : Visitor(ThreadState::Current()), + isolate_(isolate), + graph_(graph), + node_builder_(node_builder) { + CHECK(isolate); + CHECK(graph); + CHECK_EQ(isolate, ThreadState::Current()->GetIsolate()); } void V8EmbedderGraphBuilder::BuildEmbedderGraph() { @@ -86,30 +292,16 @@ DCHECK(unknown_worklist_.empty()); } -V8EmbedderGraphBuilder::DomTreeState -V8EmbedderGraphBuilder::DomTreeStateFromWrapper( - uint16_t class_id, - v8::Local<v8::Object> v8_value) { - if (class_id != WrapperTypeInfo::kNodeClassId) - return DomTreeState::kUnknown; - Node* node = V8Node::ToImpl(v8_value); - Node* root = V8GCController::OpaqueRootForGC(isolate_, node); - if (root->isConnected() && - !node->GetDocument().MasterDocument().IsContextDestroyed()) { - return DomTreeState::kAttached; - } - return DomTreeState::kDetached; -} - void V8EmbedderGraphBuilder::VisitPersistentHandleInternal( v8::Local<v8::Object> v8_value, uint16_t class_id) { ScriptWrappable* traceable = ToScriptWrappable(v8_value); if (!traceable) return; - Graph::Node* wrapper = GraphNode(v8_value); - DomTreeState dom_tree_state = DomTreeStateFromWrapper(class_id, v8_value); - EmbedderNode* graph_node = GraphNode( + Graph::Node* wrapper = node_builder_->GraphNode(v8_value); + DomTreeState dom_tree_state = + DomTreeStateFromWrapper(isolate_, class_id, v8_value); + EmbedderNode* graph_node = node_builder_->GraphNode( traceable, traceable->NameInHeapSnapshot(), wrapper, dom_tree_state); const TraceDescriptor& descriptor = TraceDescriptorFor<ScriptWrappable>(traceable); @@ -152,7 +344,7 @@ // Add an edge from the current parent to the V8 object. v8::Local<v8::Value> v8_value = traced_wrapper.NewLocal(isolate_); if (!v8_value.IsEmpty()) { - graph_->AddEdge(current_parent_, GraphNode(v8_value)); + graph_->AddEdge(current_parent_, node_builder_->GraphNode(v8_value)); } } @@ -168,8 +360,8 @@ HeapObjectHeader::FromPayload(traceable)->GcInfoIndex()) ->name(traceable) .value; - EmbedderNode* graph_node = - GraphNode(traceable, name, nullptr, current_parent_->GetDomTreeState()); + EmbedderNode* graph_node = node_builder_->GraphNode( + traceable, name, nullptr, current_parent_->GetDomTreeState()); graph_->AddEdge(current_parent_, graph_node); PushToWorklist(ToWorklistItem(graph_node, wrapper_descriptor)); } @@ -182,30 +374,6 @@ desc.callback(this, desc.base_object_payload); } -v8::EmbedderGraph::Node* V8EmbedderGraphBuilder::GraphNode( - const v8::Local<v8::Value>& value) const { - return graph_->V8Node(value); -} - -V8EmbedderGraphBuilder::EmbedderNode* V8EmbedderGraphBuilder::GraphNode( - Traceable traceable, - const char* name, - v8::EmbedderGraph::Node* wrapper, - DomTreeState dom_tree_state) const { - auto iter = graph_node_.find(traceable); - if (iter != graph_node_.end()) { - iter->value->UpdateDomTreeState(dom_tree_state); - return iter->value; - } - // Ownership of the new node is transferred to the graph_. - // graph_node_.at(tracable) is valid for all BuildEmbedderGraph execution. - auto* raw_node = new EmbedderNode(name, wrapper, dom_tree_state); - EmbedderNode* node = static_cast<EmbedderNode*>( - graph_->AddNode(std::unique_ptr<Graph::Node>(raw_node))); - graph_node_.insert(traceable, node); - return node; -} - void V8EmbedderGraphBuilder::VisitPendingActivities() { // Ownership of the new node is transferred to the graph_. EmbedderNode* root = @@ -221,7 +389,7 @@ return {node, descriptor.base_object_payload, descriptor.callback}; } -void V8EmbedderGraphBuilder::PushToWorklist(WorklistItem item) const { +void V8EmbedderGraphBuilder::PushToWorklist(WorklistItem item) { if (!visited_.Contains(item.traceable)) { visited_.insert(item.traceable); worklist_.push_back(item); @@ -238,4 +406,12 @@ } } +void EmbedderGraphBuilder::BuildEmbedderGraphCallback(v8::Isolate* isolate, + v8::EmbedderGraph* graph, + void*) { + NodeBuilder node_builder(graph); + V8EmbedderGraphBuilder builder(isolate, graph, &node_builder); + builder.BuildEmbedderGraph(); +} + } // namespace blink
diff --git a/third_party/blink/renderer/bindings/core/v8/v8_embedder_graph_builder.h b/third_party/blink/renderer/bindings/core/v8/v8_embedder_graph_builder.h index a76150d..6fb90c4a 100644 --- a/third_party/blink/renderer/bindings/core/v8/v8_embedder_graph_builder.h +++ b/third_party/blink/renderer/bindings/core/v8/v8_embedder_graph_builder.h
@@ -5,155 +5,19 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_V8_EMBEDDER_GRAPH_BUILDER_H_ #define THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_V8_EMBEDDER_GRAPH_BUILDER_H_ -#include "third_party/blink/renderer/platform/bindings/script_wrappable_visitor.h" +#include "third_party/blink/renderer/platform/wtf/allocator.h" #include "v8/include/v8-profiler.h" #include "v8/include/v8.h" namespace blink { -class V8EmbedderGraphBuilder - : public ScriptWrappableVisitor, - public v8::PersistentHandleVisitor, - public v8::EmbedderHeapTracer::TracedGlobalHandleVisitor { +class EmbedderGraphBuilder { + STATIC_ONLY(EmbedderGraphBuilder); + public: - using Traceable = const void*; - using Graph = v8::EmbedderGraph; - - V8EmbedderGraphBuilder(v8::Isolate*, Graph*); - static void BuildEmbedderGraphCallback(v8::Isolate*, v8::EmbedderGraph*, - void* data); - void BuildEmbedderGraph(); - - // v8::PersistentHandleVisitor override. - void VisitPersistentHandle(v8::Persistent<v8::Value>*, - uint16_t class_id) override; - - // v8::EmbedderHeapTracer::TracedGlobalHandleVisitor override. - void VisitTracedGlobalHandle( - const v8::TracedGlobal<v8::Value>& value) override; - - // Visitor overrides. - void Visit(const TraceWrapperV8Reference<v8::Value>&) final; - void VisitWithWrappers(void*, TraceDescriptor) final; - void VisitBackingStoreStrongly(void* object, - void** object_slot, - TraceDescriptor desc) final; - - protected: - using Visitor::Visit; - - private: - // Information about whether a node is attached to the main DOM tree - // or not. It is computed as follows: - // 1) A Document with IsContextDestroyed() = true is detached. - // 2) A Document with IsContextDestroyed() = false is attached. - // 3) A Node that is not connected to any Document is detached. - // 4) A Node that is connected to a detached Document is detached. - // 5) A Node that is connected to an attached Document is attached. - // 6) A ScriptWrappable that is reachable from an attached Node is - // attached. - // 7) A ScriptWrappable that is reachable from a detached Node is - // detached. - // 8) A ScriptWrappable that is not reachable from any Node is - // considered (conservatively) as attached. - // The unknown state applies to ScriptWrappables during graph - // traversal when we don't have reachability information yet. - enum class DomTreeState { kAttached, kDetached, kUnknown }; - - DomTreeState DomTreeStateFromWrapper(uint16_t class_id, - v8::Local<v8::Object> v8_value); - - class EmbedderNode : public Graph::Node { - public: - EmbedderNode(const char* name, - Graph::Node* wrapper, - DomTreeState dom_tree_state) - : name_(name), wrapper_(wrapper), dom_tree_state_(dom_tree_state) {} - - DomTreeState GetDomTreeState() { return dom_tree_state_; } - void UpdateDomTreeState(DomTreeState parent_dom_tree_state) { - // If the child's state is unknown, then take the parent's state. - // If the parent is attached, then the child is also attached. - if (dom_tree_state_ == DomTreeState::kUnknown || - parent_dom_tree_state == DomTreeState::kAttached) { - dom_tree_state_ = parent_dom_tree_state; - } - } - // Graph::Node overrides. - const char* Name() override { return name_; } - const char* NamePrefix() override { - return dom_tree_state_ == DomTreeState::kDetached ? "Detached" : nullptr; - } - size_t SizeInBytes() override { return 0; } - Graph::Node* WrapperNode() override { return wrapper_; } - - private: - const char* name_; - Graph::Node* wrapper_; - DomTreeState dom_tree_state_; - }; - - class EmbedderRootNode : public EmbedderNode { - public: - explicit EmbedderRootNode(const char* name) - : EmbedderNode(name, nullptr, DomTreeState::kUnknown) {} - // Graph::Node override. - bool IsRootNode() override { return true; } - }; - - class ParentScope { - STACK_ALLOCATED(); - - public: - ParentScope(V8EmbedderGraphBuilder* visitor, EmbedderNode* parent) - : visitor_(visitor) { - DCHECK_EQ(visitor->current_parent_, nullptr); - visitor->current_parent_ = parent; - } - ~ParentScope() { visitor_->current_parent_ = nullptr; } - - private: - V8EmbedderGraphBuilder* visitor_; - }; - - struct WorklistItem { - EmbedderNode* node; - Traceable traceable; - TraceCallback trace_callback; - }; - - void VisitPersistentHandleInternal(v8::Local<v8::Object>, uint16_t); - - WorklistItem ToWorklistItem(EmbedderNode*, const TraceDescriptor&) const; - - Graph::Node* GraphNode(const v8::Local<v8::Value>&) const; - EmbedderNode* GraphNode(Traceable, - const char* name, - Graph::Node* wrapper, - DomTreeState) const; - - void VisitPendingActivities(); - void VisitTransitiveClosure(); - - // Push the item to the default worklist if item.traceable was not - // already visited. - void PushToWorklist(WorklistItem) const; - - v8::Isolate* isolate_; - EmbedderNode* current_parent_; - mutable Graph* graph_; - mutable HashSet<Traceable> visited_; - mutable HashMap<Traceable, EmbedderNode*> graph_node_; - // The default worklist that is used to visit transitive closure. - mutable Deque<WorklistItem> worklist_; - // The worklist that collects detached Nodes during persistent handle - // iteration. - mutable Deque<WorklistItem> detached_worklist_; - // The worklist that collects ScriptWrappables with unknown information - // about attached/detached state during persistent handle iteration. - mutable Deque<WorklistItem> unknown_worklist_; + void*); }; } // namespace blink
diff --git a/third_party/blink/renderer/bindings/core/v8/v8_initializer.cc b/third_party/blink/renderer/bindings/core/v8/v8_initializer.cc index 4a8ed51..2aabade3 100644 --- a/third_party/blink/renderer/bindings/core/v8/v8_initializer.cc +++ b/third_party/blink/renderer/bindings/core/v8/v8_initializer.cc
@@ -742,7 +742,7 @@ if (v8::HeapProfiler* profiler = isolate->GetHeapProfiler()) { profiler->AddBuildEmbedderGraphCallback( - &V8EmbedderGraphBuilder::BuildEmbedderGraphCallback, nullptr); + &EmbedderGraphBuilder::BuildEmbedderGraphCallback, nullptr); } V8PerIsolateData::From(isolate)->SetThreadDebugger(
diff --git a/third_party/blink/renderer/build/scripts/core/css/properties/templates/style_builder_functions.tmpl b/third_party/blink/renderer/build/scripts/core/css/properties/templates/style_builder_functions.tmpl index 039ec51..680cfe6d 100644 --- a/third_party/blink/renderer/build/scripts/core/css/properties/templates/style_builder_functions.tmpl +++ b/third_party/blink/renderer/build/scripts/core/css/properties/templates/style_builder_functions.tmpl
@@ -76,7 +76,7 @@ ResolveDirectionAwareProperty(state.Style()->Direction(), state.Style()->GetWritingMode()); DCHECK(!resolved_property.IDEquals(PropertyID())); -ToLonghand(resolved_property).{{apply_call}}; +To<Longhand>(resolved_property).{{apply_call}}; {% endmacro %} {% macro style_builder_functions(property, header) %}
diff --git a/third_party/blink/renderer/core/animation/css/css_animations.cc b/third_party/blink/renderer/core/animation/css/css_animations.cc index bd8fb87d..71407ff 100644 --- a/third_party/blink/renderer/core/animation/css/css_animations.cc +++ b/third_party/blink/renderer/core/animation/css/css_animations.cc
@@ -382,14 +382,14 @@ wtf_size_t existing_animation_index = 0; if (css_animations) { - for (wtf_size_t i = 0; i < css_animations->running_animations_.size(); - i++) { + for (wtf_size_t j = 0; j < css_animations->running_animations_.size(); + j++) { const RunningAnimation& running_animation = - *css_animations->running_animations_[i]; + *css_animations->running_animations_[j]; if (running_animation.name == name && running_animation.name_index == name_index) { existing_animation = &running_animation; - existing_animation_index = i; + existing_animation_index = j; break; } }
diff --git a/third_party/blink/renderer/core/animation/effect_input.cc b/third_party/blink/renderer/core/animation/effect_input.cc index c2e3d0c..89950ab 100644 --- a/third_party/blink/renderer/core/animation/effect_input.cc +++ b/third_party/blink/renderer/core/animation/effect_input.cc
@@ -426,7 +426,7 @@ // See https://drafts.csswg.org/web-animations/#processing-a-keyframes-argument StringKeyframeVector ConvertObjectForm(Element* element, Document& document, - const v8::Local<v8::Object>& keyframe, + const v8::Local<v8::Object>& v8_keyframe, ScriptState* script_state, ExceptionState& exception_state) { // We implement much of this procedure out of order from the way the spec is @@ -437,7 +437,7 @@ // to process a keyframe-like object'. BasePropertyIndexedKeyframe* property_indexed_keyframe = NativeValueTraits<BasePropertyIndexedKeyframe>::NativeValue( - script_state->GetIsolate(), keyframe, exception_state); + script_state->GetIsolate(), v8_keyframe, exception_state); if (exception_state.HadException()) return {}; @@ -466,7 +466,7 @@ // object' and step 5.2 of the 'procedure to process a keyframes argument'. Vector<String> keyframe_properties = GetOwnPropertyNames( - script_state->GetIsolate(), keyframe, exception_state); + script_state->GetIsolate(), v8_keyframe, exception_state); if (exception_state.HadException()) return {}; @@ -496,7 +496,7 @@ continue; Vector<String> values; - if (!GetPropertyIndexedKeyframeValues(keyframe, property, script_state, + if (!GetPropertyIndexedKeyframeValues(v8_keyframe, property, script_state, exception_state, values)) { return {}; }
diff --git a/third_party/blink/renderer/core/animation/list_interpolation_functions.cc b/third_party/blink/renderer/core/animation/list_interpolation_functions.cc index b1625a5..09bfde3a 100644 --- a/third_party/blink/renderer/core/animation/list_interpolation_functions.cc +++ b/third_party/blink/renderer/core/animation/list_interpolation_functions.cc
@@ -135,17 +135,17 @@ ToNonInterpolableList(*end.non_interpolable_value); for (wtf_size_t i = 0; i < final_length; i++) { - PairwiseInterpolationValue result = nullptr; if (length_matching_strategy == LengthMatchingStrategy::kLowestCommonMultiple || (i < start_length && i < end_length)) { - InterpolationValue start( + InterpolationValue start_merge( start_interpolable_list.Get(i % start_length)->Clone(), start_non_interpolable_list.Get(i % start_length)); - InterpolationValue end(end_interpolable_list.Get(i % end_length)->Clone(), - end_non_interpolable_list.Get(i % end_length)); - PairwiseInterpolationValue result = - merge_single_item_conversions.Run(std::move(start), std::move(end)); + InterpolationValue end_merge( + end_interpolable_list.Get(i % end_length)->Clone(), + end_non_interpolable_list.Get(i % end_length)); + PairwiseInterpolationValue result = merge_single_item_conversions.Run( + std::move(start_merge), std::move(end_merge)); if (!result) return nullptr; result_start_interpolable_list->Set(
diff --git a/third_party/blink/renderer/core/css/cssom/computed_style_property_map.cc b/third_party/blink/renderer/core/css/cssom/computed_style_property_map.cc index 303d6d78..1c0f69e 100644 --- a/third_party/blink/renderer/core/css/cssom/computed_style_property_map.cc +++ b/third_party/blink/renderer/core/css/cssom/computed_style_property_map.cc
@@ -163,7 +163,7 @@ } // namespace -unsigned int ComputedStylePropertyMap::size() { +unsigned int ComputedStylePropertyMap::size() const { const ComputedStyle* style = UpdateStyle(); if (!style) return 0; @@ -202,7 +202,7 @@ return nullptr; } -const ComputedStyle* ComputedStylePropertyMap::UpdateStyle() { +const ComputedStyle* ComputedStylePropertyMap::UpdateStyle() const { Node* node = StyledNode(); if (!node || !node->InActiveDocument()) return nullptr; @@ -225,7 +225,7 @@ } const CSSValue* ComputedStylePropertyMap::GetProperty( - CSSPropertyID property_id) { + CSSPropertyID property_id) const { const ComputedStyle* style = UpdateStyle(); if (!style) return nullptr; @@ -244,7 +244,7 @@ } const CSSValue* ComputedStylePropertyMap::GetCustomProperty( - AtomicString property_name) { + AtomicString property_name) const { const ComputedStyle* style = UpdateStyle(); if (!style) return nullptr; @@ -290,7 +290,7 @@ } String ComputedStylePropertyMap::SerializationForShorthand( - const CSSProperty& property) { + const CSSProperty& property) const { DCHECK(property.IsShorthand()); const ComputedStyle* style = UpdateStyle(); if (!style) {
diff --git a/third_party/blink/renderer/core/css/cssom/computed_style_property_map.h b/third_party/blink/renderer/core/css/cssom/computed_style_property_map.h index 0bcd9f97..bf4b583 100644 --- a/third_party/blink/renderer/core/css/cssom/computed_style_property_map.h +++ b/third_party/blink/renderer/core/css/cssom/computed_style_property_map.h
@@ -39,7 +39,7 @@ StylePropertyMapReadOnlyMainThread::Trace(visitor); } - unsigned int size() override; + unsigned int size() const override; // ComputedStylePropertyMap needs to be sorted. This puts CSS properties // first, then prefixed properties, then custom properties. Everything is @@ -48,11 +48,11 @@ const CSSPropertyName&); protected: - const CSSValue* GetProperty(CSSPropertyID) override; - const CSSValue* GetCustomProperty(AtomicString) override; + const CSSValue* GetProperty(CSSPropertyID) const override; + const CSSValue* GetCustomProperty(AtomicString) const override; void ForEachProperty(const IterationCallback&) override; - String SerializationForShorthand(const CSSProperty&) final; + String SerializationForShorthand(const CSSProperty&) const final; private: // TODO: Pseudo-element support requires reintroducing Element.pseudo(...). @@ -62,7 +62,7 @@ Member<Node> node_; Node* StyledNode() const; - const ComputedStyle* UpdateStyle(); + const ComputedStyle* UpdateStyle() const; DISALLOW_COPY_AND_ASSIGN(ComputedStylePropertyMap); };
diff --git a/third_party/blink/renderer/core/css/cssom/declared_style_property_map.cc b/third_party/blink/renderer/core/css/cssom/declared_style_property_map.cc index 7727b70..71786559 100644 --- a/third_party/blink/renderer/core/css/cssom/declared_style_property_map.cc +++ b/third_party/blink/renderer/core/css/cssom/declared_style_property_map.cc
@@ -17,21 +17,21 @@ DeclaredStylePropertyMap::DeclaredStylePropertyMap(CSSStyleRule* owner_rule) : StylePropertyMap(), owner_rule_(owner_rule) {} -unsigned int DeclaredStylePropertyMap::size() { +unsigned int DeclaredStylePropertyMap::size() const { if (!GetStyleRule()) return 0; return GetStyleRule()->Properties().PropertyCount(); } const CSSValue* DeclaredStylePropertyMap::GetProperty( - CSSPropertyID property_id) { + CSSPropertyID property_id) const { if (!GetStyleRule()) return nullptr; return GetStyleRule()->Properties().GetPropertyCSSValue(property_id); } const CSSValue* DeclaredStylePropertyMap::GetCustomProperty( - AtomicString property_name) { + AtomicString property_name) const { if (!GetStyleRule()) return nullptr; return GetStyleRule()->Properties().GetPropertyCSSValue(property_name); @@ -111,7 +111,7 @@ } String DeclaredStylePropertyMap::SerializationForShorthand( - const CSSProperty& property) { + const CSSProperty& property) const { DCHECK(property.IsShorthand()); if (StyleRule* style_rule = GetStyleRule()) { return StylePropertySerializer(style_rule->Properties())
diff --git a/third_party/blink/renderer/core/css/cssom/declared_style_property_map.h b/third_party/blink/renderer/core/css/cssom/declared_style_property_map.h index 63e229b..f0757b74 100644 --- a/third_party/blink/renderer/core/css/cssom/declared_style_property_map.h +++ b/third_party/blink/renderer/core/css/cssom/declared_style_property_map.h
@@ -29,11 +29,11 @@ StylePropertyMap::Trace(visitor); } - unsigned int size() final; + unsigned int size() const final; protected: - const CSSValue* GetProperty(CSSPropertyID) override; - const CSSValue* GetCustomProperty(AtomicString) override; + const CSSValue* GetProperty(CSSPropertyID) const override; + const CSSValue* GetCustomProperty(AtomicString) const override; void ForEachProperty(const IterationCallback&) override; void SetProperty(CSSPropertyID, const CSSValue&) override; bool SetShorthandProperty(CSSPropertyID, @@ -44,7 +44,7 @@ void RemoveCustomProperty(const AtomicString&) override; void RemoveAllProperties() final; - String SerializationForShorthand(const CSSProperty&) final; + String SerializationForShorthand(const CSSProperty&) const final; private: StyleRule* GetStyleRule() const;
diff --git a/third_party/blink/renderer/core/css/cssom/inline_style_property_map.cc b/third_party/blink/renderer/core/css/cssom/inline_style_property_map.cc index 048930d..933a6af 100644 --- a/third_party/blink/renderer/core/css/cssom/inline_style_property_map.cc +++ b/third_party/blink/renderer/core/css/cssom/inline_style_property_map.cc
@@ -11,19 +11,20 @@ namespace blink { -unsigned int InlineStylePropertyMap::size() { +unsigned int InlineStylePropertyMap::size() const { const CSSPropertyValueSet* inline_style = owner_element_->InlineStyle(); return inline_style ? inline_style->PropertyCount() : 0; } -const CSSValue* InlineStylePropertyMap::GetProperty(CSSPropertyID property_id) { +const CSSValue* InlineStylePropertyMap::GetProperty( + CSSPropertyID property_id) const { const CSSPropertyValueSet* inline_style = owner_element_->InlineStyle(); return inline_style ? inline_style->GetPropertyCSSValue(property_id) : nullptr; } const CSSValue* InlineStylePropertyMap::GetCustomProperty( - AtomicString property_name) { + AtomicString property_name) const { const CSSPropertyValueSet* inline_style = owner_element_->InlineStyle(); return inline_style ? inline_style->GetPropertyCSSValue(property_name) : nullptr; @@ -79,7 +80,7 @@ } String InlineStylePropertyMap::SerializationForShorthand( - const CSSProperty& property) { + const CSSProperty& property) const { DCHECK(property.IsShorthand()); if (const CSSPropertyValueSet* inline_style = owner_element_->InlineStyle()) { return StylePropertySerializer(*inline_style)
diff --git a/third_party/blink/renderer/core/css/cssom/inline_style_property_map.h b/third_party/blink/renderer/core/css/cssom/inline_style_property_map.h index 791504bd..40969db 100644 --- a/third_party/blink/renderer/core/css/cssom/inline_style_property_map.h +++ b/third_party/blink/renderer/core/css/cssom/inline_style_property_map.h
@@ -21,11 +21,11 @@ StylePropertyMap::Trace(visitor); } - unsigned int size() final; + unsigned int size() const final; protected: - const CSSValue* GetProperty(CSSPropertyID) override; - const CSSValue* GetCustomProperty(AtomicString) override; + const CSSValue* GetProperty(CSSPropertyID) const override; + const CSSValue* GetCustomProperty(AtomicString) const override; void ForEachProperty(const IterationCallback&) override; void SetProperty(CSSPropertyID, const CSSValue&) override; bool SetShorthandProperty(CSSPropertyID, @@ -36,7 +36,7 @@ void RemoveCustomProperty(const AtomicString&) override; void RemoveAllProperties() final; - String SerializationForShorthand(const CSSProperty&) final; + String SerializationForShorthand(const CSSProperty&) const final; private: Member<Element> owner_element_;
diff --git a/third_party/blink/renderer/core/css/cssom/paint_worklet_input.h b/third_party/blink/renderer/core/css/cssom/paint_worklet_input.h index 1a88409c..f3e53f2 100644 --- a/third_party/blink/renderer/core/css/cssom/paint_worklet_input.h +++ b/third_party/blink/renderer/core/css/cssom/paint_worklet_input.h
@@ -35,7 +35,9 @@ const std::string& Name() const { return name_; } const FloatSize& ContainerSize() const { return container_size_; } float EffectiveZoom() const { return effective_zoom_; } - PaintWorkletStylePropertyMap* StyleMap() { return style_map_.Get(); } + const PaintWorkletStylePropertyMap* StyleMap() const { + return style_map_.Get(); + } private: const std::string name_;
diff --git a/third_party/blink/renderer/core/css/cssom/paint_worklet_style_property_map.cc b/third_party/blink/renderer/core/css/cssom/paint_worklet_style_property_map.cc index 8f393ee..d5b646d 100644 --- a/third_party/blink/renderer/core/css/cssom/paint_worklet_style_property_map.cc +++ b/third_party/blink/renderer/core/css/cssom/paint_worklet_style_property_map.cc
@@ -110,7 +110,7 @@ CSSStyleValue* PaintWorkletStylePropertyMap::get( const ExecutionContext* execution_context, const String& property_name, - ExceptionState& exception_state) { + ExceptionState& exception_state) const { CSSStyleValueVector all_values = getAll(execution_context, property_name, exception_state); return all_values.IsEmpty() ? nullptr : all_values[0]; @@ -119,7 +119,7 @@ CSSStyleValueVector PaintWorkletStylePropertyMap::getAll( const ExecutionContext* execution_context, const String& property_name, - ExceptionState& exception_state) { + ExceptionState& exception_state) const { CSSPropertyID property_id = cssPropertyID(property_name); if (property_id == CSSPropertyInvalid) { exception_state.ThrowTypeError("Invalid propertyName: " + property_name); @@ -139,11 +139,11 @@ bool PaintWorkletStylePropertyMap::has( const ExecutionContext* execution_context, const String& property_name, - ExceptionState& exception_state) { + ExceptionState& exception_state) const { return !getAll(execution_context, property_name, exception_state).IsEmpty(); } -unsigned PaintWorkletStylePropertyMap::size() { +unsigned PaintWorkletStylePropertyMap::size() const { return values_.size(); }
diff --git a/third_party/blink/renderer/core/css/cssom/paint_worklet_style_property_map.h b/third_party/blink/renderer/core/css/cssom/paint_worklet_style_property_map.h index fe7b063..8ce2561 100644 --- a/third_party/blink/renderer/core/css/cssom/paint_worklet_style_property_map.h +++ b/third_party/blink/renderer/core/css/cssom/paint_worklet_style_property_map.h
@@ -33,22 +33,22 @@ CSSStyleValue* get(const ExecutionContext*, const String& property_name, - ExceptionState&) override; + ExceptionState&) const override; CSSStyleValueVector getAll(const ExecutionContext*, const String& property_name, - ExceptionState&) override; + ExceptionState&) const override; bool has(const ExecutionContext*, const String& property_name, - ExceptionState&) override; + ExceptionState&) const override; - unsigned int size() override; + unsigned int size() const override; void Trace(blink::Visitor*) override; - const HashMap<String, std::unique_ptr<CrossThreadStyleValue>>& - ValuesForTest() { + const HashMap<String, std::unique_ptr<CrossThreadStyleValue>>& ValuesForTest() + const { return values_; }
diff --git a/third_party/blink/renderer/core/css/cssom/paint_worklet_style_property_map_test.cc b/third_party/blink/renderer/core/css/cssom/paint_worklet_style_property_map_test.cc index 2277f039..a444aba4 100644 --- a/third_party/blink/renderer/core/css/cssom/paint_worklet_style_property_map_test.cc +++ b/third_party/blink/renderer/core/css/cssom/paint_worklet_style_property_map_test.cc
@@ -44,7 +44,7 @@ waitable_event.Wait(); } - void CheckCustomProperties(PaintWorkletStylePropertyMap* map, + void CheckCustomProperties(const PaintWorkletStylePropertyMap* map, DummyExceptionStateForTesting& exception_state) { const CSSStyleValue* foo = map->get(nullptr, "--foo", exception_state); ASSERT_NE(nullptr, foo); @@ -71,7 +71,7 @@ EXPECT_FALSE(exception_state.HadException()); } - void CheckNativeProperties(PaintWorkletStylePropertyMap* map, + void CheckNativeProperties(const PaintWorkletStylePropertyMap* map, DummyExceptionStateForTesting& exception_state) { map->get(nullptr, "color", exception_state); EXPECT_FALSE(exception_state.HadException()); @@ -100,7 +100,7 @@ DCHECK(!IsMainThread()); thread_->InitializeOnThread(); - PaintWorkletStylePropertyMap* map = input->StyleMap(); + const PaintWorkletStylePropertyMap* map = input->StyleMap(); DCHECK(map); DummyExceptionStateForTesting exception_state; CheckNativeProperties(map, exception_state); @@ -159,7 +159,7 @@ UpdateAllLifecyclePhasesForTest(); Node* node = PageNode(); - PaintWorkletStylePropertyMap* map = + const PaintWorkletStylePropertyMap* map = MakeGarbageCollected<PaintWorkletStylePropertyMap>( GetDocument(), node->ComputedStyleRef(), node, native_properties, empty_custom_properties); @@ -187,7 +187,7 @@ UpdateAllLifecyclePhasesForTest(); Node* node = PageNode(); - PaintWorkletStylePropertyMap* map = + const PaintWorkletStylePropertyMap* map = MakeGarbageCollected<PaintWorkletStylePropertyMap>( GetDocument(), node->ComputedStyleRef(), node, empty_native_properties, custom_properties);
diff --git a/third_party/blink/renderer/core/css/cssom/prepopulated_computed_style_property_map.cc b/third_party/blink/renderer/core/css/cssom/prepopulated_computed_style_property_map.cc index 375abfb..0c60272d 100644 --- a/third_party/blink/renderer/core/css/cssom/prepopulated_computed_style_property_map.cc +++ b/third_party/blink/renderer/core/css/cssom/prepopulated_computed_style_property_map.cc
@@ -41,7 +41,7 @@ } } -unsigned PrepopulatedComputedStylePropertyMap::size() { +unsigned PrepopulatedComputedStylePropertyMap::size() const { return native_values_.size() + custom_values_.size(); } @@ -83,12 +83,12 @@ } const CSSValue* PrepopulatedComputedStylePropertyMap::GetProperty( - CSSPropertyID property_id) { + CSSPropertyID property_id) const { return native_values_.at(property_id); } const CSSValue* PrepopulatedComputedStylePropertyMap::GetCustomProperty( - AtomicString property_name) { + AtomicString property_name) const { return custom_values_.at(property_name); } @@ -117,7 +117,7 @@ } String PrepopulatedComputedStylePropertyMap::SerializationForShorthand( - const CSSProperty&) { + const CSSProperty&) const { // TODO(816722): Shorthands not yet supported for this style map. NOTREACHED(); return "";
diff --git a/third_party/blink/renderer/core/css/cssom/prepopulated_computed_style_property_map.h b/third_party/blink/renderer/core/css/cssom/prepopulated_computed_style_property_map.h index 7d346e5f..c4419a21 100644 --- a/third_party/blink/renderer/core/css/cssom/prepopulated_computed_style_property_map.h +++ b/third_party/blink/renderer/core/css/cssom/prepopulated_computed_style_property_map.h
@@ -38,15 +38,15 @@ // Updates the values of the properties based on the new computed style. void UpdateStyle(const Document&, const ComputedStyle&); - unsigned size() override; + unsigned size() const override; void Trace(blink::Visitor*) override; protected: - const CSSValue* GetProperty(CSSPropertyID) override; - const CSSValue* GetCustomProperty(AtomicString) override; + const CSSValue* GetProperty(CSSPropertyID) const override; + const CSSValue* GetCustomProperty(AtomicString) const override; void ForEachProperty(const IterationCallback&) override; - String SerializationForShorthand(const CSSProperty&) override; + String SerializationForShorthand(const CSSProperty&) const override; private: void UpdateNativeProperty(const ComputedStyle&, CSSPropertyID);
diff --git a/third_party/blink/renderer/core/css/cssom/style_property_map_read_only.h b/third_party/blink/renderer/core/css/cssom/style_property_map_read_only.h index bdb8445..cf577d9 100644 --- a/third_party/blink/renderer/core/css/cssom/style_property_map_read_only.h +++ b/third_party/blink/renderer/core/css/cssom/style_property_map_read_only.h
@@ -22,15 +22,15 @@ public: virtual CSSStyleValue* get(const ExecutionContext*, const String& property_name, - ExceptionState&) = 0; + ExceptionState&) const = 0; virtual CSSStyleValueVector getAll(const ExecutionContext*, const String& property_name, - ExceptionState&) = 0; + ExceptionState&) const = 0; virtual bool has(const ExecutionContext*, const String& property_name, - ExceptionState&) = 0; + ExceptionState&) const = 0; - virtual unsigned int size() = 0; + virtual unsigned int size() const = 0; }; } // namespace blink
diff --git a/third_party/blink/renderer/core/css/cssom/style_property_map_read_only_main_thread.cc b/third_party/blink/renderer/core/css/cssom/style_property_map_read_only_main_thread.cc index 7af8d20..f1fb21a3 100644 --- a/third_party/blink/renderer/core/css/cssom/style_property_map_read_only_main_thread.cc +++ b/third_party/blink/renderer/core/css/cssom/style_property_map_read_only_main_thread.cc
@@ -61,7 +61,7 @@ CSSStyleValue* StylePropertyMapReadOnlyMainThread::get( const ExecutionContext* execution_context, const String& property_name, - ExceptionState& exception_state) { + ExceptionState& exception_state) const { base::Optional<CSSPropertyName> name = CSSPropertyName::From(property_name); if (!name) { @@ -94,7 +94,7 @@ CSSStyleValueVector StylePropertyMapReadOnlyMainThread::getAll( const ExecutionContext* execution_context, const String& property_name, - ExceptionState& exception_state) { + ExceptionState& exception_state) const { base::Optional<CSSPropertyName> name = CSSPropertyName::From(property_name); if (!name) { @@ -123,13 +123,13 @@ bool StylePropertyMapReadOnlyMainThread::has( const ExecutionContext* execution_context, const String& property_name, - ExceptionState& exception_state) { + ExceptionState& exception_state) const { return !getAll(execution_context, property_name, exception_state).IsEmpty(); } const CSSValue* StylePropertyMapReadOnlyMainThread::GetCustomProperty( const ExecutionContext& execution_context, - const AtomicString& property_name) { + const AtomicString& property_name) const { const CSSValue* value = GetCustomProperty(property_name); const auto* document = DynamicTo<Document>(execution_context); @@ -169,7 +169,7 @@ } CSSStyleValue* StylePropertyMapReadOnlyMainThread::GetShorthandProperty( - const CSSProperty& property) { + const CSSProperty& property) const { DCHECK(property.IsShorthand()); const auto serialization = SerializationForShorthand(property); if (serialization.IsEmpty())
diff --git a/third_party/blink/renderer/core/css/cssom/style_property_map_read_only_main_thread.h b/third_party/blink/renderer/core/css/cssom/style_property_map_read_only_main_thread.h index 0acda91..c98f863 100644 --- a/third_party/blink/renderer/core/css/cssom/style_property_map_read_only_main_thread.h +++ b/third_party/blink/renderer/core/css/cssom/style_property_map_read_only_main_thread.h
@@ -21,35 +21,35 @@ CSSStyleValue* get(const ExecutionContext*, const String& property_name, - ExceptionState&) override; + ExceptionState&) const override; CSSStyleValueVector getAll(const ExecutionContext*, const String& property_name, - ExceptionState&) override; + ExceptionState&) const override; bool has(const ExecutionContext*, const String& property_name, - ExceptionState&) override; + ExceptionState&) const override; - unsigned int size() override = 0; + unsigned int size() const override = 0; protected: StylePropertyMapReadOnlyMainThread() = default; - virtual const CSSValue* GetProperty(CSSPropertyID) = 0; - virtual const CSSValue* GetCustomProperty(AtomicString) = 0; + virtual const CSSValue* GetProperty(CSSPropertyID) const = 0; + virtual const CSSValue* GetCustomProperty(AtomicString) const = 0; using IterationCallback = std::function<void(const CSSPropertyName&, const CSSValue&)>; virtual void ForEachProperty(const IterationCallback&) = 0; - virtual String SerializationForShorthand(const CSSProperty&) = 0; + virtual String SerializationForShorthand(const CSSProperty&) const = 0; const CSSValue* GetCustomProperty(const ExecutionContext&, - const AtomicString&); + const AtomicString&) const; private: IterationSource* StartIteration(ScriptState*, ExceptionState&) override; - CSSStyleValue* GetShorthandProperty(const CSSProperty&); + CSSStyleValue* GetShorthandProperty(const CSSProperty&) const; private: DISALLOW_COPY_AND_ASSIGN(StylePropertyMapReadOnlyMainThread);
diff --git a/third_party/blink/renderer/core/css/parser/css_property_parser_helpers.cc b/third_party/blink/renderer/core/css/parser/css_property_parser_helpers.cc index 14375c84..aebac1d 100644 --- a/third_party/blink/renderer/core/css/parser/css_property_parser_helpers.cc +++ b/third_party/blink/renderer/core/css/parser/css_property_parser_helpers.cc
@@ -1909,7 +1909,7 @@ .WithAliasParsing(isPropertyAlias(unresolved_property)) .WithCurrentShorthand(current_shorthand); - const CSSValue* result = ToLonghand(CSSProperty::Get(property_id)) + const CSSValue* result = To<Longhand>(CSSProperty::Get(property_id)) .ParseSingleValue(range, context, local_context); return result; }
diff --git a/third_party/blink/renderer/core/css/properties/css_parsing_utils.cc b/third_party/blink/renderer/core/css/properties/css_parsing_utils.cc index 249c9be..475b3a6e 100644 --- a/third_party/blink/renderer/core/css/properties/css_parsing_utils.cc +++ b/third_party/blink/renderer/core/css/properties/css_parsing_utils.cc
@@ -591,7 +591,7 @@ for (unsigned i = 0; i < longhand_count; ++i) { if (!parsed_longhand[i]) { longhands[i]->Append( - *ToLonghand(shorthand.properties()[i])->InitialValue()); + *To<Longhand>(shorthand.properties()[i])->InitialValue()); } parsed_longhand[i] = false; }
diff --git a/third_party/blink/renderer/core/css/properties/longhand.h b/third_party/blink/renderer/core/css/properties/longhand.h index 053abca8..52a04325 100644 --- a/third_party/blink/renderer/core/css/properties/longhand.h +++ b/third_party/blink/renderer/core/css/properties/longhand.h
@@ -9,6 +9,7 @@ #include "third_party/blink/renderer/core/css/css_initial_value.h" #include "third_party/blink/renderer/platform/graphics/color.h" +#include "third_party/blink/renderer/platform/wtf/casting.h" namespace blink { @@ -43,11 +44,12 @@ constexpr Longhand() : CSSProperty() {} }; -DEFINE_TYPE_CASTS(Longhand, - CSSProperty, - longhand, - longhand->IsLonghand(), - longhand.IsLonghand()); +template <> +struct DowncastTraits<Longhand> { + static bool AllowFrom(const CSSProperty& longhand) { + return longhand.IsLonghand(); + } +}; } // namespace blink
diff --git a/third_party/blink/renderer/core/css/properties/shorthands/border_image_custom.cc b/third_party/blink/renderer/core/css/properties/shorthands/border_image_custom.cc index 7928f69..7dafd9db 100644 --- a/third_party/blink/renderer/core/css/properties/shorthands/border_image_custom.cc +++ b/third_party/blink/renderer/core/css/properties/shorthands/border_image_custom.cc
@@ -35,32 +35,35 @@ css_property_parser_helpers::AddProperty( CSSPropertyBorderImageSource, CSSPropertyBorderImage, - source ? *source - : *ToLonghand(&GetCSSPropertyBorderImageSource())->InitialValue(), + source + ? *source + : *To<Longhand>(&GetCSSPropertyBorderImageSource())->InitialValue(), important, css_property_parser_helpers::IsImplicitProperty::kNotImplicit, properties); css_property_parser_helpers::AddProperty( CSSPropertyBorderImageSlice, CSSPropertyBorderImage, slice ? *slice - : *ToLonghand(&GetCSSPropertyBorderImageSlice())->InitialValue(), + : *To<Longhand>(&GetCSSPropertyBorderImageSlice())->InitialValue(), important, css_property_parser_helpers::IsImplicitProperty::kNotImplicit, properties); css_property_parser_helpers::AddProperty( CSSPropertyBorderImageWidth, CSSPropertyBorderImage, width ? *width - : *ToLonghand(&GetCSSPropertyBorderImageWidth())->InitialValue(), + : *To<Longhand>(&GetCSSPropertyBorderImageWidth())->InitialValue(), important, css_property_parser_helpers::IsImplicitProperty::kNotImplicit, properties); css_property_parser_helpers::AddProperty( CSSPropertyBorderImageOutset, CSSPropertyBorderImage, - outset ? *outset - : *ToLonghand(&GetCSSPropertyBorderImageOutset())->InitialValue(), + outset + ? *outset + : *To<Longhand>(&GetCSSPropertyBorderImageOutset())->InitialValue(), important, css_property_parser_helpers::IsImplicitProperty::kNotImplicit, properties); css_property_parser_helpers::AddProperty( CSSPropertyBorderImageRepeat, CSSPropertyBorderImage, - repeat ? *repeat - : *ToLonghand(&GetCSSPropertyBorderImageRepeat())->InitialValue(), + repeat + ? *repeat + : *To<Longhand>(&GetCSSPropertyBorderImageRepeat())->InitialValue(), important, css_property_parser_helpers::IsImplicitProperty::kNotImplicit, properties);
diff --git a/third_party/blink/renderer/core/css/properties/shorthands/offset_custom.cc b/third_party/blink/renderer/core/css/properties/shorthands/offset_custom.cc index 81169ef4..7a921e99 100644 --- a/third_party/blink/renderer/core/css/properties/shorthands/offset_custom.cc +++ b/third_party/blink/renderer/core/css/properties/shorthands/offset_custom.cc
@@ -28,7 +28,7 @@ // CSSPropertys, and the base CSSProperty::ParseSingleValue contains // no functionality. const CSSValue* offset_position = - ToLonghand(GetCSSPropertyOffsetPosition()) + To<Longhand>(GetCSSPropertyOffsetPosition()) .ParseSingleValue(range, context, CSSParserLocalContext()); const CSSValue* offset_path = css_parsing_utils::ConsumeOffsetPath(range, context); @@ -46,7 +46,7 @@ const CSSValue* offset_anchor = nullptr; if (css_property_parser_helpers::ConsumeSlashIncludingWhitespace(range)) { offset_anchor = - ToLonghand(GetCSSPropertyOffsetAnchor()) + To<Longhand>(GetCSSPropertyOffsetAnchor()) .ParseSingleValue(range, context, CSSParserLocalContext()); if (!offset_anchor) return false;
diff --git a/third_party/blink/renderer/core/css/properties/shorthands/place_content_custom.cc b/third_party/blink/renderer/core/css/properties/shorthands/place_content_custom.cc index 99c29aa..70d2a9d 100644 --- a/third_party/blink/renderer/core/css/properties/shorthands/place_content_custom.cc +++ b/third_party/blink/renderer/core/css/properties/shorthands/place_content_custom.cc
@@ -24,7 +24,7 @@ CSSParserTokenRange range_copy = range; const CSSValue* align_content_value = - ToLonghand(GetCSSPropertyAlignContent()) + To<Longhand>(GetCSSPropertyAlignContent()) .ParseSingleValue(range, context, local_context); if (!align_content_value) return false; @@ -33,7 +33,7 @@ range = range_copy; const CSSValue* justify_content_value = - ToLonghand(GetCSSPropertyJustifyContent()) + To<Longhand>(GetCSSPropertyJustifyContent()) .ParseSingleValue(range, context, local_context); if (!justify_content_value || !range.AtEnd()) return false;
diff --git a/third_party/blink/renderer/core/css/properties/shorthands/place_items_custom.cc b/third_party/blink/renderer/core/css/properties/shorthands/place_items_custom.cc index c7b6c2fb..bb3fc0b9 100644 --- a/third_party/blink/renderer/core/css/properties/shorthands/place_items_custom.cc +++ b/third_party/blink/renderer/core/css/properties/shorthands/place_items_custom.cc
@@ -24,7 +24,7 @@ CSSParserTokenRange range_copy = range; const CSSValue* align_items_value = - ToLonghand(GetCSSPropertyAlignItems()) + To<Longhand>(GetCSSPropertyAlignItems()) .ParseSingleValue(range, context, local_context); if (!align_items_value) return false; @@ -33,7 +33,7 @@ range = range_copy; const CSSValue* justify_items_value = - ToLonghand(GetCSSPropertyJustifyItems()) + To<Longhand>(GetCSSPropertyJustifyItems()) .ParseSingleValue(range, context, local_context); if (!justify_items_value || !range.AtEnd()) return false;
diff --git a/third_party/blink/renderer/core/css/properties/shorthands/place_self_custom.cc b/third_party/blink/renderer/core/css/properties/shorthands/place_self_custom.cc index c4683c9..639ae9d 100644 --- a/third_party/blink/renderer/core/css/properties/shorthands/place_self_custom.cc +++ b/third_party/blink/renderer/core/css/properties/shorthands/place_self_custom.cc
@@ -24,7 +24,7 @@ CSSParserTokenRange range_copy = range; const CSSValue* align_self_value = - ToLonghand(GetCSSPropertyAlignSelf()) + To<Longhand>(GetCSSPropertyAlignSelf()) .ParseSingleValue(range, context, local_context); if (!align_self_value) return false; @@ -33,7 +33,7 @@ range = range_copy; const CSSValue* justify_self_value = - ToLonghand(GetCSSPropertyJustifySelf()) + To<Longhand>(GetCSSPropertyJustifySelf()) .ParseSingleValue(range, context, local_context); if (!justify_self_value || !range.AtEnd()) return false;
diff --git a/third_party/blink/renderer/core/css/resolver/style_builder.cc b/third_party/blink/renderer/core/css/resolver/style_builder.cc index 78c281e..01010861 100644 --- a/third_party/blink/renderer/core/css/resolver/style_builder.cc +++ b/third_party/blink/renderer/core/css/resolver/style_builder.cc
@@ -121,11 +121,11 @@ DCHECK(id != CSSPropertyVariable || !is_inherit); if (is_initial) - ToLonghand(property).ApplyInitial(state); + To<Longhand>(property).ApplyInitial(state); else if (is_inherit) - ToLonghand(property).ApplyInherit(state); + To<Longhand>(property).ApplyInherit(state); else - ToLonghand(property).ApplyValue(state, value); + To<Longhand>(property).ApplyValue(state, value); } } // namespace blink
diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink/renderer/core/dom/document.cc index 1d04d16..e7debdfc 100644 --- a/third_party/blink/renderer/core/dom/document.cc +++ b/third_party/blink/renderer/core/dom/document.cc
@@ -2599,16 +2599,13 @@ UpdateStyleAndLayoutTree(); } -void Document::UpdateStyleAndLayoutIgnorePendingStylesheets( - Document::RunPostLayoutTasks run_post_layout_tasks) { +void Document::UpdateStyleAndLayoutIgnorePendingStylesheets() { DCHECK(!find_in_page_root_); - UpdateStyleAndLayoutIgnorePendingStylesheetsConsideringInvisibleNodes( - run_post_layout_tasks); + UpdateStyleAndLayoutIgnorePendingStylesheetsConsideringInvisibleNodes(); } void Document:: - UpdateStyleAndLayoutIgnorePendingStylesheetsConsideringInvisibleNodes( - Document::RunPostLayoutTasks run_post_layout_tasks) { + UpdateStyleAndLayoutIgnorePendingStylesheetsConsideringInvisibleNodes() { LocalFrameView* local_view = View(); if (local_view) local_view->WillStartForcedLayout(); @@ -2616,12 +2613,8 @@ UpdateStyleAndLayoutTreeIgnorePendingStylesheets(); UpdateStyleAndLayout(); - if (local_view) { - if (run_post_layout_tasks == kRunPostLayoutTasksSynchronously) - local_view->FlushAnyPendingPostLayoutTasks(); - + if (local_view) local_view->DidFinishForcedLayout(); - } } scoped_refptr<ComputedStyle> Document::StyleForPage(int page_index) {
diff --git a/third_party/blink/renderer/core/dom/document.h b/third_party/blink/renderer/core/dom/document.h index 348004be7..9cbc69b 100644 --- a/third_party/blink/renderer/core/dom/document.h +++ b/third_party/blink/renderer/core/dom/document.h
@@ -521,12 +521,10 @@ kRunPostLayoutTasksAsynchronously, kRunPostLayoutTasksSynchronously, }; - void UpdateStyleAndLayoutIgnorePendingStylesheets( - RunPostLayoutTasks = kRunPostLayoutTasksAsynchronously); + void UpdateStyleAndLayoutIgnorePendingStylesheets(); // Same as UpdateStyleAndLayoutIgnorePendingStyleSheets() // but allows style & layout tree calculation for invisible nodes. - void UpdateStyleAndLayoutIgnorePendingStylesheetsConsideringInvisibleNodes( - RunPostLayoutTasks = kRunPostLayoutTasksAsynchronously); + void UpdateStyleAndLayoutIgnorePendingStylesheetsConsideringInvisibleNodes(); void UpdateStyleAndLayoutIgnorePendingStylesheetsForNode(const Node*); scoped_refptr<ComputedStyle> StyleForPage(int page_index);
diff --git a/third_party/blink/renderer/core/editing/inline_box_position.cc b/third_party/blink/renderer/core/editing/inline_box_position.cc index f792ee28..73d81dd4 100644 --- a/third_party/blink/renderer/core/editing/inline_box_position.cc +++ b/third_party/blink/renderer/core/editing/inline_box_position.cc
@@ -217,8 +217,7 @@ } const PositionTemplate<Strategy>& upstream_equivalent = UpstreamIgnoringEditingBoundaries(position); - if (upstream_equivalent == position || - DownstreamIgnoringEditingBoundaries(upstream_equivalent) == position) + if (upstream_equivalent == position) return PositionWithAffinityTemplate<Strategy>(); return ComputeInlineAdjustedPositionAlgorithm(
diff --git a/third_party/blink/renderer/core/editing/inline_box_position_test.cc b/third_party/blink/renderer/core/editing/inline_box_position_test.cc index f4ad06e..44d1ff7 100644 --- a/third_party/blink/renderer/core/editing/inline_box_position_test.cc +++ b/third_party/blink/renderer/core/editing/inline_box_position_test.cc
@@ -49,12 +49,15 @@ SetBodyContent( "<div contenteditable id=sample>abc<input contenteditable=false></div>"); Element* const sample = GetDocument().getElementById("sample"); + Element* const input = GetDocument().QuerySelector("input"); + const InlineBox* const input_wrapper_box = + ToLayoutBox(input->GetLayoutObject())->InlineBoxWrapper(); const InlineBoxPosition& actual = ComputeInlineBoxPosition( PositionWithAffinity(Position::LastPositionInNode(*sample))); // Should not be in infinite-loop - EXPECT_EQ(nullptr, actual.inline_box); - EXPECT_EQ(0, actual.offset_in_box); + EXPECT_EQ(input_wrapper_box, actual.inline_box); + EXPECT_EQ(1, actual.offset_in_box); } // http://crbug.com/841363
diff --git a/third_party/blink/renderer/core/editing/local_caret_rect_test.cc b/third_party/blink/renderer/core/editing/local_caret_rect_test.cc index 562f569..a38033d 100644 --- a/third_party/blink/renderer/core/editing/local_caret_rect_test.cc +++ b/third_party/blink/renderer/core/editing/local_caret_rect_test.cc
@@ -972,4 +972,21 @@ PositionWithAffinity(position, TextAffinity::kDownstream))); } +// https://crbug.com/936988 +TEST_P(ParameterizedLocalCaretRectTest, AfterIneditableInline) { + // For LayoutNG, we also enable EditingNG to test NG caret rendering. + ScopedEditingNGForTest editing_ng(LayoutNGEnabled()); + + LoadAhem(); + InsertStyleElement("div { font: 10px/10px Ahem }"); + SetBodyContent( + "<div contenteditable><span contenteditable=\"false\">foo</span></div>"); + const Element* div = GetDocument().QuerySelector("div"); + const Node* text = div->firstChild()->firstChild(); + + const Position position = Position::LastPositionInNode(*div); + EXPECT_EQ(LocalCaretRect(text->GetLayoutObject(), LayoutRect(30, 0, 1, 10)), + LocalCaretRectOfPosition(PositionWithAffinity(position))); +} + } // namespace blink
diff --git a/third_party/blink/renderer/core/html/html_plugin_element.cc b/third_party/blink/renderer/core/html/html_plugin_element.cc index 97034ac..b0d373d 100644 --- a/third_party/blink/renderer/core/html/html_plugin_element.cc +++ b/third_party/blink/renderer/core/html/html_plugin_element.cc
@@ -483,8 +483,9 @@ // Needs to load the plugin immediatedly because this function is called // when JavaScript code accesses the plugin. // FIXME: Check if dispatching events here is safe. - GetDocument().UpdateStyleAndLayoutIgnorePendingStylesheets( - Document::kRunPostLayoutTasksSynchronously); + GetDocument().UpdateStyleAndLayoutIgnorePendingStylesheets(); + GetDocument().View()->FlushAnyPendingPostLayoutTasks(); + return ExistingLayoutEmbeddedContent(); }
diff --git a/third_party/blink/renderer/core/input/event_handler.cc b/third_party/blink/renderer/core/input/event_handler.cc index 1dc75d8..965e7a9 100644 --- a/third_party/blink/renderer/core/input/event_handler.cc +++ b/third_party/blink/renderer/core/input/event_handler.cc
@@ -748,20 +748,6 @@ mouse_event_manager_->SetCapturesDragging(false); } - // If the hit testing originally determined the event was in a scrollbar, - // refetch the MouseEventWithHitTestResults in case the scrollbar - // EmbeddedContentView was destroyed when the mouse event was handled. - if (mev.GetScrollbar()) { - if (mev.GetScrollbar() == last_scrollbar_under_mouse_.Get()) { - HitTestRequest read_only_request(HitTestRequest::kReadOnly | - HitTestRequest::kActive); - mev = frame_->GetDocument()->PerformMouseEventHitTest( - read_only_request, document_point, mouse_event); - if (mev.GetScrollbar() != last_scrollbar_under_mouse_.Get()) - last_scrollbar_under_mouse_ = nullptr; - } - } - // Scrollbars should get events anyway, even disabled controls might be // scrollable. if (PassMousePressEventToScrollbar(mev))
diff --git a/third_party/blink/renderer/core/inspector/v8_inspector_string.cc b/third_party/blink/renderer/core/inspector/v8_inspector_string.cc index 1738fed..83f403fc 100644 --- a/third_party/blink/renderer/core/inspector/v8_inspector_string.cc +++ b/third_party/blink/renderer/core/inspector/v8_inspector_string.cc
@@ -90,6 +90,11 @@ builder.Append('"'); } +// static +String StringUtil::fromUTF16(const uint16_t* data, size_t length) { + return String(reinterpret_cast<const UChar*>(data), length); +} + namespace { class BinaryBasedOnSharedBuffer : public Binary::Impl { public:
diff --git a/third_party/blink/renderer/core/inspector/v8_inspector_string.h b/third_party/blink/renderer/core/inspector/v8_inspector_string.h index 483d07b..b1d3281 100644 --- a/third_party/blink/renderer/core/inspector/v8_inspector_string.h +++ b/third_party/blink/renderer/core/inspector/v8_inspector_string.h
@@ -17,7 +17,6 @@ #include "third_party/blink/renderer/platform/wtf/text/string_builder.h" #include "third_party/blink/renderer/platform/wtf/text/string_hash.h" #include "third_party/blink/renderer/platform/wtf/text/string_to_number.h" -#include "third_party/blink/renderer/platform/wtf/text/string_utf8_adaptor.h" #include "third_party/blink/renderer/platform/wtf/text/string_view.h" #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" #include "v8/include/v8-inspector.h" @@ -39,7 +38,6 @@ using String = WTF::String; using StringBuilder = WTF::StringBuilder; -using StringUTF8Adapter = WTF::StringUTF8Adaptor; struct ProtocolMessage { String json; @@ -91,6 +89,17 @@ static String fromUTF8(const uint8_t* data, size_t length) { return String::FromUTF8(reinterpret_cast<const char*>(data), length); } + + static String fromUTF16(const uint16_t* data, size_t length); + + static const uint8_t* CharactersLatin1(const String& s) { + return reinterpret_cast<const uint8_t*>(s.Characters8()); + } + static const uint8_t* CharactersUTF8(const String& s) { return nullptr; } + static const uint16_t* CharactersUTF16(const String& s) { + return reinterpret_cast<const uint16_t*>(s.Characters16()); + } + static size_t CharacterCount(const String& s) { return s.length(); } }; // A read-only sequence of uninterpreted bytes with reference-counted storage.
diff --git a/third_party/blink/renderer/core/page/page.cc b/third_party/blink/renderer/core/page/page.cc index 974d4af..926b3bb 100644 --- a/third_party/blink/renderer/core/page/page.cc +++ b/third_party/blink/renderer/core/page/page.cc
@@ -21,6 +21,7 @@ #include "third_party/blink/renderer/core/page/page.h" +#include "base/debug/stack_trace.h" #include "third_party/blink/public/platform/platform.h" #include "third_party/blink/public/platform/web_layer_tree_view.h" #include "third_party/blink/public/web/blink.h"
diff --git a/third_party/blink/renderer/core/paint/fragment_data.cc b/third_party/blink/renderer/core/paint/fragment_data.cc index 8b10ff11..9b5f209 100644 --- a/third_party/blink/renderer/core/paint/fragment_data.cc +++ b/third_party/blink/renderer/core/paint/fragment_data.cc
@@ -6,8 +6,6 @@ #include "third_party/blink/renderer/core/paint/paint_layer.h" #include "third_party/blink/renderer/platform/graphics/paint/geometry_mapper.h" -#include "base/debug/stack_trace.h" - namespace blink { // These are defined here because of PaintLayer dependency.
diff --git a/third_party/blink/renderer/core/style/computed_style.cc b/third_party/blink/renderer/core/style/computed_style.cc index d5428ac..152e7ec1 100644 --- a/third_party/blink/renderer/core/style/computed_style.cc +++ b/third_party/blink/renderer/core/style/computed_style.cc
@@ -2022,12 +2022,12 @@ Color ComputedStyle::VisitedDependentColor( const CSSProperty& color_property) const { Color unvisited_color = - ToLonghand(color_property).ColorIncludingFallback(false, *this); + To<Longhand>(color_property).ColorIncludingFallback(false, *this); if (InsideLink() != EInsideLink::kInsideVisitedLink) return unvisited_color; Color visited_color = - ToLonghand(color_property).ColorIncludingFallback(true, *this); + To<Longhand>(color_property).ColorIncludingFallback(true, *this); // Take the alpha from the unvisited color, but get the RGB values from the // visited color.
diff --git a/third_party/blink/renderer/core/svg/svg_fe_convolve_matrix_element.idl b/third_party/blink/renderer/core/svg/svg_fe_convolve_matrix_element.idl index d2a4737..e628d4a 100644 --- a/third_party/blink/renderer/core/svg/svg_fe_convolve_matrix_element.idl +++ b/third_party/blink/renderer/core/svg/svg_fe_convolve_matrix_element.idl
@@ -45,10 +45,6 @@ [MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedEnumeration edgeMode; [MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedNumber kernelUnitLengthX; [MeasureAs=SVG1DOMFilter] readonly attribute SVGAnimatedNumber kernelUnitLengthY; - - // TODO(foolip): The following was part of SVG 1.1. https://crbug.com/695977 - // http://www.w3.org/TR/SVG11/filters.html#InterfaceSVGFEConvolveMatrixElement - // https://github.com/w3c/fxtf-drafts/issues/114 [Measure] readonly attribute SVGAnimatedBoolean preserveAlpha; };
diff --git a/third_party/blink/renderer/core/testing/internals.cc b/third_party/blink/renderer/core/testing/internals.cc index 446e343..9c6a8da 100644 --- a/third_party/blink/renderer/core/testing/internals.cc +++ b/third_party/blink/renderer/core/testing/internals.cc
@@ -2664,8 +2664,8 @@ "The node provided is neither a document nor an IFrame."); return; } - document->UpdateStyleAndLayoutIgnorePendingStylesheets( - Document::kRunPostLayoutTasksSynchronously); + document->UpdateStyleAndLayoutIgnorePendingStylesheets(); + document->View()->FlushAnyPendingPostLayoutTasks(); } void Internals::forceFullRepaint(Document* document,
diff --git a/third_party/blink/renderer/modules/accessibility/ax_layout_object.cc b/third_party/blink/renderer/modules/accessibility/ax_layout_object.cc index ad546bef..2c095e348 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_layout_object.cc +++ b/third_party/blink/renderer/modules/accessibility/ax_layout_object.cc
@@ -3166,18 +3166,64 @@ return ax::mojom::SortDirection::kOther; } -static ax::mojom::Role DecideRoleFromSibling(LayoutTableCell* sibling_cell) { - if (!sibling_cell) +static bool IsNonEmptyNonHeaderCell(LayoutTableCell* cell) { + if (!cell) + return false; + + if (Node* node = cell->GetNode()) + return node->hasChildren() && node->HasTagName(kTdTag); + + return false; +} + +static bool IsHeaderCell(LayoutTableCell* cell) { + if (!cell) + return false; + + if (Node* node = cell->GetNode()) + return node->HasTagName(kThTag); + + return false; +} + +static ax::mojom::Role DecideRoleFromSiblings(LayoutTableCell* cell) { + if (!IsHeaderCell(cell)) return ax::mojom::Role::kCell; - if (Node* sibling_node = sibling_cell->GetNode()) { - if (sibling_node->HasTagName(kThTag)) - return ax::mojom::Role::kColumnHeader; - if (sibling_node->HasTagName(kTdTag)) - return ax::mojom::Role::kRowHeader; - } + // If this header is only cell in its row, it is a column header. + // It is also a column header if it has a header on either side of it. + // If instead it has a non-empty td element next to it, it is a row header. + LayoutTableCell* next_cell = cell->NextCell(); + LayoutTableCell* previous_cell = cell->PreviousCell(); + if (!next_cell && !previous_cell) + return ax::mojom::Role::kColumnHeader; + if (IsHeaderCell(next_cell) && IsHeaderCell(previous_cell)) + return ax::mojom::Role::kColumnHeader; + if (IsNonEmptyNonHeaderCell(next_cell) || + IsNonEmptyNonHeaderCell(previous_cell)) + return ax::mojom::Role::kRowHeader; - return ax::mojom::Role::kCell; + LayoutTableRow* layout_row = cell->Row(); + DCHECK(layout_row); + + // If this row's first or last cell is a non-empty td, this is a row header. + // Do the same check for the second and second-to-last cells because tables + // often have an empty cell at the intersection of the row and column headers. + LayoutTableCell* first_cell = layout_row->FirstCell(); + DCHECK(first_cell); + + LayoutTableCell* last_cell = layout_row->LastCell(); + DCHECK(last_cell); + + if (IsNonEmptyNonHeaderCell(first_cell) || IsNonEmptyNonHeaderCell(last_cell)) + return ax::mojom::Role::kRowHeader; + + if (IsNonEmptyNonHeaderCell(first_cell->NextCell()) || + IsNonEmptyNonHeaderCell(last_cell->PreviousCell())) + return ax::mojom::Role::kRowHeader; + + // We have no evidence that this is not a column header. + return ax::mojom::Role::kColumnHeader; } ax::mojom::Role AXLayoutObject::DetermineTableRowRole() const { @@ -3228,23 +3274,7 @@ EqualIgnoringASCIICase(scope, "colgroup")) return ax::mojom::Role::kColumnHeader; - // Check the previous cell and the next cell on the same row. - LayoutTableCell* layout_cell = ToLayoutTableCell(layout_object_); - ax::mojom::Role header_role = ax::mojom::Role::kCell; - // if header is preceded by header cells on the same row, then it is a - // column header. If it is preceded by other cells then it's a row header. - if ((header_role = DecideRoleFromSibling(layout_cell->PreviousCell())) != - ax::mojom::Role::kCell) - return header_role; - - // if header is followed by header cells on the same row, then it is a - // column header. If it is followed by other cells then it's a row header. - if ((header_role = DecideRoleFromSibling(layout_cell->NextCell())) != - ax::mojom::Role::kCell) - return header_role; - - // If there are no other cells on that row, then it is a column header. - return ax::mojom::Role::kColumnHeader; + return DecideRoleFromSiblings(ToLayoutTableCell(layout_object_)); } AXObject* AXLayoutObject::CellForColumnAndRow(unsigned target_column_index,
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_coding_parameters.idl b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_coding_parameters.idl index ba67415..d16a03ab 100644 --- a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_coding_parameters.idl +++ b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_coding_parameters.idl
@@ -4,5 +4,5 @@ // https://w3c.github.io/webrtc-pc/#rtcrtpcodingparameters dictionary RTCRtpCodingParameters { - //TODO(orphis): Missing rid. https://crbug.com/857034 -}; \ No newline at end of file + DOMString rid; +};
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.cc b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.cc index b8131ec..2d258c86 100644 --- a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.cc +++ b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.cc
@@ -100,6 +100,15 @@ if (parameters->hasEncodings()) { if (parameters->encodings().size() != new_parameters->encodings().size()) return true; + + for (wtf_size_t i = 0; i < parameters->encodings().size(); ++i) { + const auto& encoding = parameters->encodings()[i]; + const auto& new_encoding = new_parameters->encodings()[i]; + if (encoding->hasRid() != new_encoding->hasRid() || + (encoding->hasRid() && encoding->rid() != new_encoding->rid())) { + return true; + } + } } if (parameters->hasHeaderExtensions() != @@ -244,9 +253,11 @@ webrtc::RtpEncodingParameters ToRtpEncodingParameters( const RTCRtpEncodingParameters* encoding) { // TODO(orphis): Forward missing fields from the WebRTC library: - // codecPayloadType, dtx, ptime, maxFramerate, scaleResolutionDownBy, - // rid + // codecPayloadType, dtx, ptime, maxFramerate, scaleResolutionDownBy. webrtc::RtpEncodingParameters webrtc_encoding; + if (encoding->hasRid()) { + webrtc_encoding.rid = WebString(encoding->rid()).Utf8(); + } webrtc_encoding.active = encoding->active(); webrtc_encoding.bitrate_priority = PriorityToDouble(encoding->priority()); webrtc_encoding.network_priority = @@ -359,8 +370,9 @@ SafeCast<wtf_size_t>(webrtc_parameters->encodings.size())); for (const auto& webrtc_encoding : webrtc_parameters->encodings) { // TODO(orphis): Forward missing fields from the WebRTC library: - // codecPayloadType, dtx, ptime, maxFramerate, scaleResolutionDownBy, rid + // codecPayloadType, dtx, ptime, maxFramerate, scaleResolutionDownBy. RTCRtpEncodingParameters* encoding = RTCRtpEncodingParameters::Create(); + encoding->setRid(WebString::FromUTF8(webrtc_encoding.rid)); encoding->setActive(webrtc_encoding.active); if (webrtc_encoding.max_bitrate_bps) { encoding->setMaxBitrate(webrtc_encoding.max_bitrate_bps.value());
diff --git a/third_party/blink/renderer/platform/fonts/shaping/shape_result.cc b/third_party/blink/renderer/platform/fonts/shaping/shape_result.cc index 4c7f862..155408d 100644 --- a/third_party/blink/renderer/platform/fonts/shaping/shape_result.cc +++ b/third_party/blink/renderer/platform/fonts/shaping/shape_result.cc
@@ -1276,9 +1276,10 @@ float ShapeResult::LineLeftBounds() const { DCHECK(!runs_.IsEmpty()); const RunInfo& run = *runs_.front(); + if (run.glyph_data_.IsEmpty()) + return 0.0f; const bool is_horizontal_run = run.IsHorizontal(); const SimpleFontData& font_data = *run.font_data_; - DCHECK(!run.glyph_data_.IsEmpty()) << *this; const unsigned character_index = run.glyph_data_.front().character_index; GlyphBoundsAccumulator bounds(0.f); for (const auto& glyph : run.glyph_data_) { @@ -1297,9 +1298,10 @@ float ShapeResult::LineRightBounds() const { DCHECK(!runs_.IsEmpty()); const RunInfo& run = *runs_.back(); + if (run.glyph_data_.IsEmpty()) + return 0.0f; const bool is_horizontal_run = run.IsHorizontal(); const SimpleFontData& font_data = *run.font_data_; - DCHECK(!run.glyph_data_.IsEmpty()) << *this; const unsigned character_index = run.glyph_data_.back().character_index; GlyphBoundsAccumulator bounds(width_); for (const auto& glyph : base::Reversed(run.glyph_data_)) { @@ -1379,7 +1381,6 @@ : target->EndIndex() - std::max(start_offset, StartIndex()); unsigned target_run_size_before = target->runs_.size(); float total_width = 0; - //run_index = 0; for (; run_index < runs_.size(); run_index++) { const auto& run = runs_[run_index]; unsigned run_start = run->start_index_;
diff --git a/third_party/blink/renderer/platform/geometry/length_functions.cc b/third_party/blink/renderer/platform/geometry/length_functions.cc index ce385e4..6aef97e 100644 --- a/third_party/blink/renderer/platform/geometry/length_functions.cc +++ b/third_party/blink/renderer/platform/geometry/length_functions.cc
@@ -60,11 +60,9 @@ return 0; } -LayoutUnit MinimumValueForLength(const Length& length, - LayoutUnit maximum_value) { +LayoutUnit MinimumValueForLengthInternal(const Length& length, + LayoutUnit maximum_value) { switch (length.GetType()) { - case Length::kFixed: - return LayoutUnit(length.Value()); case Length::kPercent: // Don't remove the extra cast to float. It is needed for rounding on // 32-bit Intel machines that use the FPU stack. @@ -75,6 +73,7 @@ case Length::kFillAvailable: case Length::kAuto: return LayoutUnit(); + case Length::kFixed: case Length::kMinContent: case Length::kMaxContent: case Length::kFitContent:
diff --git a/third_party/blink/renderer/platform/geometry/length_functions.h b/third_party/blink/renderer/platform/geometry/length_functions.h index e72752c..1612b98 100644 --- a/third_party/blink/renderer/platform/geometry/length_functions.h +++ b/third_party/blink/renderer/platform/geometry/length_functions.h
@@ -24,6 +24,8 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GEOMETRY_LENGTH_FUNCTIONS_H_ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GEOMETRY_LENGTH_FUNCTIONS_H_ +#include "third_party/blink/renderer/platform/geometry/layout_unit.h" +#include "third_party/blink/renderer/platform/geometry/length.h" #include "third_party/blink/renderer/platform/platform_export.h" namespace blink { @@ -38,8 +40,17 @@ PLATFORM_EXPORT int IntValueForLength(const Length&, int maximum_value); PLATFORM_EXPORT float FloatValueForLength(const Length&, float maximum_value); -PLATFORM_EXPORT LayoutUnit MinimumValueForLength(const Length&, - LayoutUnit maximum_value); +PLATFORM_EXPORT LayoutUnit +MinimumValueForLengthInternal(const Length&, LayoutUnit maximum_value); + +inline LayoutUnit MinimumValueForLength(const Length& length, + LayoutUnit maximum_value) { + if (LIKELY(length.IsFixed())) + return LayoutUnit(length.Value()); + + return MinimumValueForLengthInternal(length, maximum_value); +} + PLATFORM_EXPORT LayoutUnit ValueForLength(const Length&, LayoutUnit maximum_value); PLATFORM_EXPORT FloatSize FloatSizeForLengthSize(const LengthSize&,
diff --git a/third_party/blink/renderer/platform/graphics/decoding_image_generator.cc b/third_party/blink/renderer/platform/graphics/decoding_image_generator.cc index db1c46b..ea80294 100644 --- a/third_party/blink/renderer/platform/graphics/decoding_image_generator.cc +++ b/third_party/blink/renderer/platform/graphics/decoding_image_generator.cc
@@ -181,9 +181,18 @@ // Convert the color type to the requested one if necessary if (decoded && target_info.colorType() != dst_info.colorType()) { - decoded = SkPixmap{target_info, memory, adjusted_row_bytes}.readPixels( - SkPixmap{dst_info, pixels, row_bytes}); + auto canvas = SkCanvas::MakeRasterDirect(dst_info, pixels, row_bytes); + DCHECK(canvas); + SkPaint paint; + if (dst_info.colorType() == kARGB_4444_SkColorType || + dst_info.colorType() == kRGB_565_SkColorType) { + paint.setDither(true); + } + paint.setBlendMode(SkBlendMode::kSrc); + SkBitmap bitmap; + decoded = bitmap.installPixels(target_info, memory, adjusted_row_bytes); DCHECK(decoded); + canvas->drawBitmap(bitmap, 0, 0, &paint); } return decoded; }
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc index a178d3c..559bba3d 100644 --- a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc +++ b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.cc
@@ -8,7 +8,6 @@ #include <utility> #include "base/bind.h" -#include "base/debug/stack_trace.h" #include "base/feature_list.h" #include "base/logging.h" #include "base/metrics/field_trial_params.h"
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index 07b6369..7a41bb3d 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -2032,8 +2032,17 @@ crbug.com/876732 [ Win ] fast/dom/HTMLImageElement/image-srcset-w-onerror.html [ Failure Pass ] -# The test will pass once PassiveDocumentWheelEventListeners is enabled by default. -crbug.com/626196 external/wpt/dom/events/document-level-wheel-event-listener-passive-by-default-manual.html [ Failure ] +# These tests only pass with --enable-threaded-compositing. +crbug.com/770028 external/wpt/dom/events/document-level-wheel-event-listener-passive-by-default-manual.html [ Skip ] +crbug.com/770028 external/wpt/dom/events/document-level-touchmove-event-listener-passive-by-default.html [ Skip ] + +# Only virtual/threaded version of these tests pass (or running them with --enable-threaded-compositing). +crbug.com/936891 fast/scrolling/document-level-touchmove-event-listener-passive-by-default.html [ Skip ] +crbug.com/936891 virtual/scroll_customization/fast/scrolling/document-level-touchmove-event-listener-passive-by-default.html [ Skip ] +crbug.com/936891 virtual/fractional_scrolling/fast/scrolling/document-level-touchmove-event-listener-passive-by-default.html [ Skip ] +crbug.com/936891 fast/scrolling/document-level-wheel-event-listener-passive-by-default.html [ Skip ] +crbug.com/936891 virtual/scroll_customization/fast/scrolling/document-level-wheel-event-listener-passive-by-default.html [ Skip ] +crbug.com/936891 virtual/fractional_scrolling/fast/scrolling/document-level-wheel-event-listener-passive-by-default.html [ Skip ] crbug.com/597221 fast/dom/Window/window-postmessage-clone-deep-array.html [ Failure ] crbug.com/597221 virtual/user-activation-v2/fast/dom/Window/window-postmessage-clone-deep-array.html [ Failure ] @@ -2922,7 +2931,6 @@ crbug.com/849859 external/wpt/css/css-animations/CSSAnimation-pausing.tentative.html [ Failure ] crbug.com/849859 external/wpt/css/css-animations/Element-getAnimations-dynamic-changes.tentative.html [ Failure ] crbug.com/849859 external/wpt/web-animations/timing-model/animations/pausing-an-animation.html [ Failure ] -crbug.com/875622 external/wpt/css/css-animations/AnimationEffect-getComputedTiming.tentative.html [ Pass Failure ] crbug.com/875622 external/wpt/css/css-transitions/AnimationEffect-getComputedTiming.tentative.html [ Pass Failure ] crbug.com/552085 external/wpt/css/css-cascade/important-prop.html [ Failure ] @@ -5941,8 +5949,6 @@ crbug.com/915352 [ Mac10.10 Mac10.11 ] virtual/threaded/external/wpt/animation-worklet/worklet-animation-with-scroll-timeline-and-display-none.https.html [ Pass Failure ] # Sheriff 2019-03-01 -crbug.com/937215 [ Linux ] media/controls/modern/doubletap-to-jump-forwards.html [ Pass Failure ] -crbug.com/937215 [ Linux ] virtual/video-surface-layer/media/controls/modern/doubletap-to-jump-forwards.html [ Pass Failure ] crbug.com/937170 [ Linux Win7 ] external/wpt/IndexedDB/interleaved-cursors-large.html [ Pass Timeout Crash ] crbug.com/937312 [ Win7 ] external/wpt/background-fetch/fetch.https.window.html [ Pass Timeout ] crbug.com/893659 [ Mac ] virtual/threaded/fast/events/pointerevents/pinch/pointerevent_touch-action-pinch_zoom_touch.html [ Pass Failure Crash ] @@ -5960,3 +5966,7 @@ crbug.com/937811 [ Linux Release ] http/tests/devtools/elements/shadow/elements-panel-shadow-selection-on-refresh-3.js [ Pass Failure ] crbug.com/937811 [ Win Release ] http/tests/devtools/elements/shadow/elements-panel-shadow-selection-on-refresh-2.js [ Pass Failure ] crbug.com/937811 [ Win Release ] http/tests/devtools/elements/shadow/elements-panel-shadow-selection-on-refresh-3.js [ Pass Failure ] +crbug.com/935689 [ Linux Debug ] external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/counter-styles-3/symbols-function.html [ Failure Pass ] +crbug.com/937858 [ Debug ] external/wpt/ambient-light/AmbientLightSensor.https.html [ Pass Failure ] +crbug.com/937902 [ Linux Debug ] virtual/disable-blink-gen-property-trees/compositing/overflow/overflow-scroll-with-local-background.html [ Pass Failure ] +crbug.com/937991 [ Win7 Release ] http/tests/devtools/cache-storage/cache-data.js [ Pass Timeout ]
diff --git a/third_party/blink/web_tests/W3CImportExpectations b/third_party/blink/web_tests/W3CImportExpectations index 7c91bd1f5..94fb8ec 100644 --- a/third_party/blink/web_tests/W3CImportExpectations +++ b/third_party/blink/web_tests/W3CImportExpectations
@@ -153,10 +153,28 @@ # The wpt tools (including manifest and wptserve) are checked in to # blinkpy/third_party/wpt so that we can manually update them and keep -# a stable pinned version. -external/wpt/tools [ Skip ] -external/wpt/wpt [ Skip ] -external/wpt/wpt.py [ Skip ] +# a stable pinned version. This manual import supports the legacy layout +# test runner (run_web_tests). +# The tools directory is also automatically imported alongside the tests +# in order to run wptrunner in the Chromium CQ. The following exceptions +# are for directories we don't need. +external/wpt/tools/ci/tests [ Skip ] +external/wpt/tools/gitignore/tests [ Skip ] +external/wpt/tools/lint/tests [ Skip ] +external/wpt/tools/manifest/tests [ Skip ] +external/wpt/tools/pywebsocket/example [ Skip ] +external/wpt/tools/pywebsocket/tests [ Skip ] +external/wpt/tools/scripts [ Skip ] +external/wpt/tools/wpt/tests [ Skip ] +external/wpt/tools/wptrunner/docs [ Skip ] +external/wpt/tools/wptrunner/test [ Skip ] +external/wpt/tools/wptrunner/wptrunner/browsers/sauce_setup [ Skip ] +external/wpt/tools/wptrunner/wptrunner/tests [ Skip ] +external/wpt/tools/wptserve/docs [ Skip ] +external/wpt/tools/wptserve/tests [ Skip ] +# These two files contain comments that look like version control markers +external/wpt/tools/third_party/hyper/hyper/packages/rfc3986/__init__.py [ Skip ] +external/wpt/tools/third_party/pytest/src/_pytest/_argcomplete.py [ Skip ] # The outputs of these tests contain random values generated by token() # in common/utils.js. These could be imported if the results for
diff --git a/third_party/blink/web_tests/accessibility/table-header-column-row-expected.txt b/third_party/blink/web_tests/accessibility/table-header-column-row-expected.txt index 0a030178..093399882 100644 --- a/third_party/blink/web_tests/accessibility/table-header-column-row-expected.txt +++ b/third_party/blink/web_tests/accessibility/table-header-column-row-expected.txt
@@ -3,8 +3,8 @@ col head data row head row head data col head row header and column header (1) -data row head column head -column head column head data +data row head row head +row head row head data row head data row head row header and column header (2) row head data data @@ -70,16 +70,16 @@ AXRole: AXRowHeader "row head" AXRole: AXStaticText "row head" AXRole: AXInlineTextBox "row head" - AXRole: AXColumnHeader "column head" - AXRole: AXStaticText "column head" - AXRole: AXInlineTextBox "column head" + AXRole: AXRowHeader "row head" + AXRole: AXStaticText "row head" + AXRole: AXInlineTextBox "row head" AXRole: AXRow - AXRole: AXColumnHeader "column head" - AXRole: AXStaticText "column head" - AXRole: AXInlineTextBox "column head" - AXRole: AXColumnHeader "column head" - AXRole: AXStaticText "column head" - AXRole: AXInlineTextBox "column head" + AXRole: AXRowHeader "row head" + AXRole: AXStaticText "row head" + AXRole: AXInlineTextBox "row head" + AXRole: AXRowHeader "row head" + AXRole: AXStaticText "row head" + AXRole: AXInlineTextBox "row head" AXRole: AXCell "data" AXRole: AXStaticText "data" AXRole: AXInlineTextBox "data"
diff --git a/third_party/blink/web_tests/accessibility/table-header-column-row.html b/third_party/blink/web_tests/accessibility/table-header-column-row.html index 0f4df90..8a488e1a 100644 --- a/third_party/blink/web_tests/accessibility/table-header-column-row.html +++ b/third_party/blink/web_tests/accessibility/table-header-column-row.html
@@ -27,11 +27,11 @@ <tr> <td>data</td> <th>row head</th> - <th>column head</th> + <th>row head</th> </tr> <tr> - <th>column head</th> - <th>column head</th> + <th>row head</th> + <th>row head</th> <td>data</td> </tr> <tr>
diff --git a/third_party/blink/web_tests/accessibility/table-headers-expected.txt b/third_party/blink/web_tests/accessibility/table-headers-expected.txt index 3c5d70e..6fb6558 100644 --- a/third_party/blink/web_tests/accessibility/table-headers-expected.txt +++ b/third_party/blink/web_tests/accessibility/table-headers-expected.txt
@@ -7,8 +7,8 @@ col head data row head row head data col head row header and column header (1) -data row head column head -column head column head data +data row head row head +row head row head data row head data row head row header and column header (2) row head data data @@ -53,14 +53,8 @@ PASS table2.columnHeaderAtIndex(2).isEqual(table2.cellForColumnAndRow(0, 1)) is true PASS table2.columnHeaderAtIndex(3).isEqual(table2.cellForColumnAndRow(2, 2)) is true PASS table2.columnHeadersCount is 4 -PASS table3.rowHeaderAtIndex(0).isEqual(table3.cellForColumnAndRow(1, 0)) is true -PASS table3.rowHeaderAtIndex(1).isEqual(table3.cellForColumnAndRow(0, 2)) is true -PASS table3.rowHeaderAtIndex(2).isEqual(table3.cellForColumnAndRow(2, 2)) is true -PASS table3.rowHeadersCount is 3 -PASS table3.columnHeaderAtIndex(0).isEqual(table3.cellForColumnAndRow(2, 0)) is true -PASS table3.columnHeaderAtIndex(1).isEqual(table3.cellForColumnAndRow(0, 1)) is true -PASS table3.columnHeaderAtIndex(2).isEqual(table3.cellForColumnAndRow(1, 1)) is true -PASS table3.columnHeadersCount is 3 +PASS table3.rowHeadersCount is 6 +PASS table3.columnHeadersCount is 0 PASS table4.rowHeaderAtIndex(0).isEqual(table4.cellForColumnAndRow(0, 0)) is true PASS table4.rowHeadersCount is 1 PASS table4.columnHeaderAtIndex(0).isEqual(table4.cellForColumnAndRow(0, 1)) is true
diff --git a/third_party/blink/web_tests/accessibility/table-headers.html b/third_party/blink/web_tests/accessibility/table-headers.html index 936ba9d..d26cbcd8 100644 --- a/third_party/blink/web_tests/accessibility/table-headers.html +++ b/third_party/blink/web_tests/accessibility/table-headers.html
@@ -60,11 +60,11 @@ <tr> <td>data</td> <th>row head</th> - <th>column head</th> + <th>row head</th> </tr> <tr> - <th>column head</th> - <th>column head</th> + <th>row head</th> + <th>row head</th> <td>data</td> </tr> <tr> @@ -184,15 +184,9 @@ var table3 = accessibilityController.accessibleElementById("table3"); // Row headers - shouldBeTrue("table3.rowHeaderAtIndex(0).isEqual(table3.cellForColumnAndRow(1, 0))"); - shouldBeTrue("table3.rowHeaderAtIndex(1).isEqual(table3.cellForColumnAndRow(0, 2))"); - shouldBeTrue("table3.rowHeaderAtIndex(2).isEqual(table3.cellForColumnAndRow(2, 2))"); - shouldBe("table3.rowHeadersCount", "3"); + shouldBe("table3.rowHeadersCount", "6"); // Column headers - shouldBeTrue("table3.columnHeaderAtIndex(0).isEqual(table3.cellForColumnAndRow(2, 0))"); - shouldBeTrue("table3.columnHeaderAtIndex(1).isEqual(table3.cellForColumnAndRow(0, 1))"); - shouldBeTrue("table3.columnHeaderAtIndex(2).isEqual(table3.cellForColumnAndRow(1, 1))"); - shouldBe("table3.columnHeadersCount", "3"); + shouldBe("table3.columnHeadersCount", "0"); var table4 = accessibilityController.accessibleElementById("table4"); // Row headers
diff --git a/third_party/blink/web_tests/external/wpt/IndexedDB/bindings-inject-key.html b/third_party/blink/web_tests/external/wpt/IndexedDB/bindings-inject-key.html index 821b009..72edc91 100644 --- a/third_party/blink/web_tests/external/wpt/IndexedDB/bindings-inject-key.html +++ b/third_party/blink/web_tests/external/wpt/IndexedDB/bindings-inject-key.html
@@ -21,6 +21,9 @@ configurable: true, set: t.step_func((value) => { setter_called = true; }), }); + t.add_cleanup(function() { + delete Object.prototype['10']; + }); request.onerror = t.unreached_func('request should not fail'); request.onsuccess = t.step_func(() => { const result = request.result; @@ -31,8 +34,6 @@ 'Result should have own-property overriding prototype setter.'); assert_equals(result[10], 'key', 'Result should have expected property.'); - - delete Object.prototype['10']; t.done(); }); }, @@ -53,6 +54,9 @@ configurable: true, set: t.step_func(function(value) { setter_called = true; }), }); + t.add_cleanup(function() { + delete Object.prototype['id']; + }); request.onerror = t.unreached_func('request should not fail'); request.onsuccess = t.step_func(function() { const result = request.result; @@ -63,8 +67,6 @@ 'Result should have own-property overriding prototype setter.'); assert_equals(result.id, 1, 'Own property should match primary key generator value'); - - delete Object.prototype['id']; t.done(); }); }, @@ -81,6 +83,11 @@ const request = tx.objectStore('store').get(1); Object.prototype.a = {b: {c: 'on proto'}}; + t.add_cleanup(function() { + delete Object.prototype.a; + }); + assert_equals(Object.prototype.a.b.c, 'on proto', + 'Prototype should be configured for test'); request.onerror = t.unreached_func('request should not fail'); request.onsuccess = t.step_func(function() { @@ -94,7 +101,7 @@ assert_equals(result.a.b.c, 1, 'Own property should match primary key generator value'); assert_equals(Object.prototype.a.b.c, 'on proto', - 'Prototype should not be modified'); + 'Prototype should not be modified'); t.done(); }); },
diff --git a/third_party/blink/web_tests/external/wpt/dom/events/document-level-touchmove-event-listener-passive-by-default.html b/third_party/blink/web_tests/external/wpt/dom/events/document-level-touchmove-event-listener-passive-by-default.html new file mode 100644 index 0000000..f3f0d58 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/dom/events/document-level-touchmove-event-listener-passive-by-default.html
@@ -0,0 +1,73 @@ +<!DOCTYPE html> +<title>Default passive document level touchmove event listener test</title> +<link rel="help" href="https://github.com/WICG/interventions/issues/35"> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="/resources/testdriver.js"></script> +<script src="/resources/testdriver-actions.js"></script> +<script src="/resources/testdriver-vendor.js"></script> +<body onload=runTest()> +<div id="touchDiv"> +</div> +</body> +<style> +#touchDiv { + width: 100px; + height: 100px; +} +</style> +<script> +var touch_div = document.getElementById("touchDiv"); +var cancelable = true; +var touch_move_arrived = false; +document.addEventListener("touchmove", function (event) { + cancelable = event.cancelable; + touch_move_arrived = true; + event.preventDefault(); +}); + +function waitFor(condition) { + const MAX_FRAME = 500; + return new Promise((resolve, reject) => { + function tick(frames) { + // We requestAnimationFrame either for 500 frames or until condition is + // met. + if (frames >= MAX_FRAME) + reject("Condition did not become true after 500 frames"); + else if (condition()) + resolve(); + else + requestAnimationFrame(tick.bind(this, frames + 1)); + } + tick(0); + }); +} + +function waitForCompositorCommit() { + return new Promise((resolve) => { + // rAF twice. + window.requestAnimationFrame(() => { + window.requestAnimationFrame(resolve); + }); + }); +} + +function injectInput() { + new test_driver.Actions() + .addPointer("touch_pointer", "touch") + .pointerMove(0, 0, {origin: touch_div}) + .pointerDown() + .pointerMove(30, 30) + .pointerUp() + .send(); +} + +function runTest() { + promise_test (async () => { + await waitForCompositorCommit(); + injectInput(); + await waitFor(()=> { return touch_move_arrived; }); + assert_false(cancelable); + }, "Touchmove events are non-cancelable since the event listener is treated as passive."); +} +</script>
diff --git a/third_party/blink/web_tests/external/wpt/dom/events/document-level-wheel-event-listener-passive-by-default-manual.html b/third_party/blink/web_tests/external/wpt/dom/events/document-level-wheel-event-listener-passive-by-default-manual.html index c94d5b00..4fa67528 100644 --- a/third_party/blink/web_tests/external/wpt/dom/events/document-level-wheel-event-listener-passive-by-default-manual.html +++ b/third_party/blink/web_tests/external/wpt/dom/events/document-level-wheel-event-listener-passive-by-default-manual.html
@@ -3,15 +3,40 @@ <link rel="help" href="https://github.com/WICG/interventions/issues/64"> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> +<body onload=runTest()> <div>This is a manual test since there is no way to synthesize wheel events. Scroll by wheel in the middle of the page to run the test.</div> +</body> <script> -function testWheelCancelable(test) { - document.addEventListener("wheel", test.step_func(event => { - assert_false(event.cancelable, "Wheel event must be non-cancelable."); - test.done(); - })); +var cancelable = true; +var wheel_arrived = false; +document.addEventListener("wheel", function (event) { + cancelable = event.cancelable; + wheel_arrived = true; + event.preventDefault(); +}); + +function waitFor(condition) { + const MAX_FRAME = 200; + return new Promise((resolve, reject) => { + function tick(frames) { + // We requestAnimationFrame either for 200 frames or until condition is + // met. + if (frames >= MAX_FRAME) + reject("Condition did not become true after 200 frames"); + else if (condition()) + resolve(); + else + requestAnimationFrame(tick.bind(this, frames + 1)); + } + tick(0); + }); } -async_test(t => { testWheelCancelable(t); }, "Wheel events are " + - "non-cancelable since the event listener is treated as passive"); + +function runTest() { + promise_test (async () => { + await waitFor(()=> { return wheel_arrived; }); + assert_false(cancelable); + }, "Wheel events are non-cancelable since the event listener is treated as passive."); +} </script>
diff --git a/third_party/blink/web_tests/external/wpt/webrtc/RTCRtpParameters-encodings-expected.txt b/third_party/blink/web_tests/external/wpt/webrtc/RTCRtpParameters-encodings-expected.txt index ce30e45..c18ec3c8 100644 --- a/third_party/blink/web_tests/external/wpt/webrtc/RTCRtpParameters-encodings-expected.txt +++ b/third_party/blink/web_tests/external/wpt/webrtc/RTCRtpParameters-encodings-expected.txt
@@ -4,7 +4,7 @@ FAIL sender.getParameters() should return sendEncodings set by addTransceiver() promise_test: Unhandled rejection with value: object "InvalidAccessError: Failed to execute 'setRemoteDescription' on 'RTCPeerConnection': Failed to set remote answer sdp: Failed to set remote audio description send parameters." PASS sender.setParameters() with mismatch number of encodings should reject with InvalidModificationError PASS sender.setParameters() with encodings unset should reject with TypeError -FAIL setParameters() with modified encoding.rid field should reject with InvalidModificationError assert_equals: expected (string) "foo" but got (undefined) undefined +PASS setParameters() with modified encoding.rid field should reject with InvalidModificationError PASS setParameters() with encoding.scaleResolutionDownBy field set to less than 1.0 should reject with RangeError PASS setParameters() with encoding.scaleResolutionDownBy field set to greater than 1.0 should succeed FAIL setParameters() with modified encoding.dtx should succeed with RTCRtpTransceiverInit assert_equals: expected (string) "enabled" but got (undefined) undefined
diff --git a/third_party/blink/web_tests/external/wpt/webrtc/RTCRtpParameters-encodings.html b/third_party/blink/web_tests/external/wpt/webrtc/RTCRtpParameters-encodings.html index 23cb769..0d3d08a 100644 --- a/third_party/blink/web_tests/external/wpt/webrtc/RTCRtpParameters-encodings.html +++ b/third_party/blink/web_tests/external/wpt/webrtc/RTCRtpParameters-encodings.html
@@ -220,8 +220,8 @@ promise_test(async t => { const pc = new RTCPeerConnection(); t.add_cleanup(() => pc.close()); - const { sender } = pc.addTransceiver('audio', { - sendEncodings: [{ rid: 'foo' }], + const { sender } = pc.addTransceiver('video', { + sendEncodings: [{ rid: 'foo' }, { rid: 'baz' }], }); await doOfferAnswerExchange(t, pc);
diff --git a/third_party/blink/web_tests/external/wpt/webrtc/protocol/README.txt b/third_party/blink/web_tests/external/wpt/webrtc/protocol/README.txt index 062db854..1310717 100644 --- a/third_party/blink/web_tests/external/wpt/webrtc/protocol/README.txt +++ b/third_party/blink/web_tests/external/wpt/webrtc/protocol/README.txt
@@ -14,6 +14,8 @@ - draft-ietf-rtcweb-fec - draft-ietf-rtcweb-data-protocol - draft-ietf-rtcweb-data-channel +- draft-ietf-mmusic-sdp-simulcast +- draft-ietf-mmusic-rid - RFC 7742, "WebRTC Video Processing and Codec Requirements" - RFC 7874, "WebRTC Audio Codec and Processing Requirements"
diff --git a/third_party/blink/web_tests/external/wpt/webrtc/protocol/simulcast-offer.html b/third_party/blink/web_tests/external/wpt/webrtc/protocol/simulcast-offer.html new file mode 100644 index 0000000..77ae7f9 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/webrtc/protocol/simulcast-offer.html
@@ -0,0 +1,33 @@ +<!doctype html> +<meta charset=utf-8> +<title>RTCPeerConnection Simulcast Offer</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +'use strict'; + +// Tests for the construction of offers with simulcast according to: +// draft-ietf-mmusic-sdp-simulcast-13 +// draft-ietf-mmusic-rid-15 +promise_test(async t => { + const pc = new RTCPeerConnection(); + t.add_cleanup(() => pc.close()); + const expected_rids = ['foo', 'bar', 'baz']; + pc.addTransceiver('video', { + sendEncodings: expected_rids.map(rid => ({rid})) + }); + + const offer = await pc.createOffer(); + let offer_lines = offer.sdp.split('\r\n'); + // Check for a RID line for each layer. + for (const rid of expected_rids) { + let result = offer_lines.find(line => line.startsWith(`a=rid:${rid}`)); + assert_not_equals(result, undefined, `RID attribute for '${rid}' missing.`); + } + + // Check for simulcast attribute with send direction and all RIDs. + let result = offer_lines.find( + line => line.startsWith(`a=simulcast:send ${expected_rids.join(';')}`)); + assert_not_equals(result, undefined, "Could not find simulcast attribute."); +}, 'createOffer() with multiple send encodings should create simulcast offer'); +</script>
diff --git a/third_party/blink/web_tests/external/wpt_automation/dom/events/document-level-wheel-event-listener-passive-by-default-manual-automation.js b/third_party/blink/web_tests/external/wpt_automation/dom/events/document-level-wheel-event-listener-passive-by-default-manual-automation.js index ab3f79f0..9dae3c3 100644 --- a/third_party/blink/web_tests/external/wpt_automation/dom/events/document-level-wheel-event-listener-passive-by-default-manual-automation.js +++ b/third_party/blink/web_tests/external/wpt_automation/dom/events/document-level-wheel-event-listener-passive-by-default-manual-automation.js
@@ -16,9 +16,12 @@ { var input_injection = async_test("Input Injection Automation"); // Returns a promise that gets resolved when input injection is finished. - inject_input().then(function() { - input_injection.done(); - }); + window.requestAnimationFrame( + function () { + inject_input().then(function() { + input_injection.done(); + }); + }); } function inject_input() {
diff --git a/third_party/blink/web_tests/fast/events/synthetic-events/tap-on-scaled-screen.html b/third_party/blink/web_tests/fast/events/synthetic-events/tap-on-scaled-screen.html index 8db2e00..4c60687 100644 --- a/third_party/blink/web_tests/fast/events/synthetic-events/tap-on-scaled-screen.html +++ b/third_party/blink/web_tests/fast/events/synthetic-events/tap-on-scaled-screen.html
@@ -13,6 +13,7 @@ test(function(t) { var receivedTap = false; +var input_types = []; var box = document.getElementById('box'); var targetRect = box.getBoundingClientRect(); var offset = 50; @@ -29,14 +30,29 @@ assert_approx_equals(event.screenY, y+window.screenY, floatPrecision); } +function validPointerDownResult(event) { + input_types.push(event.pointerType); + assert_equals(event.target.id, "box"); + assert_approx_equals(event.clientX, x, floatPrecision); + assert_approx_equals(event.clientY, y, floatPrecision); + assert_approx_equals(event.screenX, x+window.screenX, floatPrecision); + assert_approx_equals(event.screenY, y+window.screenY, floatPrecision); +} + var testTap = async_test('Send a tap event.'); testTap.step(function () { box.addEventListener('click', validTapResult); + box.addEventListener('pointerdown', validPointerDownResult); if (window.chrome && chrome.gpuBenchmarking) { - chrome.gpuBenchmarking.tap(x, y, function() { - assert_true(receivedTap); - testTap.done(); - }); + var inputs = [chrome.gpuBenchmarking.TOUCH_INPUT, chrome.gpuBenchmarking.MOUSE_INPUT]; + for (var input of inputs) { + chrome.gpuBenchmarking.tap(x, y, function() { + assert_true(receivedTap); + if (input_types.join(' ') == "touch mouse") { + testTap.done(); + } + }, 50, input); + } } });
diff --git a/third_party/blink/web_tests/fast/peerconnection/RTCRtpSender-getParameters.html b/third_party/blink/web_tests/fast/peerconnection/RTCRtpSender-getParameters.html index 823f5ed..9c3c3982 100644 --- a/third_party/blink/web_tests/fast/peerconnection/RTCRtpSender-getParameters.html +++ b/third_party/blink/web_tests/fast/peerconnection/RTCRtpSender-getParameters.html
@@ -83,13 +83,13 @@ for(let encoding of parameters.encodings) { assert_false(encoding.hasOwnProperty("codecPayloadType"), "unset codecPayloadType"); assert_false(encoding.hasOwnProperty("dtx"), "unset dtx"); + assert_equals(encoding.rid, ''); assert_true(encoding.active); assert_equals(encoding.priority, "low"); assert_false(encoding.hasOwnProperty("ptime"), "unset ptime"); assert_false(encoding.hasOwnProperty("maxBitrate"), "unset maxBitrate"); assert_false(encoding.hasOwnProperty("maxFramerate"), "unset maxFramerate"); assert_false(encoding.hasOwnProperty("scaleResolutionDownBy"), "unset scaleResolutionDownBy"); - assert_false(encoding.hasOwnProperty("rid"), "unset rid"); } assert_false(parameters.hasOwnProperty("degradationPreference"), "unimplemented degradationPreference");
diff --git a/third_party/blink/web_tests/fast/peerconnection/RTCRtpSender-setParameters-expected.txt b/third_party/blink/web_tests/fast/peerconnection/RTCRtpSender-setParameters-expected.txt index 5f5f3974..d0af7a2f 100644 --- a/third_party/blink/web_tests/fast/peerconnection/RTCRtpSender-setParameters-expected.txt +++ b/third_party/blink/web_tests/fast/peerconnection/RTCRtpSender-setParameters-expected.txt
@@ -16,7 +16,7 @@ PASS video setParameters() check for codecs.sdpFmtpLine removed PASS video setParameters() check for encodings remove one PASS video setParameters() check for encodings add one -FAIL video setParameters() check for encodings.rid modification assert_unreached: Should have rejected: undefined Reached unreachable code +PASS video setParameters() check for encodings.rid modification PASS video setParameters() check for headerExtensions remove one PASS video setParameters() check for headerExtensions add one PASS video setParameters() check for headerExtensions.uri modification @@ -38,7 +38,7 @@ PASS audio setParameters() check for codecs.sdpFmtpLine removed PASS audio setParameters() check for encodings remove one PASS audio setParameters() check for encodings add one -FAIL audio setParameters() check for encodings.rid modification assert_unreached: Should have rejected: undefined Reached unreachable code +PASS audio setParameters() check for encodings.rid modification PASS audio setParameters() check for headerExtensions remove one PASS audio setParameters() check for headerExtensions add one PASS audio setParameters() check for headerExtensions.uri modification
diff --git a/third_party/blink/web_tests/fast/scrolling/document-level-touchmove-event-listener-passive-by-default.html b/third_party/blink/web_tests/fast/scrolling/document-level-touchmove-event-listener-passive-by-default.html new file mode 100644 index 0000000..2206691 --- /dev/null +++ b/third_party/blink/web_tests/fast/scrolling/document-level-touchmove-event-listener-passive-by-default.html
@@ -0,0 +1,42 @@ +<!DOCTYPE html> +<title>Default passive document level touchmove event listener test</title> +<link rel="help" href="https://github.com/WICG/interventions/issues/35"> +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> +<script src="../../resources/gesture-util.js"></script> +<body onload=runTest()> +<div id="touchDiv"> +</div> +</body> +<style> +#touchDiv { + width: 100px; + height: 100px; +} +</style> +<script> +var touch_div = document.getElementById("touchDiv"); +var rect = touch_div.getBoundingClientRect(); +var x = rect.left + rect.width / 2; +var y = rect.top + rect.height / 2; +var cancelable = true; +var touch_move_arrived = false; +document.addEventListener("touchmove", function (event) { + cancelable = event.cancelable; + touch_move_arrived = true; + event.preventDefault(); +}); + +function injectInput() { + return smoothScroll(10, x, y, GestureSourceType.TOUCH_INPUT, "down"); +} + +function runTest() { + promise_test (async () => { + await waitForCompositorCommit(); + await injectInput(); + await waitFor(()=> { return touch_move_arrived; }); + assert_false(cancelable); + }, "Touchmove events are non-cancelable since the event listener is treated as passive."); +} +</script>
diff --git a/third_party/blink/web_tests/fast/scrolling/document-level-wheel-event-listener-passive-by-default.html b/third_party/blink/web_tests/fast/scrolling/document-level-wheel-event-listener-passive-by-default.html new file mode 100644 index 0000000..45f33e66 --- /dev/null +++ b/third_party/blink/web_tests/fast/scrolling/document-level-wheel-event-listener-passive-by-default.html
@@ -0,0 +1,42 @@ +<!DOCTYPE html> +<title>Default passive document level wheel event listener test</title> +<link rel="help" href="https://github.com/WICG/interventions/issues/64"> +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> +<script src="../../resources/gesture-util.js"></script> +<body onload=runTest()> +<div id="wheelDiv"> +</div> +</body> +<style> +#wheelDiv { + width: 100px; + height: 100px; +} +</style> +<script> +var wheel_div = document.getElementById("wheelDiv"); +var rect = wheel_div.getBoundingClientRect(); +var x = rect.left + rect.width / 2; +var y = rect.top + rect.height / 2; +var cancelable = true; +var wheel_arrived = false; +document.addEventListener("wheel", function (event) { + cancelable = event.cancelable; + wheel_arrived = true; + event.preventDefault(); +}); + +function injectInput() { + return smoothScroll(10, x, y, GestureSourceType.MOUSE_INPUT, "down"); +} + +function runTest() { + promise_test (async () => { + await waitForCompositorCommit(); + await injectInput(); + await waitFor(()=> { return wheel_arrived; }); + assert_false(cancelable); + }, "Wheel events are non-cancelable since the event listener is treated as passive."); +} +</script>
diff --git a/third_party/blink/web_tests/fast/text/international/standalone_virama_mark-expected.txt b/third_party/blink/web_tests/fast/text/international/standalone_virama_mark-expected.txt new file mode 100644 index 0000000..874a109 --- /dev/null +++ b/third_party/blink/web_tests/fast/text/international/standalone_virama_mark-expected.txt
@@ -0,0 +1,3 @@ +ம் + +This test passes if it does not crash
diff --git a/third_party/blink/web_tests/fast/text/international/standalone_virama_mark.html b/third_party/blink/web_tests/fast/text/international/standalone_virama_mark.html new file mode 100644 index 0000000..8ac360ae --- /dev/null +++ b/third_party/blink/web_tests/fast/text/international/standalone_virama_mark.html
@@ -0,0 +1,14 @@ +<!DOCTYPE html> +<html> + <head> + <meta chartset="utf-8"> + <script> + if (window.testRunner) + testRunner.dumpAsText(); + </script> + </head> + <body> + <span>ம</span>் + <p>This test passes if it does not crash</p> + </body> +</html>
diff --git a/third_party/blink/web_tests/media/controls/modern/doubletap-to-jump-forwards.html b/third_party/blink/web_tests/media/controls/modern/doubletap-to-jump-forwards.html index d15584b..06eff61b 100644 --- a/third_party/blink/web_tests/media/controls/modern/doubletap-to-jump-forwards.html +++ b/third_party/blink/web_tests/media/controls/modern/doubletap-to-jump-forwards.html
@@ -26,10 +26,9 @@ }); video.addEventListener('seeked', () => { - double_tap_gesture.then(t.step_func_done(() => { - // Check the video advanced 10 seconds - assert_equals(Math.round(video.currentTime), time + 10); - })); + // Check the video advanced 10 seconds + assert_equals(Math.round(video.currentTime), time + 10); + double_tap_gesture.then(t.step_func_done()); }, { once: true }); video.play();
diff --git a/third_party/blink/web_tests/virtual/webrtc-wpt-plan-b/external/wpt/webrtc/protocol/simulcast-offer-expected.txt b/third_party/blink/web_tests/virtual/webrtc-wpt-plan-b/external/wpt/webrtc/protocol/simulcast-offer-expected.txt new file mode 100644 index 0000000..a89f2c128 --- /dev/null +++ b/third_party/blink/web_tests/virtual/webrtc-wpt-plan-b/external/wpt/webrtc/protocol/simulcast-offer-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL createOffer() with multiple send encodings should create simulcast offer promise_test: Unhandled rejection with value: object "InvalidStateError: Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'. 'unified-plan' will become the default behavior in the future, but it is currently experimental. To try it out, construct the RTCPeerConnection with sdpSemantics:'unified-plan' present in the RTCConfiguration argument." +Harness: the test ran to completion. +
diff --git a/third_party/feed/README.chromium b/third_party/feed/README.chromium index 924dd7d..b7a5b2b 100644 --- a/third_party/feed/README.chromium +++ b/third_party/feed/README.chromium
@@ -2,7 +2,7 @@ Short name: feed URL: https://chromium.googlesource.com/feed Version: 0 -Revision: 9a7f20c75b0e6ca8d669e967ec0bd6b72965df3e +Revision: 0ac884dad3d640ac4a31ba80c7f0d25be623ab52 License: Apache 2.0 License File: LICENSE Security Critical: yes
diff --git a/third_party/inspector_protocol/README.chromium b/third_party/inspector_protocol/README.chromium index 99d42cb..4ed4d17 100644 --- a/third_party/inspector_protocol/README.chromium +++ b/third_party/inspector_protocol/README.chromium
@@ -2,7 +2,7 @@ Short Name: inspector_protocol URL: https://chromium.googlesource.com/deps/inspector_protocol/ Version: 0 -Revision: f67ec5180f476830e839226b5ca948e43070fdab +Revision: 13e24ccee66d7e0590ce1266db9c906e3648561 License: BSD License File: LICENSE Security Critical: no
diff --git a/third_party/inspector_protocol/encoding/cbor.cc b/third_party/inspector_protocol/encoding/cbor.cc index 9ff93da..259cfb1 100644 --- a/third_party/inspector_protocol/encoding/cbor.cc +++ b/third_party/inspector_protocol/encoding/cbor.cc
@@ -4,8 +4,10 @@ #include "cbor.h" +#include <stdio.h> #include <cassert> #include <limits> +#include <string> #include "json_parser_handler.h" namespace inspector_protocol { @@ -188,6 +190,40 @@ out->insert(out->end(), in.begin(), in.end()); } +void EncodeFromLatin1(span<uint8_t> latin1, std::vector<uint8_t>* out) { + for (std::ptrdiff_t ii = 0; ii < latin1.size(); ++ii) { + if (latin1[ii] <= 127) + continue; + // If there's at least one non-ASCII char, convert to UTF8. + std::vector<uint8_t> utf8(latin1.begin(), latin1.begin() + ii); + for (; ii < latin1.size(); ++ii) { + if (latin1[ii] <= 127) { + utf8.push_back(latin1[ii]); + } else { + // 0xC0 means it's a UTF8 sequence with 2 bytes. + utf8.push_back((latin1[ii] >> 6) | 0xc0); + utf8.push_back((latin1[ii] | 0x80) & 0xbf); + } + } + EncodeString8(span<uint8_t>(utf8.data(), utf8.size()), out); + return; + } + EncodeString8(latin1, out); +} + +void EncodeFromUTF16(span<uint16_t> utf16, std::vector<uint8_t>* out) { + // If there's at least one non-ASCII char, encode as STRING16 (UTF16). + for (uint16_t ch : utf16) { + if (ch <= 127) + continue; + EncodeString16(utf16, out); + return; + } + // It's all US-ASCII, strip out every second byte and encode as UTF8. + WriteTokenStart(MajorType::STRING, static_cast<uint64_t>(utf16.size()), out); + out->insert(out->end(), utf16.begin(), utf16.end()); +} + void EncodeBinary(span<uint8_t> in, std::vector<uint8_t>* out) { out->push_back(kExpectedConversionToBase64Tag); uint64_t byte_length = static_cast<uint64_t>(in.size_bytes()); @@ -273,11 +309,15 @@ envelopes_.pop_back(); } - void HandleString16(std::vector<uint16_t> chars) override { + void HandleString8(span<uint8_t> chars) override { + EncodeString8(chars, out_); + } + + void HandleString16(span<uint16_t> chars) override { for (uint16_t ch : chars) { if (ch >= 0x7f) { // If there's at least one non-7bit character, we encode as UTF16. - EncodeString16(span<uint16_t>(chars.data(), chars.size()), out_); + EncodeString16(chars, out_); return; } } @@ -337,25 +377,13 @@ span<uint8_t> rep = tokenizer->GetString16WireRep(); for (std::ptrdiff_t ii = 0; ii < rep.size(); ii += 2) value.push_back((rep[ii + 1] << 8) | rep[ii]); - out->HandleString16(std::move(value)); + out->HandleString16(span<uint16_t>(value.data(), value.size())); tokenizer->Next(); } -// For now this method only covers US-ASCII. Later, we may allow UTF8. -bool ParseASCIIString(CBORTokenizer* tokenizer, JSONParserHandler* out) { +bool ParseUTF8String(CBORTokenizer* tokenizer, JSONParserHandler* out) { assert(tokenizer->TokenTag() == CBORTokenTag::STRING8); - std::vector<uint16_t> value16; - for (uint8_t ch : tokenizer->GetString8()) { - // We only accept us-ascii (7 bit) strings here. Other strings must - // be encoded with 16 bit (the BYTE_STRING case). - if (ch >= 0x7f) { - out->HandleError( - Status{Error::CBOR_STRING8_MUST_BE_7BIT, tokenizer->Status().pos}); - return false; - } - value16.push_back(ch); - } - out->HandleString16(std::move(value16)); + out->HandleString8(tokenizer->GetString8()); tokenizer->Next(); return true; } @@ -399,7 +427,7 @@ tokenizer->Next(); return true; case CBORTokenTag::STRING8: - return ParseASCIIString(tokenizer, out); + return ParseUTF8String(tokenizer, out); case CBORTokenTag::STRING16: ParseUTF16String(tokenizer, out); return true; @@ -466,7 +494,8 @@ } // Parse key. if (tokenizer->TokenTag() == CBORTokenTag::STRING8) { - if (!ParseASCIIString(tokenizer, out)) return false; + if (!ParseUTF8String(tokenizer, out)) + return false; } else if (tokenizer->TokenTag() == CBORTokenTag::STRING16) { ParseUTF16String(tokenizer, out); } else {
diff --git a/third_party/inspector_protocol/encoding/cbor.h b/third_party/inspector_protocol/encoding/cbor.h index c4b3c30..2785f633 100644 --- a/third_party/inspector_protocol/encoding/cbor.h +++ b/third_party/inspector_protocol/encoding/cbor.h
@@ -96,8 +96,9 @@ // - UTF16 strings, including with unbalanced surrogate pairs, are encoded // as CBOR BYTE_STRING (major type 2). For such strings, the number of // bytes encoded must be even. -// - UTF8 strings (major type 3) may only have ASCII characters -// (7 bit US-ASCII). +// - UTF8 strings (major type 3) are supported. +// - 7 bit US-ASCII strings must always be encoded as UTF8 strings, not +// as UTF16 strings. // - Arbitrary byte arrays, in the inspector protocol called 'binary', // are encoded as BYTE_STRING (major type 2), prefixed with a byte // indicating base64 when rendered as JSON. @@ -114,6 +115,15 @@ // Encodes a UTF8 string |in| as STRING (major type 3). void EncodeString8(span<uint8_t> in, std::vector<uint8_t>* out); +// Encodes the given |latin1| string as STRING8. +// If any non-ASCII character is present, it will be represented +// as a 2 byte UTF8 sequence. +void EncodeFromLatin1(span<uint8_t> latin1, std::vector<uint8_t>* out); + +// Encodes the given |utf16| string as STRING8 if it's entirely US-ASCII. +// Otherwise, encodes as STRING16. +void EncodeFromUTF16(span<uint16_t> utf16, std::vector<uint8_t>* out); + // Encodes arbitrary binary data in |in| as a BYTE_STRING (major type 2) with // definitive length, prefixed with tag 22 indicating expected conversion to // base64 (see RFC 7049, Table 3 and Section 2.4.4.2).
diff --git a/third_party/inspector_protocol/encoding/cbor_test.cc b/third_party/inspector_protocol/encoding/cbor_test.cc index d3264c4..9f6201f 100644 --- a/third_party/inspector_protocol/encoding/cbor_test.cc +++ b/third_party/inspector_protocol/encoding/cbor_test.cc
@@ -329,6 +329,63 @@ EXPECT_EQ(CBORTokenTag::DONE, tokenizer.TokenTag()); } +TEST(EncodeFromLatin1Test, ConvertsToUTF8IfNeeded) { + std::vector<std::pair<std::string, std::string>> examples = { + {"Hello, world.", "Hello, world."}, + {"Above: \xDC" + "ber", + "Above: Über"}, + {"\xA5 500 are about \xA3 3.50; a y with umlaut is \xFF", + "¥ 500 are about £ 3.50; a y with umlaut is ÿ"}}; + + for (const auto& example : examples) { + const std::string& latin1 = example.first; + const std::string& expected_utf8 = example.second; + std::vector<uint8_t> encoded; + EncodeFromLatin1( + span<uint8_t>(reinterpret_cast<const uint8_t*>(latin1.data()), + latin1.size()), + &encoded); + CBORTokenizer tokenizer(span<uint8_t>(&encoded[0], encoded.size())); + EXPECT_EQ(CBORTokenTag::STRING8, tokenizer.TokenTag()); + std::vector<uint8_t> decoded(tokenizer.GetString8().begin(), + tokenizer.GetString8().end()); + std::string decoded_str(decoded.begin(), decoded.end()); + EXPECT_THAT(decoded_str, testing::Eq(expected_utf8)); + } +} + +TEST(EncodeFromUTF16Test, ConvertsToUTF8IfEasy) { + std::vector<uint16_t> ascii = {'e', 'a', 's', 'y'}; + std::vector<uint8_t> encoded; + EncodeFromUTF16(span<uint16_t>(ascii.data(), ascii.size()), &encoded); + + CBORTokenizer tokenizer(span<uint8_t>(&encoded[0], encoded.size())); + EXPECT_EQ(CBORTokenTag::STRING8, tokenizer.TokenTag()); + std::vector<uint8_t> decoded(tokenizer.GetString8().begin(), + tokenizer.GetString8().end()); + std::string decoded_str(decoded.begin(), decoded.end()); + EXPECT_THAT(decoded_str, testing::Eq("easy")); +} + +TEST(EncodeFromUTF16Test, EncodesAsString16IfNeeded) { + // Since this message contains non-ASCII characters, the routine is + // forced to encode as UTF16. We see this below by checking that the + // token tag is STRING16. + std::vector<uint16_t> msg = {'H', 'e', 'l', 'l', 'o', + ',', ' ', 0xd83c, 0xdf0e, '.'}; + std::vector<uint8_t> encoded; + EncodeFromUTF16(span<uint16_t>(msg.data(), msg.size()), &encoded); + + CBORTokenizer tokenizer(span<uint8_t>(&encoded[0], encoded.size())); + EXPECT_EQ(CBORTokenTag::STRING16, tokenizer.TokenTag()); + std::vector<uint16_t> decoded = + String16WireRepToHost(tokenizer.GetString16WireRep()); + std::string utf8_decoded = + base::UTF16ToUTF8(base::StringPiece16(decoded.data(), decoded.size())); + EXPECT_EQ("Hello, 🌎.", utf8_decoded); +} + // // EncodeBinary / CBORTokenTag::BINARY // @@ -409,9 +466,7 @@ // // NewJSONToCBOREncoder // -void EncodeSevenBitStringForTest(const std::string& key, - std::vector<uint8_t>* out) { - for (char c : key) assert(c > 0); // Enforce 7 bits. Sadly, char is signed. +void EncodeUTF8ForTest(const std::string& key, std::vector<uint8_t>* out) { EncodeString8( span<uint8_t>(reinterpret_cast<const uint8_t*>(key.data()), key.size()), out); @@ -426,7 +481,7 @@ std::unique_ptr<JSONParserHandler> encoder = NewJSONToCBOREncoder(&encoded, &status); std::vector<uint16_t> utf16 = {'f', 'o', 'o'}; - encoder->HandleString16(utf16); + encoder->HandleString16(span<uint16_t>(utf16.data(), utf16.size())); EXPECT_EQ(Error::OK, status.error); // Here we assert that indeed, seven bit strings are represented as // bytes on the wire, "foo" is just "foo". @@ -461,7 +516,7 @@ 0, 0, 0, 94, // length is 94 bytes }; expected.push_back(0xbf); // indef length map start - EncodeSevenBitStringForTest("string", &expected); + EncodeUTF8ForTest("string", &expected); // This is followed by the encoded string for "Hello, 🌎." // So, it's the same bytes that we tested above in // EncodeDecodeString16Test.RoundtripsHelloWorld. @@ -470,17 +525,17 @@ {'H', 0, 'e', 0, 'l', 0, 'l', 0, 'o', 0, ',', 0, ' ', 0, 0x3c, 0xd8, 0x0e, 0xdf, '.', 0}}) expected.push_back(ch); - EncodeSevenBitStringForTest("double", &expected); + EncodeUTF8ForTest("double", &expected); EncodeDouble(3.1415, &expected); - EncodeSevenBitStringForTest("int", &expected); + EncodeUTF8ForTest("int", &expected); EncodeInt32(1, &expected); - EncodeSevenBitStringForTest("negative int", &expected); + EncodeUTF8ForTest("negative int", &expected); EncodeInt32(-1, &expected); - EncodeSevenBitStringForTest("bool", &expected); + EncodeUTF8ForTest("bool", &expected); expected.push_back(7 << 5 | 21); // RFC 7049 Section 2.3, Table 2: true - EncodeSevenBitStringForTest("null", &expected); + EncodeUTF8ForTest("null", &expected); expected.push_back(7 << 5 | 22); // RFC 7049 Section 2.3, Table 2: null - EncodeSevenBitStringForTest("array", &expected); + EncodeUTF8ForTest("array", &expected); expected.push_back(0xd8); // envelope expected.push_back(0x5a); // byte string with 32 bit length // the length is 5 bytes (that's up to end indef length array below). @@ -541,7 +596,8 @@ NewJSONToCBOREncoder(&encoded, &status); encoder->HandleObjectBegin(); // Emit a key. - encoder->HandleString16(std::vector<uint16_t>{'f', 'o', 'o'}); + std::vector<uint16_t> key = {'f', 'o', 'o'}; + encoder->HandleString16(span<uint16_t>(key.data(), key.size())); // Emit the binary payload, an arbitrary array of bytes that happens to // be the ascii message "Hello, world.". encoder->HandleBinary(std::vector<uint8_t>{'H', 'e', 'l', 'l', 'o', ',', ' ', @@ -581,7 +637,7 @@ const uint8_t kPayloadLen = 27; std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, 0, 0, kPayloadLen}; bytes.push_back(0xbf); // start indef length map. - EncodeSevenBitStringForTest("msg", &bytes); // key: msg + EncodeUTF8ForTest("msg", &bytes); // key: msg // Now write the value, the familiar "Hello, 🌎." where the globe is expressed // as two utf16 chars. bytes.push_back(/*major type=*/2 << 5 | /*additional info=*/20); @@ -601,6 +657,29 @@ EXPECT_EQ("{\"msg\":\"Hello, \\ud83c\\udf0e.\"}", out); } +TEST(ParseCBORTest, UTF8IsSupportedInKeys) { + const uint8_t kPayloadLen = 11; + std::vector<uint8_t> bytes = {cbor::kInitialByteForEnvelope, + cbor::kInitialByteFor32BitLengthByteString, + 0, + 0, + 0, + kPayloadLen}; + bytes.push_back(cbor::kInitialByteIndefiniteLengthMap); + EncodeUTF8ForTest("🌎", &bytes); // Two UTF16 chars. + EncodeUTF8ForTest("☾", &bytes); // Can be encoded as a single UTF16 char. + bytes.push_back(cbor::kStopByte); + EXPECT_EQ(kPayloadLen, bytes.size() - 6); + + std::string out; + Status status; + std::unique_ptr<JSONParserHandler> json_writer = + NewJSONWriter(GetLinuxDevPlatform(), &out, &status); + ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get()); + EXPECT_EQ(Error::OK, status.error); + EXPECT_EQ("{\"\\ud83c\\udf0e\":\"\\u263e\"}", out); +} + TEST(ParseCBORTest, NoInputError) { std::vector<uint8_t> in = {}; std::string out; @@ -632,7 +711,7 @@ constexpr uint8_t kPayloadLen = 5; std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, 0, 0, kPayloadLen, // envelope 0xbf}; // map start - EncodeSevenBitStringForTest("key", &bytes); // A key; so value would be next. + EncodeUTF8ForTest("key", &bytes); // A key; so value would be next. EXPECT_EQ(kPayloadLen, bytes.size() - 6); std::string out; Status status; @@ -648,8 +727,7 @@ constexpr uint8_t kPayloadLen = 8; std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, 0, 0, kPayloadLen, // envelope 0xbf}; // The byte for starting a map. - EncodeSevenBitStringForTest("array", - &bytes); // A key; so value would be next. + EncodeUTF8ForTest("array", &bytes); // A key; so value would be next. bytes.push_back(0x9f); // byte for indefinite length array start. EXPECT_EQ(kPayloadLen, bytes.size() - 6); std::string out; @@ -701,9 +779,9 @@ envelopes.emplace_back(); envelopes.back().EncodeStart(&bytes); bytes.push_back(0xbf); // indef length map start - EncodeSevenBitStringForTest("key", &bytes); + EncodeUTF8ForTest("key", &bytes); } - EncodeSevenBitStringForTest("innermost_value", &bytes); + EncodeUTF8ForTest("innermost_value", &bytes); for (int ii = 0; ii < depth; ++ii) { bytes.push_back(0xff); // stop byte, finishes map. envelopes.back().EncodeStop(&bytes); @@ -770,7 +848,7 @@ constexpr uint8_t kPayloadLen = 6; std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, 0, 0, kPayloadLen, // envelope 0xbf}; // map start - EncodeSevenBitStringForTest("key", &bytes); + EncodeUTF8ForTest("key", &bytes); int64_t error_pos = bytes.size(); bytes.push_back(6 << 5 | 5); // tags aren't supported yet. EXPECT_EQ(kPayloadLen, bytes.size() - 6); @@ -789,7 +867,7 @@ constexpr uint8_t kPayloadLen = 11; std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, 0, 0, kPayloadLen, // envelope 0xbf}; // map start - EncodeSevenBitStringForTest("key", &bytes); + EncodeUTF8ForTest("key", &bytes); int64_t error_pos = bytes.size(); // a BYTE_STRING of length 5 as value; since we interpret these as string16, // it's going to be invalid as each character would need two bytes, but @@ -811,7 +889,7 @@ constexpr uint8_t kPayloadLen = 6; std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, 0, 0, kPayloadLen, // envelope 0xbf}; // map start - EncodeSevenBitStringForTest("key", &bytes); + EncodeUTF8ForTest("key", &bytes); int64_t error_pos = bytes.size(); // a STRING of length 5 as value, but we're at the end of the bytes array // so it can't be decoded successfully. @@ -827,32 +905,11 @@ EXPECT_EQ("", out); } -TEST(ParseCBORTest, String8MustBe7BitError) { - constexpr uint8_t kPayloadLen = 11; - std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, 0, 0, kPayloadLen, // envelope - 0xbf}; // map start - EncodeSevenBitStringForTest("key", &bytes); - int64_t error_pos = bytes.size(); - // a STRING of length 5 as value, with a payload that has bytes outside - // 7 bit (> 0x7f). - bytes.push_back(3 << 5 | 5); - for (int ii = 0; ii < 5; ++ii) bytes.push_back(0xf0); - EXPECT_EQ(kPayloadLen, bytes.size() - 6); - std::string out; - Status status; - std::unique_ptr<JSONParserHandler> json_writer = - NewJSONWriter(GetLinuxDevPlatform(), &out, &status); - ParseCBOR(span<uint8_t>(bytes.data(), bytes.size()), json_writer.get()); - EXPECT_EQ(Error::CBOR_STRING8_MUST_BE_7BIT, status.error); - EXPECT_EQ(error_pos, status.pos); - EXPECT_EQ("", out); -} - TEST(ParseCBORTest, InvalidBinaryError) { constexpr uint8_t kPayloadLen = 9; std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, 0, 0, kPayloadLen, // envelope 0xbf}; // map start - EncodeSevenBitStringForTest("key", &bytes); + EncodeUTF8ForTest("key", &bytes); int64_t error_pos = bytes.size(); bytes.push_back(6 << 5 | 22); // base64 hint for JSON; indicates binary bytes.push_back(2 << 5 | 10); // BYTE_STRING (major type 2) of length 10 @@ -874,7 +931,7 @@ constexpr uint8_t kPayloadLen = 8; std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, 0, 0, kPayloadLen, // envelope 0xbf}; // map start - EncodeSevenBitStringForTest("key", &bytes); + EncodeUTF8ForTest("key", &bytes); int64_t error_pos = bytes.size(); bytes.push_back(7 << 5 | 27); // initial byte for double // Just two garbage bytes, not enough to represent an actual double. @@ -895,7 +952,7 @@ constexpr uint8_t kPayloadLen = 14; std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, 0, 0, kPayloadLen, // envelope 0xbf}; // map start - EncodeSevenBitStringForTest("key", &bytes); + EncodeUTF8ForTest("key", &bytes); int64_t error_pos = bytes.size(); // uint64_t max is a perfectly fine value to encode as CBOR unsigned, // but we don't support this since we only cover the int32_t range. @@ -916,11 +973,11 @@ constexpr uint8_t kPayloadLen = 35; std::vector<uint8_t> bytes = {0xd8, 0x5a, 0, 0, 0, kPayloadLen, // envelope 0xbf}; // map start - EncodeSevenBitStringForTest("key", &bytes); - EncodeSevenBitStringForTest("value", &bytes); + EncodeUTF8ForTest("key", &bytes); + EncodeUTF8ForTest("value", &bytes); bytes.push_back(0xff); // Up to here, it's a perfectly fine msg. int64_t error_pos = bytes.size(); - EncodeSevenBitStringForTest("trailing junk", &bytes); + EncodeUTF8ForTest("trailing junk", &bytes); cbor_internals::WriteTokenStart(MajorType::UNSIGNED, std::numeric_limits<uint64_t>::max(), &bytes);
diff --git a/third_party/inspector_protocol/encoding/json_parser.cc b/third_party/inspector_protocol/encoding/json_parser.cc index ad781e4f..27a1f23 100644 --- a/third_party/inspector_protocol/encoding/json_parser.cc +++ b/third_party/inspector_protocol/encoding/json_parser.cc
@@ -225,7 +225,8 @@ static bool IsSpaceOrNewLine(Char c) { // \v = vertial tab; \f = form feed page break. - return c == ' ' || c == '\n' || c == '\v' || c == '\f' || c == '\r'; + return c == ' ' || c == '\n' || c == '\v' || c == '\f' || c == '\r' || + c == '\t'; } static void SkipWhitespaceAndComments(const Char* start, const Char* end, @@ -467,7 +468,7 @@ HandleError(Error::JSON_PARSER_INVALID_STRING, token_start); return; } - handler_->HandleString16(std::move(value)); + handler_->HandleString16(span<uint16_t>(value.data(), value.size())); break; } case ArrayBegin: { @@ -513,7 +514,7 @@ HandleError(Error::JSON_PARSER_INVALID_STRING, token_start); return; } - handler_->HandleString16(std::move(key)); + handler_->HandleString16(span<uint16_t>(key.data(), key.size())); start = token_end; token = ParseToken(start, end, &token_start, &token_end);
diff --git a/third_party/inspector_protocol/encoding/json_parser_handler.h b/third_party/inspector_protocol/encoding/json_parser_handler.h index c501d99f..d90b65f7 100644 --- a/third_party/inspector_protocol/encoding/json_parser_handler.h +++ b/third_party/inspector_protocol/encoding/json_parser_handler.h
@@ -7,6 +7,7 @@ #include <cstdint> #include <vector> +#include "span.h" #include "status.h" namespace inspector_protocol { @@ -18,9 +19,8 @@ virtual void HandleObjectEnd() = 0; virtual void HandleArrayBegin() = 0; virtual void HandleArrayEnd() = 0; - // TODO(johannes): Support utf8 (requires utf16->utf8 conversion - // internally, including handling mismatched surrogate pairs). - virtual void HandleString16(std::vector<uint16_t> chars) = 0; + virtual void HandleString8(span<uint8_t> chars) = 0; + virtual void HandleString16(span<uint16_t> chars) = 0; virtual void HandleBinary(std::vector<uint8_t> bytes) = 0; virtual void HandleDouble(double value) = 0; virtual void HandleInt32(int32_t value) = 0;
diff --git a/third_party/inspector_protocol/encoding/json_parser_test.cc b/third_party/inspector_protocol/encoding/json_parser_test.cc index babb326..2e63129 100644 --- a/third_party/inspector_protocol/encoding/json_parser_test.cc +++ b/third_party/inspector_protocol/encoding/json_parser_test.cc
@@ -22,10 +22,16 @@ void HandleArrayEnd() override { log_ << "array end\n"; } - void HandleString16(std::vector<uint16_t> chars) override { + void HandleString8(span<uint8_t> chars) override { + base::StringPiece foo(reinterpret_cast<const char*>(chars.data()), + chars.size()); + log_ << "string8: " << foo << "\n"; + } + + void HandleString16(span<uint16_t> chars) override { base::StringPiece16 foo(reinterpret_cast<const base::char16*>(chars.data()), chars.size()); - log_ << "string: " << base::UTF16ToUTF8(foo) << "\n"; + log_ << "string16: " << base::UTF16ToUTF8(foo) << "\n"; } void HandleBinary(std::vector<uint8_t> bytes) override { @@ -69,12 +75,27 @@ EXPECT_TRUE(log_.status().ok()); EXPECT_EQ( "object begin\n" - "string: foo\n" + "string16: foo\n" "int: 42\n" "object end\n", log_.str()); } +TEST_F(JsonParserTest, Whitespace) { + std::string json = "\n {\n\"msg\"\n: \v\"Hello, world.\"\t\r}\t"; + ParseJSONChars( + GetLinuxDevPlatform(), + span<uint8_t>(reinterpret_cast<const uint8_t*>(json.data()), json.size()), + &log_); + EXPECT_TRUE(log_.status().ok()); + EXPECT_EQ( + "object begin\n" + "string16: msg\n" + "string16: Hello, world.\n" + "object end\n", + log_.str()); +} + TEST_F(JsonParserTest, NestedDictionary) { std::string json = "{\"foo\": {\"bar\": {\"baz\": 1}, \"bar2\": 2}}"; ParseJSONChars( @@ -84,14 +105,14 @@ EXPECT_TRUE(log_.status().ok()); EXPECT_EQ( "object begin\n" - "string: foo\n" + "string16: foo\n" "object begin\n" - "string: bar\n" + "string16: bar\n" "object begin\n" - "string: baz\n" + "string16: baz\n" "int: 1\n" "object end\n" - "string: bar2\n" + "string16: bar2\n" "int: 2\n" "object end\n" "object end\n", @@ -107,9 +128,9 @@ EXPECT_TRUE(log_.status().ok()); EXPECT_EQ( "object begin\n" - "string: foo\n" + "string16: foo\n" "double: 3.1415\n" - "string: bar\n" + "string16: bar\n" "double: 3.1415\n" "object end\n", log_.str()); @@ -125,8 +146,8 @@ EXPECT_TRUE(log_.status().ok()); EXPECT_EQ( "object begin\n" - "string: msg\n" - "string: Hello, 🌎.\n" + "string16: msg\n" + "string16: Hello, 🌎.\n" "object end\n", log_.str()); } @@ -145,8 +166,8 @@ EXPECT_TRUE(log_.status().ok()); EXPECT_EQ( "object begin\n" - "string: space\n" - "string: 🌎 🌙.\n" + "string16: space\n" + "string16: 🌎 🌙.\n" "object end\n", log_.str()); } @@ -174,14 +195,14 @@ EXPECT_TRUE(log_.status().ok()); EXPECT_EQ( "object begin\n" - "string: escapes\n" - "string: 🌙\n" - "string: 2 byte\n" - "string: гласность\n" - "string: 3 byte\n" - "string: 屋\n" - "string: 4 byte\n" - "string: 🌎\n" + "string16: escapes\n" + "string16: 🌙\n" + "string16: 2 byte\n" + "string16: гласность\n" + "string16: 3 byte\n" + "string16: 屋\n" + "string16: 4 byte\n" + "string16: 🌎\n" "object end\n", log_.str()); } @@ -219,11 +240,11 @@ EXPECT_TRUE(log_.status().ok()); EXPECT_EQ( "object begin\n" - "string: foo\n" + "string16: foo\n" "object begin\n" - "string: foo\n" + "string16: foo\n" "object begin\n" - "string: foo\n" + "string16: foo\n" "int: 42\n" "object end\n" "object end\n"
diff --git a/third_party/inspector_protocol/encoding/json_std_string_writer.cc b/third_party/inspector_protocol/encoding/json_std_string_writer.cc index 5f5ed78..1c849cc 100644 --- a/third_party/inspector_protocol/encoding/json_std_string_writer.cc +++ b/third_party/inspector_protocol/encoding/json_std_string_writer.cc
@@ -118,7 +118,7 @@ out_->append("]"); } - void HandleString16(std::vector<uint16_t> chars) override { + void HandleString16(span<uint16_t> chars) override { if (!status_->ok()) return; state_.top().StartElement(out_); out_->append("\""); @@ -147,6 +147,97 @@ out_->append("\""); } + void HandleString8(span<uint8_t> chars) override { + if (!status_->ok()) + return; + state_.top().StartElement(out_); + out_->append("\""); + for (std::ptrdiff_t ii = 0; ii < chars.size(); ++ii) { + uint8_t c = chars[ii]; + if (c == '"') { + out_->append("\\\""); + } else if (c == '\\') { + out_->append("\\\\"); + } else if (c == '\b') { + out_->append("\\b"); + } else if (c == '\f') { + out_->append("\\f"); + } else if (c == '\n') { + out_->append("\\n"); + } else if (c == '\r') { + out_->append("\\r"); + } else if (c == '\t') { + out_->append("\\t"); + } else if (c >= 32 && c <= 126) { + out_->append(1, c); + } else if (c < 32) { + out_->append("\\u"); + PrintHex(static_cast<uint16_t>(c), out_); + } else { + // Inspect the leading byte to figure out how long the utf8 + // byte sequence is; while doing this initialize |codepoint| + // with the first few bits. + // See table in: https://en.wikipedia.org/wiki/UTF-8 + // byte one is 110x xxxx -> 2 byte utf8 sequence + // byte one is 1110 xxxx -> 3 byte utf8 sequence + // byte one is 1111 0xxx -> 4 byte utf8 sequence + uint32_t codepoint; + int num_bytes_left; + if ((c & 0xe0) == 0xc0) { // 2 byte utf8 sequence + num_bytes_left = 1; + codepoint = c & 0x1f; + } else if ((c & 0xf0) == 0xe0) { // 3 byte utf8 sequence + num_bytes_left = 2; + codepoint = c & 0x0f; + } else if ((c & 0xf8) == 0xf0) { // 4 byte utf8 sequence + codepoint = c & 0x07; + num_bytes_left = 3; + } else { + continue; // invalid leading byte + } + + // If we have enough bytes in our input, decode the remaining ones + // belonging to this Unicode character into |codepoint|. + if (ii + num_bytes_left > chars.size()) + continue; + while (num_bytes_left > 0) { + c = chars[++ii]; + --num_bytes_left; + // Check the next byte is a continuation byte, that is 10xx xxxx. + if ((c & 0xc0) != 0x80) + continue; + codepoint = (codepoint << 6) | (c & 0x3f); + } + + // Disallow overlong encodings for ascii characters, as these + // would include " and other characters significant to JSON + // string termination / control. + if (codepoint < 0x7f) + continue; + // Invalid in UTF8, and can't be represented in UTF16 anyway. + if (codepoint > 0x10ffff) + continue; + + // So, now we transcode to UTF16, + // using the math described at https://en.wikipedia.org/wiki/UTF-16, + // for either one or two 16 bit characters. + if (codepoint < 0xffff) { + out_->append("\\u"); + PrintHex(static_cast<uint16_t>(codepoint), out_); + continue; + } + codepoint -= 0x10000; + // high surrogate + out_->append("\\u"); + PrintHex(static_cast<uint16_t>((codepoint >> 10) + 0xd800), out_); + // low surrogate + out_->append("\\u"); + PrintHex(static_cast<uint16_t>((codepoint & 0x3ff) + 0xdc00), out_); + } + } + out_->append("\""); + } + void HandleBinary(std::vector<uint8_t> bytes) override { if (!status_->ok()) return; state_.top().StartElement(out_);
diff --git a/third_party/inspector_protocol/encoding/json_std_string_writer_test.cc b/third_party/inspector_protocol/encoding/json_std_string_writer_test.cc index 0baa4d5..104d585 100644 --- a/third_party/inspector_protocol/encoding/json_std_string_writer_test.cc +++ b/third_party/inspector_protocol/encoding/json_std_string_writer_test.cc
@@ -16,28 +16,39 @@ string16.data() + string16.size()); } +void WriteUTF8AsUTF16(JSONParserHandler* writer, const std::string& utf8) { + std::vector<uint16_t> utf16 = UTF16String(utf8); + writer->HandleString16(span<uint16_t>(utf16.data(), utf16.size())); +} + TEST(JsonStdStringWriterTest, HelloWorld) { std::string out; Status status; std::unique_ptr<JSONParserHandler> writer = NewJSONWriter(GetLinuxDevPlatform(), &out, &status); writer->HandleObjectBegin(); - writer->HandleString16(UTF16String("msg1")); - writer->HandleString16(UTF16String("Hello, 🌎.")); - writer->HandleString16(UTF16String("msg2")); - writer->HandleString16(UTF16String("\\\b\r\n\t\f\"")); - writer->HandleString16(UTF16String("nested")); + WriteUTF8AsUTF16(writer.get(), "msg1"); + WriteUTF8AsUTF16(writer.get(), "Hello, 🌎."); + std::string key = "msg1-as-utf8"; + std::string value = "Hello, 🌎."; + writer->HandleString8( + span<uint8_t>(reinterpret_cast<const uint8_t*>(key.data()), key.size())); + writer->HandleString8(span<uint8_t>( + reinterpret_cast<const uint8_t*>(value.data()), value.size())); + WriteUTF8AsUTF16(writer.get(), "msg2"); + WriteUTF8AsUTF16(writer.get(), "\\\b\r\n\t\f\""); + WriteUTF8AsUTF16(writer.get(), "msg2"); writer->HandleObjectBegin(); - writer->HandleString16(UTF16String("double")); + WriteUTF8AsUTF16(writer.get(), "double"); writer->HandleDouble(3.1415); - writer->HandleString16(UTF16String("int")); + WriteUTF8AsUTF16(writer.get(), "int"); writer->HandleInt32(-42); - writer->HandleString16(UTF16String("bool")); + WriteUTF8AsUTF16(writer.get(), "bool"); writer->HandleBool(false); - writer->HandleString16(UTF16String("null")); + WriteUTF8AsUTF16(writer.get(), "null"); writer->HandleNull(); writer->HandleObjectEnd(); - writer->HandleString16(UTF16String("array")); + WriteUTF8AsUTF16(writer.get(), "array"); writer->HandleArrayBegin(); writer->HandleInt32(1); writer->HandleInt32(2); @@ -47,6 +58,7 @@ EXPECT_TRUE(status.ok()); EXPECT_EQ( "{\"msg1\":\"Hello, \\ud83c\\udf0e.\"," + "\"msg1-as-utf8\":\"Hello, \\ud83c\\udf0e.\"," "\"msg2\":\"\\\\\\b\\r\\n\\t\\f\\\"\"," "\"nested\":{\"double\":3.1415,\"int\":-42," "\"bool\":false,\"null\":null},\"array\":[1,2,3]}", @@ -104,7 +116,7 @@ std::unique_ptr<JSONParserHandler> writer = NewJSONWriter(GetLinuxDevPlatform(), &out, &status); writer->HandleObjectBegin(); - writer->HandleString16(UTF16String("msg1")); + WriteUTF8AsUTF16(writer.get(), "msg1"); writer->HandleError(Status{Error::JSON_PARSER_VALUE_EXPECTED, 42}); EXPECT_EQ(Error::JSON_PARSER_VALUE_EXPECTED, status.error); EXPECT_EQ(42, status.pos);
diff --git a/third_party/inspector_protocol/lib/CBOR_cpp.template b/third_party/inspector_protocol/lib/CBOR_cpp.template index 97ae156b..d2375b6c 100644 --- a/third_party/inspector_protocol/lib/CBOR_cpp.template +++ b/third_party/inspector_protocol/lib/CBOR_cpp.template
@@ -194,6 +194,38 @@ out->insert(out->end(), in.begin(), in.end()); } +void EncodeFromLatin1(span<uint8_t> latin1, std::vector<uint8_t>* out) { + for (std::ptrdiff_t ii = 0; ii < latin1.size(); ++ii) { + if (latin1[ii] <= 127) continue; + // If there's at least one non-ASCII char, convert to UTF8. + std::vector<uint8_t> utf8(latin1.begin(), latin1.begin() + ii); + for (; ii < latin1.size(); ++ii) { + if (latin1[ii] <= 127) { + utf8.push_back(latin1[ii]); + } else { + // 0xC0 means it's a UTF8 sequence with 2 bytes. + utf8.push_back((latin1[ii] >> 6) | 0xc0); + utf8.push_back((latin1[ii] | 0x80) & 0xbf); + } + } + EncodeString8(span<uint8_t>(utf8.data(), utf8.size()), out); + return; + } + EncodeString8(latin1, out); +} + +void EncodeFromUTF16(span<uint16_t> utf16, std::vector<uint8_t>* out) { + // If there's at least one non-ASCII char, encode as STRING16 (UTF16). + for (uint16_t ch : utf16) { + if (ch <= 127) continue; + EncodeString16(utf16, out); + return; + } + // It's all US-ASCII, strip out every second byte and encode as UTF8. + WriteTokenStart(MajorType::STRING, static_cast<uint64_t>(utf16.size()), out); + out->insert(out->end(), utf16.begin(), utf16.end()); +} + void EncodeBinary(span<uint8_t> in, std::vector<uint8_t>* out) { out->push_back(kExpectedConversionToBase64Tag); uint64_t byte_length = static_cast<uint64_t>(in.size_bytes()); @@ -279,11 +311,15 @@ envelopes_.pop_back(); } - void HandleString16(std::vector<uint16_t> chars) override { + void HandleString8(span<uint8_t> chars) override { + EncodeString8(chars, out_); + } + + void HandleString16(span<uint16_t> chars) override { for (uint16_t ch : chars) { if (ch >= 0x7f) { // If there's at least one non-7bit character, we encode as UTF16. - EncodeString16(span<uint16_t>(chars.data(), chars.size()), out_); + EncodeString16(chars, out_); return; } } @@ -343,25 +379,13 @@ span<uint8_t> rep = tokenizer->GetString16WireRep(); for (std::ptrdiff_t ii = 0; ii < rep.size(); ii += 2) value.push_back((rep[ii + 1] << 8) | rep[ii]); - out->HandleString16(std::move(value)); + out->HandleString16(span<uint16_t>(value.data(), value.size())); tokenizer->Next(); } -// For now this method only covers US-ASCII. Later, we may allow UTF8. -bool ParseASCIIString(CBORTokenizer* tokenizer, JSONParserHandler* out) { +bool ParseUTF8String(CBORTokenizer* tokenizer, JSONParserHandler* out) { assert(tokenizer->TokenTag() == CBORTokenTag::STRING8); - std::vector<uint16_t> value16; - for (uint8_t ch : tokenizer->GetString8()) { - // We only accept us-ascii (7 bit) strings here. Other strings must - // be encoded with 16 bit (the BYTE_STRING case). - if (ch >= 0x7f) { - out->HandleError( - Status{Error::CBOR_STRING8_MUST_BE_7BIT, tokenizer->Status().pos}); - return false; - } - value16.push_back(ch); - } - out->HandleString16(std::move(value16)); + out->HandleString8(tokenizer->GetString8()); tokenizer->Next(); return true; } @@ -405,7 +429,7 @@ tokenizer->Next(); return true; case CBORTokenTag::STRING8: - return ParseASCIIString(tokenizer, out); + return ParseUTF8String(tokenizer, out); case CBORTokenTag::STRING16: ParseUTF16String(tokenizer, out); return true; @@ -472,7 +496,7 @@ } // Parse key. if (tokenizer->TokenTag() == CBORTokenTag::STRING8) { - if (!ParseASCIIString(tokenizer, out)) return false; + if (!ParseUTF8String(tokenizer, out)) return false; } else if (tokenizer->TokenTag() == CBORTokenTag::STRING16) { ParseUTF16String(tokenizer, out); } else {
diff --git a/third_party/inspector_protocol/lib/CBOR_h.template b/third_party/inspector_protocol/lib/CBOR_h.template index dd637f1..9d28adb 100644 --- a/third_party/inspector_protocol/lib/CBOR_h.template +++ b/third_party/inspector_protocol/lib/CBOR_h.template
@@ -117,9 +117,8 @@ virtual void HandleObjectEnd() = 0; virtual void HandleArrayBegin() = 0; virtual void HandleArrayEnd() = 0; - // TODO(johannes): Support utf8 (requires utf16->utf8 conversion - // internally, including handling mismatched surrogate pairs). - virtual void HandleString16(std::vector<uint16_t> chars) = 0; + virtual void HandleString8(span<uint8_t> chars) = 0; + virtual void HandleString16(span<uint16_t> chars) = 0; virtual void HandleBinary(std::vector<uint8_t> bytes) = 0; virtual void HandleDouble(double value) = 0; virtual void HandleInt32(int32_t value) = 0; @@ -239,8 +238,9 @@ // - UTF16 strings, including with unbalanced surrogate pairs, are encoded // as CBOR BYTE_STRING (major type 2). For such strings, the number of // bytes encoded must be even. -// - UTF8 strings (major type 3) may only have ASCII characters -// (7 bit US-ASCII). +// - UTF8 strings (major type 3) are supported. +// - 7 bit US-ASCII strings must always be encoded as UTF8 strings, not +// as UTF16 strings. // - Arbitrary byte arrays, in the inspector protocol called 'binary', // are encoded as BYTE_STRING (major type 2), prefixed with a byte // indicating base64 when rendered as JSON. @@ -257,6 +257,15 @@ // Encodes a UTF8 string |in| as STRING (major type 3). void EncodeString8(span<uint8_t> in, std::vector<uint8_t>* out); +// Encodes the given |latin1| string as STRING8. +// If any non-ASCII character is present, it will be represented +// as a 2 byte UTF8 sequence. +void EncodeFromLatin1(span<uint8_t> latin1, std::vector<uint8_t>* out); + +// Encodes the given |utf16| string as STRING8 if it's entirely US-ASCII. +// Otherwise, encodes as STRING16. +void EncodeFromUTF16(span<uint16_t> utf16, std::vector<uint8_t>* out); + // Encodes arbitrary binary data in |in| as a BYTE_STRING (major type 2) with // definitive length, prefixed with tag 22 indicating expected conversion to // base64 (see RFC 7049, Table 3 and Section 2.4.4.2).
diff --git a/third_party/inspector_protocol/lib/Values_cpp.template b/third_party/inspector_protocol/lib/Values_cpp.template index 4b4ba99..bf31babf 100644 --- a/third_party/inspector_protocol/lib/Values_cpp.template +++ b/third_party/inspector_protocol/lib/Values_cpp.template
@@ -130,13 +130,19 @@ } case CBORTokenTag::STRING8: { span<uint8_t> str = tokenizer->GetString8(); - std::unique_ptr<Value> value = StringValue::create(StringUtil::fromUTF8(str.data(), str.size())); + std::unique_ptr<Value> value = + StringValue::create(StringUtil::fromUTF8(str.data(), str.size())); tokenizer->Next(); return value; } - case CBORTokenTag::STRING16: - // NOT SUPPORTED YET. - return nullptr; + case CBORTokenTag::STRING16: { + span<uint8_t> wire = tokenizer->GetString16WireRep(); + DCHECK_EQ(wire.size() & 1, 0); + std::unique_ptr<Value> value = StringValue::create(StringUtil::fromUTF16( + reinterpret_cast<const uint16_t*>(wire.data()), wire.size() / 2)); + tokenizer->Next(); + return value; + } case CBORTokenTag::BINARY: { span<uint8_t> payload = tokenizer->GetBinary(); tokenizer->Next(); @@ -363,10 +369,37 @@ StringUtil::builderAppendQuotedString(*output, m_stringValue); } +namespace { +// This routine distinguishes between the current encoding for a given +// string |s|, and calls encoding routines that will +// - Ensure that all ASCII strings end up being encoded as UTF8 in +// the wire format - e.g., EncodeFromUTF16 will detect ASCII and +// do the (trivial) transcode to STRING8 on the wire, but if it's +// not ASCII it'll do STRING16. +// - Select a format that's cheap to convert to. E.g., we don't +// have LATIN1 on the wire, so we call EncodeFromLatin1 which +// transcodes to UTF8 if needed. +void EncodeString(const String& s, std::vector<uint8_t>* out) { + if (StringUtil::CharactersLatin1(s)) { + EncodeFromLatin1(span<uint8_t>(StringUtil::CharactersLatin1(s), + StringUtil::CharacterCount(s)), + out); + } else if (StringUtil::CharactersUTF16(s)) { + EncodeFromUTF16(span<uint16_t>(StringUtil::CharactersUTF16(s), + StringUtil::CharacterCount(s)), + out); + } else if (StringUtil::CharactersUTF8(s)) { + EncodeString8(span<uint8_t>(StringUtil::CharactersUTF8(s), + StringUtil::CharacterCount(s)), + out); + } else { + EncodeString8(span<uint8_t>(nullptr, 0), out); // Empty string. + } +} +} // namespace + void StringValue::writeBinary(std::vector<uint8_t>* bytes) const { - StringUTF8Adapter utf8(m_stringValue); - EncodeString8(span<uint8_t>(reinterpret_cast<const uint8_t*>(utf8.Data()), - utf8.length()), bytes); + EncodeString(m_stringValue, bytes); } std::unique_ptr<Value> StringValue::clone() const @@ -557,9 +590,7 @@ const String& key = m_order[i]; Dictionary::const_iterator value = m_data.find(key); DCHECK(value != m_data.cend() && value->second); - StringUTF8Adapter utf8(key); - EncodeString8(span<uint8_t>(reinterpret_cast<const uint8_t*>(utf8.Data()), - utf8.length()), bytes); + EncodeString(key, bytes); value->second->writeBinary(bytes); } bytes->push_back(EncodeStop());
diff --git a/third_party/inspector_protocol/lib/base_string_adapter_cc.template b/third_party/inspector_protocol/lib/base_string_adapter_cc.template index 5c4b8c6..24855d4 100644 --- a/third_party/inspector_protocol/lib/base_string_adapter_cc.template +++ b/third_party/inspector_protocol/lib/base_string_adapter_cc.template
@@ -185,6 +185,13 @@ string_.reserve(capacity); } +// static +String StringUtil::fromUTF16(const uint16_t* data, size_t length) { + std::string utf8; + base::UTF16ToUTF8(reinterpret_cast<const base::char16*>(data), length, &utf8); + return utf8; +} + Binary::Binary() : bytes_(new base::RefCountedBytes) {} Binary::Binary(const Binary& binary) : bytes_(binary.bytes_) {} Binary::Binary(scoped_refptr<base::RefCountedMemory> bytes) : bytes_(bytes) {}
diff --git a/third_party/inspector_protocol/lib/base_string_adapter_h.template b/third_party/inspector_protocol/lib/base_string_adapter_h.template index b0215e0..082c7c0 100644 --- a/third_party/inspector_protocol/lib/base_string_adapter_h.template +++ b/third_party/inspector_protocol/lib/base_string_adapter_h.template
@@ -32,16 +32,6 @@ using String = std::string; using ProtocolMessage = std::string; -class {{config.lib.export_macro}} StringUTF8Adapter { - public: - StringUTF8Adapter(const std::string& string) : string_(string) { } - const char* Data() const { return string_.data(); } - size_t length() const { return string_.length(); } - - private: - const std::string& string_; -}; - class {{config.lib.export_macro}} StringBuilder { public: StringBuilder(); @@ -109,6 +99,15 @@ static String fromUTF8(const uint8_t* data, size_t length) { return std::string(reinterpret_cast<const char*>(data), length); } + + static String fromUTF16(const uint16_t* data, size_t length); + + static const uint8_t* CharactersLatin1(const String& s) { return nullptr; } + static const uint8_t* CharactersUTF8(const String& s) { + return reinterpret_cast<const uint8_t*>(s.data()); + } + static const uint16_t* CharactersUTF16(const String& s) { return nullptr; } + static size_t CharacterCount(const String& s) { return s.size(); } }; // A read-only sequence of uninterpreted bytes with reference-counted storage.
diff --git a/tools/checkperms/checkperms.py b/tools/checkperms/checkperms.py index bf03586e..5abd7d2 100755 --- a/tools/checkperms/checkperms.py +++ b/tools/checkperms/checkperms.py
@@ -173,6 +173,7 @@ 'native_client_sdk/src/build_tools/sdk_tools/third_party/fancy_urllib/' '__init__.py', 'out/', + 'third_party/blink/web_tests/external/wpt/tools/third_party/', # TODO(maruel): Fix these. 'third_party/devscripts/licensecheck.pl.vanilla', 'third_party/libxml/linux/xml2-config',
diff --git a/tools/cygprofile/profile_android_startup.py b/tools/cygprofile/profile_android_startup.py index fbe4faa..ab22198 100755 --- a/tools/cygprofile/profile_android_startup.py +++ b/tools/cygprofile/profile_android_startup.py
@@ -25,6 +25,7 @@ from devil.android import device_utils from devil.android import flag_changer from devil.android import forwarder +from devil.android.ndk import abis from devil.android.sdk import intent sys.path.append(os.path.join(_SRC_PATH, 'build', 'android')) @@ -204,8 +205,15 @@ """ if device is None: devices = device_utils.DeviceUtils.HealthyDevices() - assert len(devices) == 1, 'Expected exactly one connected device' - self._device = devices[0] + assert devices, 'Expected at least one connected device' + # In case of many connected devices, favor the device running arm64. + arm_64_device = '' + for device in devices: + if device.GetABI() == abis.ARM_64: + arm_64_device = device + break + + self._device = arm_64_device if arm_64_device else devices[0] else: self._device = device_utils.DeviceUtils(device) self._cygprofile_tests = os.path.join( @@ -217,6 +225,7 @@ self._SetUpDevice() self._pregenerated_profiles = None + def SetPregeneratedProfiles(self, files): """Set pregenerated profiles.
diff --git a/tools/gritsettings/translation_expectations.pyl b/tools/gritsettings/translation_expectations.pyl index 6625aac..4e9efbe 100644 --- a/tools/gritsettings/translation_expectations.pyl +++ b/tools/gritsettings/translation_expectations.pyl
@@ -25,7 +25,7 @@ "ash/ash_strings.grd", "ash/components/ash_components_strings.grd", "chrome/android/java/strings/android_chrome_strings.grd", - "chrome/android/java/strings/android_chrome_vr_strings.grd", + "chrome/android/features/vr/java/strings/android_chrome_vr_strings.grd", "chrome/android/features/media_router/strings/android_chrome_media_router_strings.grd", "chrome/android/webapk/strings/android_webapk_strings.grd", "chrome/app/chromium_strings.grd",
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl index 2703151..6548d7f 100644 --- a/tools/mb/mb_config.pyl +++ b/tools/mb/mb_config.pyl
@@ -92,6 +92,7 @@ }, 'chromium.chrome': { + 'chromeos-amd64-generic-google-rel': 'official_cros_chrome_sdk', 'Google Chrome ChromeOS': 'official_goma_chromeos', 'Google Chrome Linux x64': 'official_goma', 'Google Chrome Mac': 'official_goma', @@ -1623,6 +1624,14 @@ 'msan', 'release_bot', ], + # The cros chrome-sdk takes care of adding needed official/branding args + # when using the sdk with '--internal'. So use the base cros_chrome_sdk + # config here, but make sure the '--internal' argument is passed to the + # SDK when entering it. + 'official_cros_chrome_sdk': [ + 'cros_chrome_sdk', + ], + 'official_goma': [ 'official', 'goma', ],
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 2e9982b..0edb6b7 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -8111,7 +8111,7 @@ </histogram> <histogram name="Autofill.HadUserOptedIn_To_WalletSyncTransportServerCards" - enum="BooleanOptedIn" expires_after="M74"> + enum="BooleanOptedIn" expires_after="M75"> <owner>sebsg@chromium.org</owner> <owner>ftirelo@chromium.org</owner> <summary> @@ -96853,17 +96853,54 @@ units="ms"> <owner>tbansal@chromium.org</owner> <summary> - Records how long after the start of a delayable request, a non-delayable - request arrived. This is the duration of time that the delayable request - should have been queued for so as to avoid any network contetion with - later-arriving non-delayable requests. + Records how long after the start of a delayable resource request, a + non-delayable resource request arrived. This is the duration of time that + the delayable request should have been queued for so as to avoid any network + contetion with later-arriving non-delayable requests. + </summary> +</histogram> + +<histogram name="ResourceScheduler.NonDelayableLastEndToNonDelayableStart" + units="ms" expires_after="M77"> + <owner>tbansal@chromium.org</owner> + <owner>dougarnett@chromium.org</owner> + <summary> + The duration of time between the end of a non-delayable resource request to + the start of the next non-delayable resource request. Recorded at the start + of all non-delayable requests that are preceeded by at least one completed + non-delayable request in the same resource scheduler client. + </summary> +</histogram> + +<histogram + name="ResourceScheduler.NonDelayableLastStartOrEndToNonDelayableStart" + units="ms" expires_after="M77"> + <owner>tbansal@chromium.org</owner> + <owner>dougarnett@chromium.org</owner> + <summary> + The duration of time between the start of a non-delayable resource request + or end of a non-delayable request (whichever happened later) to the start of + the next non-delayable resource request. Recorded at the start of all + non-delayable requests that are preceeded by at least one started + non-delayable request in the same resource scheduler client. + </summary> +</histogram> + +<histogram name="ResourceScheduler.NonDelayableLastStartToNonDelayableStart" + units="ms" expires_after="M77"> + <owner>tbansal@chromium.org</owner> + <owner>dougarnett@chromium.org</owner> + <summary> + The duration of time between the start of a non-delayable resource request + to the start of the next non-delayable resource request. Recorded at the + start of all non-delayable requests that are preceeded by at least one + started non-delayable request in the same resource scheduler client. </summary> </histogram> <histogram name="ResourceScheduler.NumDelayableRequestsInFlightAtStart.NonDelayable" units="requests"> - <owner>devdeepray@chromium.org</owner> <owner>tbansal@chromium.org</owner> <summary> Records the number of delayable requests in-flight when a non-delayable
diff --git a/tools/perf/chrome_telemetry_build/BUILD.gn b/tools/perf/chrome_telemetry_build/BUILD.gn index cf3f8a6a..49c1ca31 100644 --- a/tools/perf/chrome_telemetry_build/BUILD.gn +++ b/tools/perf/chrome_telemetry_build/BUILD.gn
@@ -83,11 +83,6 @@ group("telemetry_chrome_test_without_chrome") { testonly = true - data = [ - "//tools/perf/core/", # chrome_telemetry_build/ depends on core/ - "//tools/perf/chrome_telemetry_build/", - "//components/crash/content/tools/generate_breakpad_symbols.py", - ] data_deps = [ "//third_party/catapult:telemetry_chrome_test_support", ] @@ -97,11 +92,13 @@ "//third_party/breakpad:minidump_stackwalk", "//third_party/breakpad:dump_syms", ] - data += [ - "//build/android/devil_chromium.py", - "//build/android/stacktrace/", # Depends on devil_chromium.py. - ] } else { data_deps += [ "//third_party/catapult/telemetry:bitmaptools" ] } + + data = [ + "//tools/perf/core/", # chrome_telemetry_build/ depends on core/ + "//tools/perf/chrome_telemetry_build/", + "//components/crash/content/tools/generate_breakpad_symbols.py", + ] }
diff --git a/tools/perf/expectations.config b/tools/perf/expectations.config index ea05c3b7..8610ff9 100644 --- a/tools/perf/expectations.config +++ b/tools/perf/expectations.config
@@ -183,7 +183,6 @@ crbug.com/815181 [ Win ] oortonline_tbmv2/http://oortonline.gl/#run [ Skip ] # Benchmark: rendering.desktop -crbug.com/350692 [ All ] rendering.desktop/microsoft_performance [ Skip ] crbug.com/755556 [ Mac ] rendering.desktop/mix_blend_mode_animation_difference [ Skip ] crbug.com/755556 [ Mac ] rendering.desktop/mix_blend_mode_animation_hue [ Skip ] @@ -194,7 +193,6 @@ crbug.com/364248 [ Nexus_5 ] rendering.mobile/geo_apis [ Skip ] crbug.com/910207 [ Nexus_5X ] rendering.mobile/geo_apis [ Skip ] crbug.com/825234 [ Android_Webview ] rendering.mobile/bouncing_balls_shadow [ Skip ] -crbug.com/350692 [ All ] rendering.mobile/microsoft_performance [ Skip ] crbug.com/755556 [ Android ] rendering.mobile/balls_css_key_frame_animations_composited_transform [ Skip ] crbug.com/840964 [ Nexus_5X ] rendering.mobile/web_animations_many_keyframes [ Skip ] crbug.com/653993 [ Android_Webview ] rendering.mobile/maps_perf_test [ Skip ] @@ -222,11 +220,6 @@ crbug.com/461127 [ All ] rendering.mobile/famo_us_twitter_demo [ Skip ] crbug.com/850295 [ All ] rendering.mobile/aquarium_20k [ Skip ] crbug.com/750876 [ All ] rendering.mobile/paper_calculator_hit_test [ Skip ] -crbug.com/446332 [ All ] rendering.mobile/slide_drawer [ Skip ] -crbug.com/764825 [ All ] rendering.mobile/swipe_action [ Skip ] -crbug.com/764825 [ All ] rendering.mobile/masonry [ Skip ] -crbug.com/338838 [ All ] rendering.mobile/basic_stream [ Skip ] -crbug.com/338838 [ All ] rendering.mobile/basic_stream [ Skip ] crbug.com/873013 [ Android_Webview ] rendering.mobile/yahoo_answers_mobile_2018 [ Skip ] crbug.com/893197 [ Nexus_5X ] rendering.mobile/yahoo_answers_mobile_2018 [ Skip ] crbug.com/865400 [ Pixel_2 ] rendering.mobile/yahoo_answers_mobile_2018 [ Skip ] @@ -297,6 +290,7 @@ crbug.com/836406 [ Linux ] system_health.memory_desktop/browse:news:flipboard [ Skip ] crbug.com/836407 [ Linux ] system_health.memory_desktop/browse:tools:maps [ Skip ] crbug.com/837397 [ Linux ] system_health.memory_desktop/load_accessibility:shopping:amazon [ Skip ] +crbug.com/934885 [ Linux ] system_health.memory_desktop/load_accessibility:media:wikipedia:2018 [ Skip ] crbug.com/869118 [ Linux ] system_health.memory_desktop/long_running:tools:gmail-background [ Skip ] crbug.com/836447 [ ChromeOS ] system_health.memory_desktop/multitab:misc:typical24 [ Skip ] crbug.com/799734 [ Win ] system_health.memory_desktop/browse:media:tumblr [ Skip ]
diff --git a/ui/accessibility/platform/ax_platform_node_win.cc b/ui/accessibility/platform/ax_platform_node_win.cc index f1e18e1..3c8e387 100644 --- a/ui/accessibility/platform/ax_platform_node_win.cc +++ b/ui/accessibility/platform/ax_platform_node_win.cc
@@ -3674,7 +3674,8 @@ break; case UIA_FrameworkIdPropertyId: - // TODO(suproteem) + V_VT(result) = VT_BSTR; + V_BSTR(result) = SysAllocString(FRAMEWORK_ID); break; case UIA_HasKeyboardFocusPropertyId:
diff --git a/ui/accessibility/platform/ax_platform_node_win.h b/ui/accessibility/platform/ax_platform_node_win.h index a321f51..bc03021 100644 --- a/ui/accessibility/platform/ax_platform_node_win.h +++ b/ui/accessibility/platform/ax_platform_node_win.h
@@ -889,6 +889,11 @@ void** object) override; protected: + // This is hard-coded; all products based on the Chromium engine will have the + // same framework name, so that assistive technology can detect any + // Chromium-based product. + static constexpr const base::char16* FRAMEWORK_ID = L"Chrome"; + AXPlatformNodeWin(); int MSAAState() const;
diff --git a/ui/accessibility/platform/ax_platform_node_win_unittest.cc b/ui/accessibility/platform/ax_platform_node_win_unittest.cc index bc0df614..d2ac878f 100644 --- a/ui/accessibility/platform/ax_platform_node_win_unittest.cc +++ b/ui/accessibility/platform/ax_platform_node_win_unittest.cc
@@ -3400,6 +3400,18 @@ child_node2, UIA_FlowsFromPropertyId, UIA_NamePropertyId, expected_names); } +TEST_F(AXPlatformNodeWinTest, TestUIAGetPropertyValueFrameworkId) { + AXNodeData root_ax_node_data; + root_ax_node_data.id = 0; + root_ax_node_data.role = ax::mojom::Role::kRootWebArea; + Init(root_ax_node_data); + + ComPtr<IRawElementProviderSimple> root_raw_element_provider_simple = + GetRootIRawElementProviderSimple(); + EXPECT_UIA_BSTR_EQ(root_raw_element_provider_simple, + UIA_FrameworkIdPropertyId, L"Chrome"); +} + TEST_F(AXPlatformNodeWinTest, TestGetPropertyValue_LabeledByTest) { AXNodeData root; root.role = ax::mojom::Role::kListItem;
diff --git a/ui/android/delegated_frame_host_android.cc b/ui/android/delegated_frame_host_android.cc index 2d82cc8..67ebc8c 100644 --- a/ui/android/delegated_frame_host_android.cc +++ b/ui/android/delegated_frame_host_android.cc
@@ -6,7 +6,6 @@ #include "base/android/build_info.h" #include "base/bind.h" -#include "base/debug/stack_trace.h" #include "base/logging.h" #include "cc/layers/solid_color_layer.h" #include "cc/layers/surface_layer.h"
diff --git a/ui/base/ui_base_switches.cc b/ui/base/ui_base_switches.cc index c2d4f25..6317c146 100644 --- a/ui/base/ui_base_switches.cc +++ b/ui/base/ui_base_switches.cc
@@ -44,10 +44,6 @@ // Enables touch event based drag and drop. const char kEnableTouchDragDrop[] = "enable-touch-drag-drop"; -// Enables touchable app context menus. -const char kEnableTouchableAppContextMenu[] = - "enable-touchable-app-context-menus"; - // Forces the caption style for WebVTT captions. const char kForceCaptionStyle[] = "force-caption-style";
diff --git a/ui/base/ui_base_switches.h b/ui/base/ui_base_switches.h index 2162f1e..16609c6 100644 --- a/ui/base/ui_base_switches.h +++ b/ui/base/ui_base_switches.h
@@ -26,7 +26,6 @@ UI_BASE_EXPORT extern const char kDisableTouchAdjustment[]; UI_BASE_EXPORT extern const char kDisableTouchDragDrop[]; UI_BASE_EXPORT extern const char kEnableTouchDragDrop[]; -UI_BASE_EXPORT extern const char kEnableTouchableAppContextMenu[]; UI_BASE_EXPORT extern const char kForceCaptionStyle[]; UI_BASE_EXPORT extern const char kForceDarkMode[]; UI_BASE_EXPORT extern const char kForceHighContrast[];
diff --git a/ui/base/ui_base_switches_util.cc b/ui/base/ui_base_switches_util.cc index ad8161db..e153ec9 100644 --- a/ui/base/ui_base_switches_util.cc +++ b/ui/base/ui_base_switches_util.cc
@@ -20,9 +20,4 @@ #endif } -bool IsTouchableAppContextMenuEnabled() { - return base::CommandLine::ForCurrentProcess()->HasSwitch( - kEnableTouchableAppContextMenu); -} - } // namespace switches
diff --git a/ui/base/ui_base_switches_util.h b/ui/base/ui_base_switches_util.h index c734787..2b6af8c 100644 --- a/ui/base/ui_base_switches_util.h +++ b/ui/base/ui_base_switches_util.h
@@ -11,10 +11,6 @@ UI_BASE_EXPORT bool IsTouchDragDropEnabled(); -// Returns whether the touchable app context menu switch has been set. Prefer -// features::IsTouchableAppContextMenuEnabled(). -UI_BASE_EXPORT bool IsTouchableAppContextMenuEnabled(); - } // namespace switches #endif // UI_BASE_UI_BASE_SWITCHES_UTIL_H_
diff --git a/ui/gfx/transform_util.cc b/ui/gfx/transform_util.cc index 6c5833d..003ecef5 100644 --- a/ui/gfx/transform_util.cc +++ b/ui/gfx/transform_util.cc
@@ -210,6 +210,114 @@ combined); } +bool Is2dTransform(const Transform& transform) { + const SkMatrix44 matrix = transform.matrix(); + if (matrix.hasPerspective()) + return false; + + return matrix.get(2, 0) == 0 && matrix.get(2, 1) == 0 && + matrix.get(0, 2) == 0 && matrix.get(1, 2) == 0 && + matrix.get(2, 2) == 1 && matrix.get(3, 2) == 0 && + matrix.get(2, 3) == 0; +} + +bool Decompose2DTransform(DecomposedTransform* decomp, + const Transform& transform) { + if (!Is2dTransform(transform)) { + return false; + } + + const SkMatrix44 matrix = transform.matrix(); + double m11 = matrix.getDouble(0, 0); + double m21 = matrix.getDouble(0, 1); + double m12 = matrix.getDouble(1, 0); + double m22 = matrix.getDouble(1, 1); + + double determinant = m11 * m22 - m12 * m21; + // Test for matrix being singular. + if (determinant == 0) { + return false; + } + + // Translation transform. + // [m11 m21 0 m41] [1 0 0 Tx] [m11 m21 0 0] + // [m12 m22 0 m42] = [0 1 0 Ty] [m12 m22 0 0] + // [ 0 0 1 0 ] [0 0 1 0 ] [ 0 0 1 0] + // [ 0 0 0 1 ] [0 0 0 1 ] [ 0 0 0 1] + decomp->translate[0] = matrix.get(0, 3); + decomp->translate[1] = matrix.get(1, 3); + + // For the remainder of the decomposition process, we can focus on the upper + // 2x2 submatrix + // [m11 m21] = [cos(R) -sin(R)] [1 K] [Sx 0 ] + // [m12 m22] [sin(R) cos(R)] [0 1] [0 Sy] + // = [Sx*cos(R) Sy*(K*cos(R) - sin(R))] + // [Sx*sin(R) Sy*(K*sin(R) + cos(R))] + + // Determine sign of the x and y scale. + if (determinant < 0) { + // If the determinant is negative, we need to flip either the x or y scale. + // Flipping both is equivalent to rotating by 180 degrees. + if (m11 < m22) { + decomp->scale[0] *= -1; + } else { + decomp->scale[1] *= -1; + } + } + + // X Scale. + // m11^2 + m12^2 = Sx^2*(cos^2(R) + sin^2(R)) = Sx^2. + // Sx = +/-sqrt(m11^2 + m22^2) + decomp->scale[0] *= sqrt(m11 * m11 + m12 * m12); + m11 /= decomp->scale[0]; + m12 /= decomp->scale[0]; + + // Post normalization, the submatrix is now of the form: + // [m11 m21] = [cos(R) Sy*(K*cos(R) - sin(R))] + // [m12 m22] [sin(R) Sy*(K*sin(R) + cos(R))] + + // XY Shear. + // m11 * m21 + m12 * m22 = Sy*K*cos^2(R) - Sy*sin(R)*cos(R) + + // Sy*K*sin^2(R) + Sy*cos(R)*sin(R) + // = Sy*K + double scaledShear = m11 * m21 + m12 * m22; + m21 -= m11 * scaledShear; + m22 -= m12 * scaledShear; + + // Post normalization, the submatrix is now of the form: + // [m11 m21] = [cos(R) -Sy*sin(R)] + // [m12 m22] [sin(R) Sy*cos(R)] + + // Y Scale. + // Similar process to determining x-scale. + decomp->scale[1] *= sqrt(m21 * m21 + m22 * m22); + m21 /= decomp->scale[1]; + m22 /= decomp->scale[1]; + decomp->skew[0] = scaledShear / decomp->scale[1]; + + // Rotation transform. + // [1-2(yy+zz) 2(xy-zw) 2(xz+yw) ] [cos(R) -sin(R) 0] + // [2(xy+zw) 1-2(xx+zz) 2(yz-xw) ] = [sin(R) cos(R) 0] + // [2(xz-yw) 2*(yz+xw) 1-2(xx+yy)] [ 0 0 1] + // Comparing terms, we can conclude that x = y = 0. + // [1-2zz -2zw 0] [cos(R) -sin(R) 0] + // [ 2zw 1-2zz 0] = [sin(R) cos(R) 0] + // [ 0 0 1] [ 0 0 1] + // cos(R) = 1 - 2*z^2 + // From the double angle formula: cos(2a) = 1 - 2 sin(a)^2 + // cos(R) = 1 - 2*sin(R/2)^2 = 1 - 2*z^2 ==> z = sin(R/2) + // sin(R) = 2*z*w + // But sin(2a) = 2 sin(a) cos(a) + // sin(R) = 2 sin(R/2) cos(R/2) = 2*z*w ==> w = cos(R/2) + double angle = atan2(m12, m11); + decomp->quaternion.set_x(0); + decomp->quaternion.set_y(0); + decomp->quaternion.set_z(sin(0.5 * angle)); + decomp->quaternion.set_w(cos(0.5 * angle)); + + return true; +} + } // namespace Transform GetScaleTransform(const Point& anchor, float scale) { @@ -252,6 +360,9 @@ if (!decomp) return false; + if (Decompose2DTransform(decomp, transform)) + return true; + // We'll operate on a copy of the matrix. SkMatrix44 matrix = transform.matrix();
diff --git a/ui/gfx/transform_util_unittest.cc b/ui/gfx/transform_util_unittest.cc index 2bcaae74..33f66f9 100644 --- a/ui/gfx/transform_util_unittest.cc +++ b/ui/gfx/transform_util_unittest.cc
@@ -6,6 +6,7 @@ #include <stddef.h> +#include "base/numerics/math_constants.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/gfx/geometry/point.h" #include "ui/gfx/geometry/point3_f.h" @@ -14,6 +15,8 @@ namespace gfx { namespace { +#define EXPECT_APPROX_EQ(val1, val2) EXPECT_NEAR(val1, val2, 1e-6); + TEST(TransformUtilTest, GetScaleTransform) { const Point kAnchor(20, 40); const float kScale = 0.5f; @@ -231,38 +234,92 @@ TEST(TransformUtilTest, RoundTripTest) { // rotateZ(90deg) - EXPECT_NEAR(0, ComputeDecompRecompError(Transform(0, 1, -1, 0, 0, 0)), 1e-6); + EXPECT_APPROX_EQ(0, ComputeDecompRecompError(Transform(0, 1, -1, 0, 0, 0))); // rotateZ(180deg) // Edge case where w = 0. - EXPECT_NEAR(0, ComputeDecompRecompError(Transform(-1, 0, 0, -1, 0, 0)), 1e-6); + EXPECT_APPROX_EQ(0, ComputeDecompRecompError(Transform(-1, 0, 0, -1, 0, 0))); // rotateX(90deg) rotateY(90deg) rotateZ(90deg) // [1 0 0][ 0 0 1][0 -1 0] [0 0 1][0 -1 0] [0 0 1] // [0 0 -1][ 0 1 0][1 0 0] = [1 0 0][1 0 0] = [0 -1 0] // [0 1 0][-1 0 0][0 0 1] [0 1 0][0 0 1] [1 0 0] // This test case leads to Gimbal lock when using Euler angles. - EXPECT_NEAR(0, - ComputeDecompRecompError( - Transform(0, 0, 1, 0, 0, -1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1)), - 1e-6); + EXPECT_APPROX_EQ(0, ComputeDecompRecompError(Transform( + 0, 0, 1, 0, 0, -1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1))); // Quaternion matrices with 0 off-diagonal elements, and negative trace. // Stress tests handling of degenerate cases in computing quaternions. // Validates fix for https://crbug.com/647554. - EXPECT_NEAR(0, ComputeDecompRecompError(Transform(1, 1, 1, 0, 0, 0)), 1e-6); - EXPECT_NEAR(0, - ComputeDecompRecompError( - Transform(-1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1)), - 1e-6); - EXPECT_NEAR(0, - ComputeDecompRecompError( - Transform(1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1)), - 1e-6); - EXPECT_NEAR(0, - ComputeDecompRecompError( - Transform(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1)), - 1e-6); + EXPECT_APPROX_EQ(0, ComputeDecompRecompError(Transform(1, 1, 1, 0, 0, 0))); + EXPECT_APPROX_EQ(0, ComputeDecompRecompError(Transform( + -1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1))); + EXPECT_APPROX_EQ(0, ComputeDecompRecompError(Transform( + 1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1))); + EXPECT_APPROX_EQ(0, ComputeDecompRecompError(Transform( + 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1))); +} + +TEST(TransformUtilTest, Transform2D) { + // The spec covering interpolation of 2D matrix transforms calls for inverting + // one of the axis in the case of a negative determinant. This differs from + // the general 3D spec, which calls for flipping all of the scales when the + // determinant is negative. Flipping all scales not only introduces rotation + // in the case of a trivial scale inversion, but causes transformed objects + // to needlessly shrink and grow as they transform through scale = 0 along + // multiple axes. 2D transformation matrices should follow the 2D spec + // regarding matrix decomposition. + DecomposedTransform decompFlipX; + DecomposeTransform(&decompFlipX, Transform(-1, 0, 0, 1, 0, 0)); + EXPECT_APPROX_EQ(-1, decompFlipX.scale[0]); + EXPECT_APPROX_EQ(1, decompFlipX.scale[1]); + EXPECT_APPROX_EQ(1, decompFlipX.scale[2]); + EXPECT_APPROX_EQ(0, decompFlipX.quaternion.z()); + EXPECT_APPROX_EQ(1, decompFlipX.quaternion.w()); + + DecomposedTransform decompFlipY; + DecomposeTransform(&decompFlipY, Transform(1, 0, 0, -1, 0, 0)); + EXPECT_APPROX_EQ(1, decompFlipY.scale[0]); + EXPECT_APPROX_EQ(-1, decompFlipY.scale[1]); + EXPECT_APPROX_EQ(1, decompFlipY.scale[2]); + EXPECT_APPROX_EQ(0, decompFlipY.quaternion.z()); + EXPECT_APPROX_EQ(1, decompFlipY.quaternion.w()); + + DecomposedTransform decompR180; + DecomposeTransform(&decompR180, Transform(-1, 0, 0, -1, 0, 0)); + EXPECT_APPROX_EQ(1, decompR180.scale[0]); + EXPECT_APPROX_EQ(1, decompR180.scale[1]); + EXPECT_APPROX_EQ(1, decompR180.scale[2]); + EXPECT_APPROX_EQ(1, decompR180.quaternion.z()); + EXPECT_APPROX_EQ(0, decompR180.quaternion.w()); + + DecomposedTransform decompR90; + DecomposeTransform(&decompR180, Transform(0, -1, 1, 0, 0, 0)); + EXPECT_APPROX_EQ(1, decompR180.scale[0]); + EXPECT_APPROX_EQ(1, decompR180.scale[1]); + EXPECT_APPROX_EQ(1, decompR180.scale[2]); + EXPECT_APPROX_EQ(1 / sqrt(2), decompR180.quaternion.z()); + EXPECT_APPROX_EQ(1 / sqrt(2), decompR180.quaternion.w()); + + DecomposedTransform decompR90Translate; + DecomposeTransform(&decompR90Translate, Transform(0, -1, 1, 0, -1, 1)); + EXPECT_APPROX_EQ(1, decompR90Translate.scale[0]); + EXPECT_APPROX_EQ(1, decompR90Translate.scale[1]); + EXPECT_APPROX_EQ(1, decompR90Translate.scale[2]); + EXPECT_APPROX_EQ(-1, decompR90Translate.translate[0]); + EXPECT_APPROX_EQ(1, decompR90Translate.translate[1]); + EXPECT_APPROX_EQ(0, decompR90Translate.translate[2]); + EXPECT_APPROX_EQ(1 / sqrt(2), decompR90Translate.quaternion.z()); + EXPECT_APPROX_EQ(1 / sqrt(2), decompR90Translate.quaternion.w()); + + DecomposedTransform decompSkewRotate; + DecomposeTransform(&decompR90Translate, Transform(1, 1, 1, 0, 0, 0)); + EXPECT_APPROX_EQ(sqrt(2), decompR90Translate.scale[0]); + EXPECT_APPROX_EQ(-1 / sqrt(2), decompR90Translate.scale[1]); + EXPECT_APPROX_EQ(1, decompR90Translate.scale[2]); + EXPECT_APPROX_EQ(-1, decompR90Translate.skew[0]); + EXPECT_APPROX_EQ(sin(base::kPiDouble / 8), decompR90Translate.quaternion.z()); + EXPECT_APPROX_EQ(cos(base::kPiDouble / 8), decompR90Translate.quaternion.w()); } } // namespace
diff --git a/ui/views/BUILD.gn b/ui/views/BUILD.gn index a5d663fe..2c29d60 100644 --- a/ui/views/BUILD.gn +++ b/ui/views/BUILD.gn
@@ -618,6 +618,7 @@ "accessibility/ax_root_obj_wrapper.h", "accessibility/ax_tree_source_views.h", "accessibility/ax_view_obj_wrapper.h", + "accessibility/ax_virtual_view_wrapper.h", "accessibility/ax_widget_obj_wrapper.h", "accessibility/ax_window_obj_wrapper.h", "controls/native/native_view_host_aura.h", @@ -654,6 +655,7 @@ "accessibility/ax_root_obj_wrapper.cc", "accessibility/ax_tree_source_views.cc", "accessibility/ax_view_obj_wrapper.cc", + "accessibility/ax_virtual_view_wrapper.cc", "accessibility/ax_widget_obj_wrapper.cc", "accessibility/ax_window_obj_wrapper.cc", "controls/menu/display_change_listener_aura.cc",
diff --git a/ui/views/accessibility/ax_aura_obj_cache.cc b/ui/views/accessibility/ax_aura_obj_cache.cc index 268e227..5fdbf125 100644 --- a/ui/views/accessibility/ax_aura_obj_cache.cc +++ b/ui/views/accessibility/ax_aura_obj_cache.cc
@@ -14,6 +14,7 @@ #include "ui/views/accessibility/ax_view_obj_wrapper.h" #include "ui/views/accessibility/ax_widget_obj_wrapper.h" #include "ui/views/accessibility/ax_window_obj_wrapper.h" +#include "ui/views/accessibility/view_accessibility.h" #include "ui/views/view.h" #include "ui/views/widget/widget.h" #include "ui/views/widget/widget_delegate.h" @@ -103,8 +104,14 @@ AXAuraObjWrapper* AXAuraObjCache::GetFocus() { View* focused_view = GetFocusedView(); - if (focused_view) + if (focused_view) { + const ViewAccessibility& view_accessibility = + focused_view->GetViewAccessibility(); + if (view_accessibility.FocusedVirtualChild()) + return view_accessibility.FocusedVirtualChild()->GetWrapper(); + return GetOrCreate(focused_view); + } return nullptr; }
diff --git a/ui/views/accessibility/ax_tree_source_views.cc b/ui/views/accessibility/ax_tree_source_views.cc index 078a89f1..b7d3fc2 100644 --- a/ui/views/accessibility/ax_tree_source_views.cc +++ b/ui/views/accessibility/ax_tree_source_views.cc
@@ -14,6 +14,7 @@ #include "ui/gfx/transform.h" #include "ui/views/accessibility/ax_aura_obj_cache.h" #include "ui/views/accessibility/ax_aura_obj_wrapper.h" +#include "ui/views/accessibility/ax_virtual_view.h" namespace views { @@ -63,7 +64,14 @@ // Root might not be in the cache. if (id == root->GetUniqueId()) return root; - return AXAuraObjCache::GetInstance()->Get(id); + AXAuraObjWrapper* wrapper = AXAuraObjCache::GetInstance()->Get(id); + + // We must do a lookup in AXVirtualView as well if the main cache doesn't hold + // this node. + if (!wrapper && AXVirtualView::GetFromId(id)) + return AXVirtualView::GetFromId(id)->GetWrapper(); + + return wrapper; } int32_t AXTreeSourceViews::GetId(AXAuraObjWrapper* node) const {
diff --git a/ui/views/accessibility/ax_view_obj_wrapper.cc b/ui/views/accessibility/ax_view_obj_wrapper.cc index 2100f6b..f5fbf1c 100644 --- a/ui/views/accessibility/ax_view_obj_wrapper.cc +++ b/ui/views/accessibility/ax_view_obj_wrapper.cc
@@ -8,6 +8,7 @@ #include "ui/accessibility/ax_node_data.h" #include "ui/accessibility/platform/ax_unique_id.h" #include "ui/views/accessibility/ax_aura_obj_cache.h" +#include "ui/views/accessibility/ax_virtual_view.h" #include "ui/views/accessibility/view_accessibility.h" #include "ui/views/view.h" #include "ui/views/widget/widget.h" @@ -50,7 +51,8 @@ if (!view_) return; - if (view_->GetViewAccessibility().IsLeaf()) + const ViewAccessibility& view_accessibility = view_->GetViewAccessibility(); + if (view_accessibility.IsLeaf()) return; // TODO(dtseng): Need to handle |Widget| child of |View|. @@ -61,6 +63,11 @@ AXAuraObjWrapper* child = aura_obj_cache_->GetOrCreate(view_->child_at(i)); out_children->push_back(child); } + + for (int i = 0; i < view_accessibility.virtual_child_count(); ++i) { + out_children->push_back( + view_accessibility.virtual_child_at(i)->GetWrapper()); + } } void AXViewObjWrapper::Serialize(ui::AXNodeData* out_node_data) {
diff --git a/ui/views/accessibility/ax_virtual_view.cc b/ui/views/accessibility/ax_virtual_view.cc index 31a322c1..eb49573 100644 --- a/ui/views/accessibility/ax_virtual_view.cc +++ b/ui/views/accessibility/ax_virtual_view.cc
@@ -7,9 +7,11 @@ #include <stdint.h> #include <algorithm> +#include <map> #include <utility> #include "base/callback.h" +#include "base/no_destructor.h" #include "ui/accessibility/ax_action_data.h" #include "ui/accessibility/ax_tree_data.h" #include "ui/accessibility/platform/ax_platform_node.h" @@ -20,11 +22,29 @@ namespace views { +// Tracks all virtual ax views. +std::map<int32_t, AXVirtualView*>& GetIdMap() { + static base::NoDestructor<std::map<int32_t, AXVirtualView*>> id_to_obj_map; + return *id_to_obj_map; +} + // static const char AXVirtualView::kViewClassName[] = "AXVirtualView"; +// static +AXVirtualView* AXVirtualView::GetFromId(int32_t id) { + auto& id_map = GetIdMap(); + const auto& it = id_map.find(id); + return it != id_map.end() ? it->second : nullptr; +} + AXVirtualView::AXVirtualView() : parent_view_(nullptr), virtual_parent_view_(nullptr) { +#if defined(USE_AURA) + wrapper_ = std::make_unique<AXVirtualViewWrapper>(this); +#endif + + GetIdMap()[unique_id_.Get()] = this; ax_platform_node_ = ui::AXPlatformNode::Create(this); DCHECK(ax_platform_node_); custom_data_.AddStringAttribute(ax::mojom::StringAttribute::kClassName, @@ -32,6 +52,7 @@ } AXVirtualView::~AXVirtualView() { + GetIdMap().erase(unique_id_.Get()); DCHECK(!parent_view_ || !virtual_parent_view_) << "Either |parent_view_| or |virtual_parent_view_| could be set but " "not both."; @@ -47,6 +68,11 @@ if (view->virtual_parent_view_ == this) return; AddChildViewAt(std::move(view), GetChildCount()); + + if (GetOwnerView()) { + GetOwnerView()->NotifyAccessibilityEvent(ax::mojom::Event::kChildrenChanged, + false); + } } void AXVirtualView::AddChildViewAt(std::unique_ptr<AXVirtualView> view, @@ -64,6 +90,10 @@ view->virtual_parent_view_ = this; children_.insert(children_.begin() + index, std::move(view)); + if (GetOwnerView()) { + GetOwnerView()->NotifyAccessibilityEvent(ax::mojom::Event::kChildrenChanged, + false); + } } void AXVirtualView::ReorderChildView(AXVirtualView* view, int index) { @@ -84,6 +114,9 @@ std::unique_ptr<AXVirtualView> child = std::move(children_[cur_index]); children_.erase(children_.begin() + cur_index); children_.insert(children_.begin() + index, std::move(child)); + + GetOwnerView()->NotifyAccessibilityEvent(ax::mojom::Event::kChildrenChanged, + false); } std::unique_ptr<AXVirtualView> AXVirtualView::RemoveChildView( @@ -106,12 +139,23 @@ children_.erase(children_.begin() + cur_index); child->virtual_parent_view_ = nullptr; child->populate_data_callback_.Reset(); + + if (GetOwnerView()) { + GetOwnerView()->NotifyAccessibilityEvent(ax::mojom::Event::kChildrenChanged, + false); + } + return child; } void AXVirtualView::RemoveAllChildViews() { while (!children_.empty()) RemoveChildView(children_.back().get()); + + if (GetOwnerView()) { + GetOwnerView()->NotifyAccessibilityEvent(ax::mojom::Event::kChildrenChanged, + false); + } } const AXVirtualView* AXVirtualView::child_at(int index) const { @@ -177,6 +221,9 @@ // made to the data that users of this class will be manipulating. static ui::AXNodeData node_data; node_data = custom_data_; + + node_data.id = GetUniqueId().Get(); + if (!GetOwnerView() || !GetOwnerView()->enabled()) node_data.SetRestriction(ax::mojom::Restriction::kDisabled); @@ -291,4 +338,8 @@ return nullptr; } +AXVirtualViewWrapper* AXVirtualView::GetWrapper() const { + return wrapper_.get(); +} + } // namespace views
diff --git a/ui/views/accessibility/ax_virtual_view.h b/ui/views/accessibility/ax_virtual_view.h index 02206520..c2ae08c 100644 --- a/ui/views/accessibility/ax_virtual_view.h +++ b/ui/views/accessibility/ax_virtual_view.h
@@ -23,6 +23,13 @@ #include "ui/gfx/native_widget_types.h" #include "ui/views/views_export.h" +#if defined(USE_AURA) +#include "ui/views/accessibility/ax_virtual_view_wrapper.h" +#else +// Currently unused. +class AXVirtualViewWrapper {}; +#endif + namespace ui { struct AXActionData; @@ -45,6 +52,8 @@ // ViewAccessibility or an AXVirtualView. class VIEWS_EXPORT AXVirtualView : public ui::AXPlatformNodeDelegateBase { public: + static AXVirtualView* GetFromId(int32_t id); + AXVirtualView(); ~AXVirtualView() override; @@ -129,7 +138,12 @@ bool IsOffscreen() const override; const ui::AXUniqueId& GetUniqueId() const override; - protected: + // Gets the real View that owns our shallowest virtual ancestor,, if any. + View* GetOwnerView() const; + + // Gets a wrapper suitable for use with tree sources. + AXVirtualViewWrapper* GetWrapper() const; + // Handle a request from assistive technology to perform an action on this // virtual view. Returns true on success, but note that the success/failure is // not propagated to the client that requested the action, since the @@ -149,9 +163,6 @@ parent_view_ = view_accessibility; } - // Gets the real View that owns our shallowest virtual ancestor,, if any. - View* GetOwnerView() const; - // We own this, but it is reference-counted on some platforms so we can't use // a unique_ptr. It is destroyed in the destructor. ui::AXPlatformNode* ax_platform_node_; @@ -172,6 +183,8 @@ base::RepeatingCallback<void(const View&, ui::AXNodeData*)> populate_data_callback_; + std::unique_ptr<AXVirtualViewWrapper> wrapper_; + friend class ViewAccessibility; DISALLOW_COPY_AND_ASSIGN(AXVirtualView); };
diff --git a/ui/views/accessibility/ax_virtual_view_wrapper.cc b/ui/views/accessibility/ax_virtual_view_wrapper.cc new file mode 100644 index 0000000..5e637c2 --- /dev/null +++ b/ui/views/accessibility/ax_virtual_view_wrapper.cc
@@ -0,0 +1,51 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ui/views/accessibility/ax_virtual_view_wrapper.h" + +#include "ui/views/accessibility/ax_aura_obj_cache.h" +#include "ui/views/accessibility/ax_view_obj_wrapper.h" +#include "ui/views/accessibility/ax_virtual_view.h" + +namespace views { + +AXVirtualViewWrapper::AXVirtualViewWrapper(AXVirtualView* virtual_view) + : virtual_view_(virtual_view) {} + +AXVirtualViewWrapper::~AXVirtualViewWrapper() = default; + +bool AXVirtualViewWrapper::IsIgnored() { + return false; +} + +AXAuraObjWrapper* AXVirtualViewWrapper::GetParent() { + if (virtual_view_->virtual_parent_view()) + return virtual_view_->virtual_parent_view()->GetWrapper(); + if (virtual_view_->GetOwnerView()) + return AXAuraObjCache::GetInstance()->GetOrCreate( + virtual_view_->GetOwnerView()); + + return nullptr; +} + +void AXVirtualViewWrapper::GetChildren( + std::vector<AXAuraObjWrapper*>* out_children) { + for (int i = 0; i < virtual_view_->GetChildCount(); ++i) + out_children->push_back(virtual_view_->child_at(i)->GetWrapper()); +} + +void AXVirtualViewWrapper::Serialize(ui::AXNodeData* out_node_data) { + *out_node_data = virtual_view_->GetData(); +} + +int32_t AXVirtualViewWrapper::GetUniqueId() const { + return virtual_view_->GetUniqueId().Get(); +} + +bool AXVirtualViewWrapper::HandleAccessibleAction( + const ui::AXActionData& action) { + return virtual_view_->HandleAccessibleAction(action); +} + +} // namespace views
diff --git a/ui/views/accessibility/ax_virtual_view_wrapper.h b/ui/views/accessibility/ax_virtual_view_wrapper.h new file mode 100644 index 0000000..8e03614 --- /dev/null +++ b/ui/views/accessibility/ax_virtual_view_wrapper.h
@@ -0,0 +1,39 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef UI_VIEWS_ACCESSIBILITY_AX_VIRTUAL_VIEW_WRAPPER_H_ +#define UI_VIEWS_ACCESSIBILITY_AX_VIRTUAL_VIEW_WRAPPER_H_ + +#include <vector> + +#include "ui/views/accessibility/ax_aura_obj_wrapper.h" +#include "ui/views/views_export.h" + +namespace views { +class AXVirtualView; + +// Wraps (and adapts) an AXVirtualView for use with AXTreeSourceViews. +class AXVirtualViewWrapper : public AXAuraObjWrapper { + public: + explicit AXVirtualViewWrapper(AXVirtualView* virtual_view); + ~AXVirtualViewWrapper() override; + + // AXAuraObjWrapper: + bool IsIgnored() override; + AXAuraObjWrapper* GetParent() override; + void GetChildren(std::vector<AXAuraObjWrapper*>* out_children) override; + void Serialize(ui::AXNodeData* out_node_data) override; + int32_t GetUniqueId() const override; + bool HandleAccessibleAction(const ui::AXActionData& action) override; + + private: + // Weak. + AXVirtualView* const virtual_view_; + + DISALLOW_COPY_AND_ASSIGN(AXVirtualViewWrapper); +}; + +} // namespace views + +#endif // UI_VIEWS_ACCESSIBILITY_AX_VIRTUAL_VIEW_WRAPPER_H_
diff --git a/ui/views/controls/button/label_button.h b/ui/views/controls/button/label_button.h index 01dfb90..46f81be3 100644 --- a/ui/views/controls/button/label_button.h +++ b/ui/views/controls/button/label_button.h
@@ -191,7 +191,7 @@ // A separate view is necessary to hold the ink drop layer so that it can // be stacked below |image_| and on top of |label_|, without resorting to // drawing |label_| on a layer (which can mess with subpixel anti-aliasing). - InkDropContainerView* ink_drop_container_; + InkDropContainerView* const ink_drop_container_; // The cached font lists in the normal and default button style. The latter // may be bold.
diff --git a/ui/views/corewm/tooltip_win.cc b/ui/views/corewm/tooltip_win.cc index 3acf4bae..e6e1fd9 100644 --- a/ui/views/corewm/tooltip_win.cc +++ b/ui/views/corewm/tooltip_win.cc
@@ -4,7 +4,6 @@ #include "ui/views/corewm/tooltip_win.h" -#include "base/debug/stack_trace.h" #include "base/i18n/rtl.h" #include "base/logging.h" #include "base/win/windowsx_shim.h"
diff --git a/ui/views/widget/desktop_aura/x11_desktop_window_move_client.cc b/ui/views/widget/desktop_aura/x11_desktop_window_move_client.cc index 52b2985e..a253702e 100644 --- a/ui/views/widget/desktop_aura/x11_desktop_window_move_client.cc +++ b/ui/views/widget/desktop_aura/x11_desktop_window_move_client.cc
@@ -4,7 +4,6 @@ #include "ui/views/widget/desktop_aura/x11_desktop_window_move_client.h" -#include "base/debug/stack_trace.h" #include "base/run_loop.h" #include "ui/aura/env.h" #include "ui/aura/window.h"
diff --git a/ui/webui/resources/cr_elements/cr_radio_group/cr_radio_group.js b/ui/webui/resources/cr_elements/cr_radio_group/cr_radio_group.js index 12f2edc..fb367837 100644 --- a/ui/webui/resources/cr_elements/cr_radio_group/cr_radio_group.js +++ b/ui/webui/resources/cr_elements/cr_radio_group/cr_radio_group.js
@@ -21,11 +21,13 @@ type: Boolean, value: false, reflectToAttribute: true, + observer: 'update_', }, selected: { type: String, notify: true, + observer: 'update_', }, selectable: { @@ -48,11 +50,8 @@ click: 'onClick_', }, - observers: [ - 'update_(disabled, selected)', - ], - hostAttributes: { + 'aria-disabled': 'false', role: 'radiogroup', }, @@ -247,11 +246,13 @@ this.buttons_.forEach(radio => { radio.checked = this.selected != undefined && radio.name == this.selected; - const canBeFocused = - radio.checked && !this.disabled && isEnabled(radio); + const disabled = this.disabled || !isEnabled(radio); + const canBeFocused = radio.checked && !disabled; noneMadeFocusable &= !canBeFocused; radio.setAttribute('tabindex', canBeFocused ? '0' : '-1'); + radio.setAttribute('aria-disabled', `${disabled}`); }); + this.setAttribute('aria-disabled', `${this.disabled}`); if (noneMadeFocusable && !this.disabled) { const focusable = this.buttons_.find(isEnabled); if (focusable) {