diff --git a/DEPS b/DEPS index 43351a40..fb1d3bb 100644 --- a/DEPS +++ b/DEPS
@@ -235,15 +235,15 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Skia # and whatever else without interference from each other. - 'skia_revision': 'f32ad08ac4a7047e04706be97191ad0a976e6b27', + 'skia_revision': '87a0078b890928828c08790bb2c846724234edcb', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. - 'v8_revision': '2324d83cc4a144a49c83c533dd6a80931ec166b9', + 'v8_revision': '35eaec5cf5c322ec9211699a68c465f6d3415bbb', # 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': 'fbf8d1ea1b5c55c9616df2ab9935b8660dc8bb8a', + 'angle_revision': 'bcc8970347f1a51b650e4a79f5e4ddec11047e79', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. @@ -310,7 +310,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling devtools-frontend # and whatever else without interference from each other. - 'devtools_frontend_revision': '113abecd98b302a7cc970666277c9f4bb7aed47a', + 'devtools_frontend_revision': '0404c7edc03c2ded9787ba7d00f821414ce4285a', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libprotobuf-mutator # and whatever else without interference from each other. @@ -350,11 +350,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'dawn_revision': '6fd28ba4cb990953dc97ff22d3fbbd9b19a5f504', + 'dawn_revision': 'a4c8c8d5bffb66900d5bc76b143ce956f4fa6a13', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'quiche_revision': '003dffca332f2b9a4f288cb983230c8783029e27', + 'quiche_revision': 'd9e16940859d20084e9de2b47450ca64d179d017', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ios_webkit # and whatever else without interference from each other. @@ -1010,7 +1010,7 @@ # Tools used when building Chrome for Chrome OS. This affects both the Simple # Chrome workflow, as well as the chromeos-chrome ebuild. 'src/third_party/chromite': { - 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '9d5f4194e9c0ce319f67bf44e84568d4b1ea32cb', + 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '6b1011520cfe00a073b0062740b25d45f47ec9d9', 'condition': 'checkout_chromeos', }, @@ -1297,7 +1297,7 @@ }, 'src/third_party/libunwindstack': { - 'url': Var('chromium_git') + '/chromium/src/third_party/libunwindstack.git' + '@' + 'b34a0059a648f179ef05da2c0927f564bdaea2b3', + 'url': Var('chromium_git') + '/chromium/src/third_party/libunwindstack.git' + '@' + '6868358481bb1e5e20d155c1084dc436c88b5e6b', 'condition': 'checkout_android', }, @@ -1399,7 +1399,7 @@ Var('chromium_git') + '/external/github.com/cisco/openh264' + '@' + '3dd5b80bc4f172dd82925bb259cb7c82348409c5', 'src/third_party/openscreen/src': - Var('chromium_git') + '/openscreen' + '@' + '5467ac6e5c120051f44720dcd0a0de9be9a52b87', + Var('chromium_git') + '/openscreen' + '@' + '0c8028efc2bb92a9fc2311ef992420948617e3f6', 'src/third_party/openxr/src': { 'url': Var('chromium_git') + '/external/github.com/KhronosGroup/OpenXR-SDK' + '@' + 'bf21ccb1007bb531b45d9978919a56ea5059c245', @@ -1416,7 +1416,7 @@ }, 'src/third_party/perfetto': - Var('android_git') + '/platform/external/perfetto.git' + '@' + '9709a3d80cc9e2ac3e6d808638334f7510ddc59a', + Var('android_git') + '/platform/external/perfetto.git' + '@' + '251c5dd034fdc7ce2578f2b5fd112e2fc0fa0e8e', 'src/third_party/perl': { 'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3', @@ -1637,7 +1637,7 @@ Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + 'e42f534de7afea5942ecae5993d9211e258918aa', 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + '56ed4680c457935f813ae36ce24324df7780b210', + Var('webrtc_git') + '/src.git' + '@' + '339965f93cdaaee297fe0764f1765de0ae1bd9f3', 'src/third_party/libgifcodec': Var('skia_git') + '/libgifcodec' + '@'+ Var('libgifcodec_revision'), @@ -1695,7 +1695,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@6eae9bf238ce787d3c8d27c22742cabb894d79e1', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@646a59e1f51fa8237c7104a6c7805d3d7581d021', 'condition': 'checkout_src_internal', }, @@ -1714,7 +1714,7 @@ 'packages': [ { 'package': 'chromeos_internal/apps/help_app/app', - 'version': 'ZFyhw4M_ljvsXoXOC9LIHZPnXMU94atIC8w0bZf3jbsC', + 'version': 'Pyw0C0bOEiWBFK01kBwB_jv5JJ1x-e5LcCpdRNLhgZsC', }, ], 'condition': 'checkout_chromeos and checkout_src_internal', @@ -1725,7 +1725,7 @@ 'packages': [ { 'package': 'chromeos_internal/apps/media_app/app', - 'version': 'CsYiCAVozIrhRckMiklfbqKUIsz-6Kls5fI6G_ERblkC', + 'version': '-gZnSSL4IDU9raGy7Srz8vSLkUuWd9JMY1Gqe0PqPbAC', }, ], 'condition': 'checkout_chromeos and checkout_src_internal',
diff --git a/PRESUBMIT.py b/PRESUBMIT.py index 9e55724..af3899d2 100644 --- a/PRESUBMIT.py +++ b/PRESUBMIT.py
@@ -4269,7 +4269,8 @@ input_api, output_api, full_path, files_to_check=[r'^PRESUBMIT_test\.py$'], run_on_python2=not use_python3, - run_on_python3=use_python3)) + run_on_python3=use_python3, + skip_shebang_check=True)) return results
diff --git a/ash/BUILD.gn b/ash/BUILD.gn index 1d16cae..e0548c1 100644 --- a/ash/BUILD.gn +++ b/ash/BUILD.gn
@@ -902,6 +902,8 @@ "shutdown_reason.h", "style/ash_color_provider.cc", "style/ash_color_provider.h", + "style/button_style.cc", + "style/button_style.h", "style/default_color_constants.h", "style/default_colors.cc", "style/default_colors.h", @@ -1503,8 +1505,6 @@ "system/unified/quiet_mode_feature_pod_controller.h", "system/unified/rounded_label_button.cc", "system/unified/rounded_label_button.h", - "system/unified/sign_out_button.cc", - "system/unified/sign_out_button.h", "system/unified/top_shortcut_button.cc", "system/unified/top_shortcut_button.h", "system/unified/top_shortcuts_view.cc", @@ -1648,6 +1648,8 @@ "wm/desks/root_window_desk_switch_animator.h", "wm/desks/scroll_arrow_button.cc", "wm/desks/scroll_arrow_button.h", + "wm/desks/templates/desks_templates_delete_button.cc", + "wm/desks/templates/desks_templates_delete_button.h", "wm/desks/templates/desks_templates_dialog_controller.cc", "wm/desks/templates/desks_templates_dialog_controller.h", "wm/desks/templates/desks_templates_grid_view.cc",
diff --git a/ash/app_list/app_list_controller_impl.cc b/ash/app_list/app_list_controller_impl.cc index a89a451..903c5102 100644 --- a/ash/app_list/app_list_controller_impl.cc +++ b/ash/app_list/app_list_controller_impl.cc
@@ -705,22 +705,6 @@ client_->OnItemUpdated(profile_id_, item->CloneMetadata()); } -void AppListControllerImpl::OnAppListStateChanged(AppListState new_state, - AppListState old_state) { - UpdateLauncherContainer(); - - if (new_state == AppListState::kStateEmbeddedAssistant) { - // ShowUi() will be no-op if the Assistant UI is already visible. - AssistantUiController::Get()->ShowUi(AssistantEntryPoint::kUnspecified); - return; - } - - if (old_state == AppListState::kStateEmbeddedAssistant) { - // CloseUi() will be no-op if the Assistant UI is already closed. - AssistantUiController::Get()->CloseUi(AssistantExitPoint::kBackInLauncher); - } -} - //////////////////////////////////////////////////////////////////////////////// // Methods used in Ash @@ -919,10 +903,6 @@ return true; } -AppListViewState AppListControllerImpl::GetAppListViewState() { - return model_->state_fullscreen(); -} - bool AppListControllerImpl::ShouldHomeLauncherBeVisible() const { if (!IsTabletMode()) return false; @@ -1681,7 +1661,13 @@ close_assistant_ui_runner_.RunAndReset(); } +AppListViewState AppListControllerImpl::GetAppListViewState() const { + return app_list_view_state_; +} + void AppListControllerImpl::OnViewStateChanged(AppListViewState state) { + app_list_view_state_ = state; + auto* notifier = GetNotifier(); if (notifier) notifier->NotifyUIStateChanged(state); @@ -1751,6 +1737,34 @@ return screen_util::SnapBoundsToDisplayEdge(bounds, window); } +AppListState AppListControllerImpl::GetCurrentAppListPage() const { + return app_list_page_; +} + +void AppListControllerImpl::OnAppListPageChanged(AppListState page) { + const AppListState old_page = app_list_page_; + if (old_page == page) + return; + + app_list_page_ = page; + + if (!fullscreen_presenter_) + return; + + UpdateLauncherContainer(); + + if (page == AppListState::kStateEmbeddedAssistant) { + // ShowUi() will be no-op if the Assistant UI is already visible. + AssistantUiController::Get()->ShowUi(AssistantEntryPoint::kUnspecified); + return; + } + + if (old_page == AppListState::kStateEmbeddedAssistant) { + // CloseUi() will be no-op if the Assistant UI is already closed. + AssistantUiController::Get()->CloseUi(AssistantExitPoint::kBackInLauncher); + } +} + int AppListControllerImpl::GetShelfSize() { return ShelfConfig::Get()->system_shelf_size(); } @@ -2142,7 +2156,7 @@ bool AppListControllerImpl::ShouldLauncherShowBehindApps() const { return IsTabletMode() && - model_->state() != AppListState::kStateEmbeddedAssistant; + app_list_page_ != AppListState::kStateEmbeddedAssistant; } int AppListControllerImpl::GetLastQueryLength() {
diff --git a/ash/app_list/app_list_controller_impl.h b/ash/app_list/app_list_controller_impl.h index b1ce50a..b590ed9c 100644 --- a/ash/app_list/app_list_controller_impl.h +++ b/ash/app_list/app_list_controller_impl.h
@@ -147,8 +147,6 @@ void OnAppListItemAdded(AppListItem* item) override; void OnAppListItemWillBeDeleted(AppListItem* item) override; void OnAppListItemUpdated(AppListItem* item) override; - void OnAppListStateChanged(AppListState new_state, - AppListState old_state) override; // SessionObserver: void OnActiveUserPrefServiceChanged(PrefService* pref_service) override; @@ -179,7 +177,7 @@ ShelfAction ToggleAppList(int64_t display_id, AppListShowSource show_source, base::TimeTicks event_time_stamp); - AppListViewState GetAppListViewState(); + // Returns whether the home launcher should be visible. bool ShouldHomeLauncherBeVisible() const; @@ -235,13 +233,16 @@ void OnStateTransitionAnimationCompleted( AppListViewState state, bool was_animation_interrupted) override; - void OnViewStateChanged(AppListViewState state) override; int AdjustAppListViewScrollOffset(int offset, ui::EventType type) override; void LoadIcon(const std::string& app_id) override; void GetAppLaunchedMetricParams( AppLaunchedMetricParams* metric_params) override; gfx::Rect SnapBoundsToDisplayEdge(const gfx::Rect& bounds) override; + AppListState GetCurrentAppListPage() const override; + void OnAppListPageChanged(AppListState page) override; + AppListViewState GetAppListViewState() const override; + void OnViewStateChanged(AppListViewState state) override; int GetShelfSize() override; bool IsInTabletMode() override; AppListColorProviderImpl* GetColorProvider(); @@ -505,6 +506,14 @@ // is disabled. std::unique_ptr<AppListBubblePresenter> bubble_presenter_; + // Tracks the current page shown in the app list view (tracked for the + // fullscreen presenter). + AppListState app_list_page_ = AppListState::kInvalidState; + + // Tracks the current state of `AppListView` (tracked for the fullscreen + // presenter) + AppListViewState app_list_view_state_ = AppListViewState::kClosed; + // True if the on-screen keyboard is shown. bool onscreen_keyboard_shown_ = false;
diff --git a/ash/app_list/app_list_metrics.cc b/ash/app_list/app_list_metrics.cc index ea23d67..59e3769 100644 --- a/ash/app_list/app_list_metrics.cc +++ b/ash/app_list/app_list_metrics.cc
@@ -11,8 +11,6 @@ #include "ash/app_list/model/app_list_folder_item.h" #include "ash/app_list/model/app_list_item.h" #include "ash/app_list/model/app_list_item_list.h" -#include "ash/app_list/model/app_list_model.h" -#include "ash/app_list/model/search/search_model.h" #include "ash/app_list/model/search/search_result.h" #include "ash/constants/ash_features.h" #include "ash/public/cpp/app_menu_constants.h" @@ -137,15 +135,14 @@ } void RecordSearchResultOpenSource(const SearchResult* result, - const AppListModel* model, - const SearchModel* search_model) { + AppListViewState state, + bool is_tablet_mode) { // Record the search metric if the SearchResult is not a suggested app. if (result->is_recommendation()) return; ApplistSearchResultOpenedSource source; - AppListViewState state = model->state_fullscreen(); - if (search_model->tablet_mode()) { + if (is_tablet_mode) { source = ApplistSearchResultOpenedSource::kFullscreenTablet; } else { source = state == AppListViewState::kHalf
diff --git a/ash/app_list/app_list_metrics.h b/ash/app_list/app_list_metrics.h index 1697e58..ae83544 100644 --- a/ash/app_list/app_list_metrics.h +++ b/ash/app_list/app_list_metrics.h
@@ -12,8 +12,6 @@ namespace ash { -class AppListModel; -class SearchModel; class SearchResult; // The UMA histogram that logs how the app list transitions from peeking to @@ -212,8 +210,8 @@ void RecordPeriodicAppListMetrics(); ASH_EXPORT void RecordSearchResultOpenSource(const SearchResult* result, - const AppListModel* model, - const SearchModel* search_model); + AppListViewState state, + bool is_tablet_mode); ASH_EXPORT void RecordSearchLaunchIndexAndQueryLength( SearchResultLaunchLocation launch_location,
diff --git a/ash/app_list/app_list_test_view_delegate.cc b/ash/app_list/app_list_test_view_delegate.cc index 13347e50..a038534 100644 --- a/ash/app_list/app_list_test_view_delegate.cc +++ b/ash/app_list/app_list_test_view_delegate.cc
@@ -196,7 +196,21 @@ AppListViewState state, bool was_animation_interrupted) {} -void AppListTestViewDelegate::OnViewStateChanged(AppListViewState state) {} +AppListState AppListTestViewDelegate::GetCurrentAppListPage() const { + return app_list_page_; +} + +void AppListTestViewDelegate::OnAppListPageChanged(AppListState page) { + app_list_page_ = page; +} + +AppListViewState AppListTestViewDelegate::GetAppListViewState() const { + return app_list_view_state_; +} + +void AppListTestViewDelegate::OnViewStateChanged(AppListViewState state) { + app_list_view_state_ = state; +} void AppListTestViewDelegate::GetAppLaunchedMetricParams( AppLaunchedMetricParams* metric_params) {} @@ -226,7 +240,7 @@ void AppListTestViewDelegate::RecordAppLaunched( ash::AppListLaunchedFrom launched_from) { - RecordAppListAppLaunched(launched_from, model_->state_fullscreen(), + RecordAppListAppLaunched(launched_from, app_list_view_state_, false /*tablet mode*/, false /*home launcher shown*/); }
diff --git a/ash/app_list/app_list_test_view_delegate.h b/ash/app_list/app_list_test_view_delegate.h index 4ac50a5..9b58eea 100644 --- a/ash/app_list/app_list_test_view_delegate.h +++ b/ash/app_list/app_list_test_view_delegate.h
@@ -110,6 +110,9 @@ void OnStateTransitionAnimationCompleted( AppListViewState state, bool was_animation_interrupted) override; + AppListState GetCurrentAppListPage() const override; + void OnAppListPageChanged(AppListState page) override; + AppListViewState GetAppListViewState() const override; void OnViewStateChanged(AppListViewState state) override; void GetAppLaunchedMetricParams( AppLaunchedMetricParams* metric_params) override; @@ -142,6 +145,8 @@ int open_assistant_ui_count_ = 0; int next_profile_app_count_ = 0; int show_wallpaper_context_menu_count_ = 0; + AppListState app_list_page_ = AppListState::kInvalidState; + AppListViewState app_list_view_state_ = AppListViewState::kClosed; bool is_tablet_mode_ = false; bool should_show_suggested_content_info_ = false; std::map<size_t, int> open_search_result_counts_;
diff --git a/ash/app_list/app_list_view_delegate.h b/ash/app_list/app_list_view_delegate.h index 4214530..d02bd102 100644 --- a/ash/app_list/app_list_view_delegate.h +++ b/ash/app_list/app_list_view_delegate.h
@@ -176,6 +176,17 @@ // pressed to indicate not to show the view any more. virtual void MarkSuggestedContentInfoDismissed() = 0; + // Gets the app list page currently shown in the fullscreen app list, as + // reported from the app list view using `OnAppListPageChanged()`. + virtual AppListState GetCurrentAppListPage() const = 0; + + // Called when the page shown in the app list contents view is updated. + virtual void OnAppListPageChanged(AppListState page) = 0; + + // Gets the current app list view state, as reported by app list view using + // `OnViewStateChanged()`. Tracked for fullscreen app list view only. + virtual AppListViewState GetAppListViewState() const = 0; + // Called when the app list view state is updated. virtual void OnViewStateChanged(AppListViewState state) = 0;
diff --git a/ash/app_list/model/app_list_model.cc b/ash/app_list/model/app_list_model.cc index f544c241..2a82614e 100644 --- a/ash/app_list/model/app_list_model.cc +++ b/ash/app_list/model/app_list_model.cc
@@ -42,20 +42,6 @@ observer.OnAppListModelStatusChanged(); } -void AppListModel::SetState(AppListState state) { - if (state_ == state) - return; - - auto old_state = state_; - state_ = state; - for (auto& observer : observers_) - observer.OnAppListStateChanged(state_, old_state); -} - -void AppListModel::SetStateFullscreen(AppListViewState state) { - state_fullscreen_ = state; -} - AppListItem* AppListModel::FindItem(const std::string& id) { AppListItem* item = top_level_item_list_->FindItem(id); if (item)
diff --git a/ash/app_list/model/app_list_model.h b/ash/app_list/model/app_list_model.h index f4cfcf29..199b27ea 100644 --- a/ash/app_list/model/app_list_model.h +++ b/ash/app_list/model/app_list_model.h
@@ -46,13 +46,6 @@ void SetStatus(AppListModelStatus status); - void SetState(AppListState state); - AppListState state() const { return state_; } - - // The current state of the AppListView. Controlled by AppListView. - void SetStateFullscreen(AppListViewState state); - AppListViewState state_fullscreen() const { return state_fullscreen_; } - // Finds the item matching |id|. AppListItem* FindItem(const std::string& id); @@ -178,9 +171,7 @@ std::unique_ptr<AppListItemList> top_level_item_list_; AppListModelStatus status_ = AppListModelStatus::kStatusNormal; - AppListState state_ = AppListState::kInvalidState; - // The AppListView state. Controlled by the AppListView. - AppListViewState state_fullscreen_ = AppListViewState::kClosed; + base::ObserverList<AppListModelObserver, true> observers_; base::ScopedMultiSourceObservation<AppListItemList, AppListItemListObserver> item_list_scoped_observations_{this};
diff --git a/ash/app_list/model/app_list_model_observer.h b/ash/app_list/model/app_list_model_observer.h index 2a6042a..87804c3 100644 --- a/ash/app_list/model/app_list_model_observer.h +++ b/ash/app_list/model/app_list_model_observer.h
@@ -33,10 +33,6 @@ // Triggered after |item| has moved, changed folders, or changed properties. virtual void OnAppListItemUpdated(AppListItem* item) {} - // Triggered after AppListState has changed. - virtual void OnAppListStateChanged(AppListState new_state, - AppListState old_state) {} - // Triggered when the custom launcher page enabled state is changed. virtual void OnCustomLauncherPageEnabledStateChanged(bool enabled) {}
diff --git a/ash/app_list/model/search/search_box_model.cc b/ash/app_list/model/search/search_box_model.cc index 2f3633f..3ee0e60 100644 --- a/ash/app_list/model/search/search_box_model.cc +++ b/ash/app_list/model/search/search_box_model.cc
@@ -16,10 +16,6 @@ SearchBoxModel::~SearchBoxModel() = default; -void SearchBoxModel::SetTabletMode(bool is_tablet_mode) { - is_tablet_mode_ = is_tablet_mode; -} - void SearchBoxModel::SetShowAssistantButton(bool show) { if (show_assistant_button_ == show) return;
diff --git a/ash/app_list/model/search/search_box_model.h b/ash/app_list/model/search/search_box_model.h index faf7239..32e56b0 100644 --- a/ash/app_list/model/search/search_box_model.h +++ b/ash/app_list/model/search/search_box_model.h
@@ -25,9 +25,6 @@ SearchBoxModel& operator=(const SearchBoxModel&) = delete; ~SearchBoxModel(); - void SetTabletMode(bool is_tablet_mode); - bool is_tablet_mode() const { return is_tablet_mode_; } - void SetShowAssistantButton(bool show); bool show_assistant_button() const { return show_assistant_button_; } @@ -45,7 +42,6 @@ private: std::u16string text_; bool search_engine_is_google_ = false; - bool is_tablet_mode_ = false; bool show_assistant_button_ = false; base::ObserverList<SearchBoxModelObserver> observers_;
diff --git a/ash/app_list/model/search/search_model.cc b/ash/app_list/model/search/search_model.cc index cd970744..01939aa 100644 --- a/ash/app_list/model/search/search_model.cc +++ b/ash/app_list/model/search/search_model.cc
@@ -18,10 +18,6 @@ SearchModel::~SearchModel() {} -void SearchModel::SetTabletMode(bool is_tablet_mode) { - search_box_->SetTabletMode(is_tablet_mode); -} - void SearchModel::SetSearchEngineIsGoogle(bool is_google) { search_box_->SetSearchEngineIsGoogle(is_google); }
diff --git a/ash/app_list/model/search/search_model.h b/ash/app_list/model/search/search_model.h index ebc1bf5f..22a3099 100644 --- a/ash/app_list/model/search/search_model.h +++ b/ash/app_list/model/search/search_model.h
@@ -34,10 +34,6 @@ ~SearchModel(); - // Whether tablet mode is active. Controlled by AppListView. - void SetTabletMode(bool is_tablet_mode); - bool tablet_mode() const { return search_box_->is_tablet_mode(); } - void SetSearchEngineIsGoogle(bool is_google); bool search_engine_is_google() const { return search_box_->search_engine_is_google();
diff --git a/ash/app_list/views/app_list_main_view.cc b/ash/app_list/views/app_list_main_view.cc index bad09f4..aba3611 100644 --- a/ash/app_list/views/app_list_main_view.cc +++ b/ash/app_list/views/app_list_main_view.cc
@@ -14,7 +14,6 @@ #include "ash/app_list/app_list_view_delegate.h" #include "ash/app_list/model/app_list_folder_item.h" #include "ash/app_list/model/app_list_item.h" -#include "ash/app_list/model/app_list_model.h" #include "ash/app_list/views/app_list_folder_view.h" #include "ash/app_list/views/app_list_item_view.h" #include "ash/app_list/views/app_list_view.h" @@ -52,20 +51,15 @@ AppListMainView::AppListMainView(AppListViewDelegate* delegate, AppListView* app_list_view) : delegate_(delegate), - model_(delegate->GetModel()), search_model_(delegate->GetSearchModel()), app_list_view_(app_list_view) { // We need a layer to apply transform to in small display so that the apps // grid fits in the display. SetPaintToLayer(); layer()->SetFillsBoundsOpaquely(false); - - model_->AddObserver(this); } -AppListMainView::~AppListMainView() { - model_->RemoveObserver(this); -} +AppListMainView::~AppListMainView() = default; void AppListMainView::Init(int initial_apps_page, SearchBoxView* search_box_view) { @@ -81,7 +75,7 @@ void AppListMainView::AddContentsViews() { DCHECK(search_box_view_); auto contents_view = std::make_unique<ContentsView>(app_list_view_); - contents_view->Init(model_); + contents_view->Init(); contents_view->SetPaintToLayer(ui::LAYER_NOT_DRAWN); contents_view->layer()->SetMasksToBounds(true); contents_view_ = AddChildView(std::move(contents_view)); @@ -105,9 +99,6 @@ } void AppListMainView::ModelChanged() { - model_->RemoveObserver(this); - model_ = delegate_->GetModel(); - model_->AddObserver(this); search_model_ = delegate_->GetSearchModel(); search_box_view_->ModelChanged(); delete contents_view_; @@ -145,16 +136,6 @@ contents_view_->SetBoundsRect(rect); } -// AppListModelObserver overrides: -void AppListMainView::OnAppListStateChanged(AppListState new_state, - AppListState old_state) { - if (new_state == AppListState::kStateEmbeddedAssistant) { - search_box_view_->SetVisible(false); - } else { - search_box_view_->SetVisible(true); - } -} - void AppListMainView::QueryChanged(SearchBoxViewBase* sender) { std::u16string raw_query = search_model_->search_box()->text(); std::u16string query;
diff --git a/ash/app_list/views/app_list_main_view.h b/ash/app_list/views/app_list_main_view.h index 6dbc26e..ae5655a 100644 --- a/ash/app_list/views/app_list_main_view.h +++ b/ash/app_list/views/app_list_main_view.h
@@ -5,7 +5,6 @@ #ifndef ASH_APP_LIST_VIEWS_APP_LIST_MAIN_VIEW_H_ #define ASH_APP_LIST_VIEWS_APP_LIST_MAIN_VIEW_H_ -#include "ash/app_list/model/app_list_model_observer.h" #include "ash/app_list/model/search/search_model.h" #include "ash/ash_export.h" #include "ash/search_box/search_box_view_delegate.h" @@ -16,7 +15,6 @@ namespace ash { -class AppListModel; class AppListView; class AppListViewDelegate; class ApplicationDragAndDropHost; @@ -28,7 +26,6 @@ // AppListMainView contains the normal view of the app list, which is shown // when the user is signed in. class ASH_EXPORT AppListMainView : public views::View, - public AppListModelObserver, public SearchBoxViewDelegate { public: AppListMainView(AppListViewDelegate* delegate, AppListView* app_list_view); @@ -52,7 +49,6 @@ ApplicationDragAndDropHost* drag_and_drop_host); ContentsView* contents_view() const { return contents_view_; } - AppListModel* model() { return model_; } SearchModel* search_model() { return search_model_; } AppListViewDelegate* view_delegate() { return delegate_; } @@ -63,10 +59,6 @@ const char* GetClassName() const override; void Layout() override; - // AppListModelObserver overrides: - void OnAppListStateChanged(AppListState new_state, - AppListState old_state) override; - private: // Adds the ContentsView. void AddContentsViews(); @@ -84,7 +76,6 @@ bool CanSelectSearchResults() override; AppListViewDelegate* delegate_; // Owned by parent view (AppListView). - AppListModel* model_; // Unowned; ownership is handled by |delegate_|. SearchModel* search_model_; // Unowned; ownership is handled by |delegate_|. // Created by AppListView. Owned by views hierarchy.
diff --git a/ash/app_list/views/app_list_view.cc b/ash/app_list/views/app_list_view.cc index 9f1f80d..8f59eb27 100644 --- a/ash/app_list/views/app_list_view.cc +++ b/ash/app_list/views/app_list_view.cc
@@ -12,7 +12,6 @@ #include "ash/app_list/app_list_metrics.h" #include "ash/app_list/app_list_util.h" -#include "ash/app_list/model/app_list_model.h" #include "ash/app_list/views/app_list_a11y_announcer.h" #include "ash/app_list/views/app_list_folder_view.h" #include "ash/app_list/views/app_list_main_view.h" @@ -635,8 +634,6 @@ AppListView::AppListView(AppListViewDelegate* delegate) : delegate_(delegate), - model_(delegate->GetModel()), - search_model_(delegate->GetSearchModel()), is_background_blur_enabled_(features::IsBackgroundBlurEnabled()), state_transition_notifier_( std::make_unique<StateTransitionNotifier>(this)), @@ -1044,7 +1041,8 @@ } if (!search_box_view_->is_search_box_active() && - model_->state() != AppListState::kStateEmbeddedAssistant) { + delegate_->GetCurrentAppListPage() != + AppListState::kStateEmbeddedAssistant) { if (!delegate_->IsInTabletMode()) Dismiss(); return; @@ -1546,7 +1544,6 @@ void AppListView::OnTabletModeChanged(bool started) { search_box_view_->OnTabletModeChanged(started); - search_model_->SetTabletMode(started); app_list_main_view_->contents_view()->OnTabletModeChanged(started); if (is_in_drag_) { @@ -1728,7 +1725,6 @@ StartAnimationForState(new_state_override); MaybeIncreasePrivacyInfoRowShownCounts(new_state_override); RecordStateTransitionForUma(new_state_override); - model_->SetStateFullscreen(new_state_override); app_list_state_ = new_state_override; if (delegate_) delegate_->OnViewStateChanged(new_state_override); @@ -1762,7 +1758,7 @@ if (!GetWidget()) return; gfx::NativeView window = GetWidget()->GetNativeView(); - AppListState contents_view_state = app_list_main_view_->model()->state(); + AppListState contents_view_state = delegate_->GetCurrentAppListPage(); if (window) { if (contents_view_state == AppListState::kStateSearchResults || contents_view_state == AppListState::kStateEmbeddedAssistant) { @@ -2415,8 +2411,7 @@ int number_of_apps_in_folders = 0; int number_of_folders = 0; int non_system_folders = 0; - AppListItemList* item_list = - app_list_main_view_->model()->top_level_item_list(); + AppListItemList* item_list = delegate_->GetModel()->top_level_item_list(); for (size_t i = 0; i < item_list->item_count(); ++i) { AppListItem* item = item_list->item_at(i); if (item->GetItemType() != AppListFolderItem::kItemType)
diff --git a/ash/app_list/views/app_list_view.h b/ash/app_list/views/app_list_view.h index 29400a1f..a780222 100644 --- a/ash/app_list/views/app_list_view.h +++ b/ash/app_list/views/app_list_view.h
@@ -44,12 +44,10 @@ class ApplicationDragAndDropHost; class AppListBackgroundShieldView; class AppListMainView; -class AppListModel; class AppsGridView; class PagedAppsGridView; class PaginationModel; class SearchBoxView; -class SearchModel; class StateTransitionNotifier; FORWARD_DECLARE_TEST(AppListControllerImplTest, @@ -553,8 +551,6 @@ void ResetSubpixelPositionOffset(ui::Layer* layer); AppListViewDelegate* const delegate_; - AppListModel* const model_; // Not Owned. - SearchModel* const search_model_; // Not Owned. // Keeps track of the number of locks that prevent the app list view // from creating app list transition accessibility events. This is used to
diff --git a/ash/app_list/views/app_list_view_unittest.cc b/ash/app_list/views/app_list_view_unittest.cc index 641d2c3..ae8286ef 100644 --- a/ash/app_list/views/app_list_view_unittest.cc +++ b/ash/app_list/views/app_list_view_unittest.cc
@@ -251,7 +251,7 @@ } } - if (state != delegate_->GetModel()->state()) { + if (state != delegate_->GetCurrentAppListPage()) { ADD_FAILURE() << "Model state does not match state " << static_cast<int>(state); success = false; @@ -2262,7 +2262,7 @@ ash::AppListState expected = ash::AppListState::kStateApps; EXPECT_TRUE(main_view->contents_view()->IsStateActive(expected)); - EXPECT_EQ(expected, delegate_->GetModel()->state()); + EXPECT_EQ(expected, delegate_->GetCurrentAppListPage()); } // Tests switching rapidly between multiple pages of the launcher. @@ -2820,12 +2820,12 @@ Initialize(false /*is_tablet_mode*/); Show(); - EXPECT_TRUE(search_box_view()->GetVisible()); + EXPECT_TRUE(search_box_view()->GetWidget()->IsVisible()); contents_view()->ShowEmbeddedAssistantUI(true); EXPECT_TRUE(contents_view()->IsShowingEmbeddedAssistantUI()); - EXPECT_FALSE(search_box_view()->GetVisible()); + EXPECT_FALSE(search_box_view()->GetWidget()->IsVisible()); } // Tests that the expand arrow cannot be seen when opening the app list with
diff --git a/ash/app_list/views/contents_view.cc b/ash/app_list/views/contents_view.cc index a4366de..65c0d64 100644 --- a/ash/app_list/views/contents_view.cc +++ b/ash/app_list/views/contents_view.cc
@@ -117,15 +117,12 @@ : kDefaultSearchBoxTopMarginInPeekingState; } -void ContentsView::Init(AppListModel* model) { - DCHECK(model); - model_ = model; - +void ContentsView::Init() { AppListViewDelegate* view_delegate = GetAppListMainView()->view_delegate(); - apps_container_view_ = - AddLauncherPage(std::make_unique<AppsContainerView>(this, model), - AppListState::kStateApps); + apps_container_view_ = AddLauncherPage( + std::make_unique<AppsContainerView>(this, view_delegate->GetModel()), + AppListState::kStateApps); // Search results UI. auto search_result_page_view = @@ -335,7 +332,7 @@ app_list_pages_[GetActivePageIndex()]->OnWillBeShown(); - GetAppListMainView()->model()->SetState(state); + GetAppListMainView()->view_delegate()->OnAppListPageChanged(state); UpdateSearchBoxVisibility(state); app_list_view_->UpdateWindowTitle(); }
diff --git a/ash/app_list/views/contents_view.h b/ash/app_list/views/contents_view.h index 7110697..7d4f893 100644 --- a/ash/app_list/views/contents_view.h +++ b/ash/app_list/views/contents_view.h
@@ -84,7 +84,7 @@ // Initialize the pages of the launcher. Should be called after // set_contents_switcher_view(). - void Init(AppListModel* model); + void Init(); // Resets the state of the view so it is ready to be shown. void ResetForShow(); @@ -267,9 +267,6 @@ int GetSearchBoxTopForViewState(AppListState state, AppListViewState view_state) const; - // Unowned pointer to application list model. - AppListModel* model_ = nullptr; - // Sub-views of the ContentsView. All owned by the views hierarchy. AssistantPageView* assistant_page_view_ = nullptr; AppsContainerView* apps_container_view_ = nullptr;
diff --git a/ash/app_list/views/search_box_view_unittest.cc b/ash/app_list/views/search_box_view_unittest.cc index b929663..92d63ba2 100644 --- a/ash/app_list/views/search_box_view_unittest.cc +++ b/ash/app_list/views/search_box_view_unittest.cc
@@ -112,7 +112,7 @@ std::make_unique<KeyPressCounterView>(app_list_view_)); widget_->Show(); - counter_view_->Init(view_delegate_.GetModel()); + counter_view_->Init(); SetContentsView(counter_view_); } @@ -655,7 +655,7 @@ view_delegate()->SetShouldShowSuggestedContentInfo(true); auto* contents_view = widget()->GetContentsView()->AddChildView( std::make_unique<KeyPressCounterView>(app_list_view())); - contents_view->Init(view_delegate()->GetModel()); + contents_view->Init(); SetContentsView(contents_view); PrivacyContainerView* const privacy_container_view = @@ -710,7 +710,7 @@ view_delegate()->SetShouldShowSuggestedContentInfo(true); auto* contents_view = widget()->GetContentsView()->AddChildView( std::make_unique<KeyPressCounterView>(app_list_view())); - contents_view->Init(view_delegate()->GetModel()); + contents_view->Init(); SetContentsView(contents_view); PrivacyContainerView* const privacy_container_view = @@ -741,7 +741,7 @@ view_delegate()->SetShouldShowSuggestedContentInfo(true); auto* contents_view = widget()->GetContentsView()->AddChildView( std::make_unique<KeyPressCounterView>(app_list_view())); - contents_view->Init(view_delegate()->GetModel()); + contents_view->Init(); SetContentsView(contents_view); PrivacyContainerView* const privacy_container_view = @@ -784,7 +784,7 @@ view_delegate()->SetShouldShowSuggestedContentInfo(true); auto* contents_view = widget()->GetContentsView()->AddChildView( std::make_unique<KeyPressCounterView>(app_list_view())); - contents_view->Init(view_delegate()->GetModel()); + contents_view->Init(); SetContentsView(contents_view); PrivacyContainerView* const privacy_container_view =
diff --git a/ash/app_list/views/search_result_list_view.cc b/ash/app_list/views/search_result_list_view.cc index b0f911a6..6cf986f 100644 --- a/ash/app_list/views/search_result_list_view.cc +++ b/ash/app_list/views/search_result_list_view.cc
@@ -233,8 +233,8 @@ auto* result = view->result(); - RecordSearchResultOpenSource(result, view_delegate_->GetModel(), - view_delegate_->GetSearchModel()); + RecordSearchResultOpenSource(result, view_delegate_->GetAppListViewState(), + view_delegate_->IsInTabletMode()); view_delegate_->NotifySearchResultsForLogging( view_delegate_->GetSearchModel()->search_box()->text(), GetSearchResultsForLogging(search_result_views_),
diff --git a/ash/app_list/views/search_result_suggestion_chip_view.cc b/ash/app_list/views/search_result_suggestion_chip_view.cc index 4c34d37..187497b 100644 --- a/ash/app_list/views/search_result_suggestion_chip_view.cc +++ b/ash/app_list/views/search_result_suggestion_chip_view.cc
@@ -255,8 +255,8 @@ void SearchResultSuggestionChipView::OnButtonPressed(const ui::Event& event) { DCHECK(result()); LogAppLaunch(index_in_container()); - RecordSearchResultOpenSource(result(), view_delegate_->GetModel(), - view_delegate_->GetSearchModel()); + RecordSearchResultOpenSource(result(), view_delegate_->GetAppListViewState(), + view_delegate_->IsInTabletMode()); view_delegate_->OpenSearchResult( result()->id(), result()->result_type(), event.flags(), AppListLaunchedFrom::kLaunchedFromSuggestionChip,
diff --git a/ash/app_list/views/search_result_tile_item_view.cc b/ash/app_list/views/search_result_tile_item_view.cc index 9d72632..1a8e0fb 100644 --- a/ash/app_list/views/search_result_tile_item_view.cc +++ b/ash/app_list/views/search_result_tile_item_view.cc
@@ -363,7 +363,7 @@ metric_params, GetAppType(), base::BindOnce(&SearchResultTileItemView::OnMenuClosed, weak_ptr_factory_.GetWeakPtr()), - view_delegate_->GetSearchModel()->tablet_mode()); + view_delegate_->IsInTabletMode()); context_menu_->Run(anchor_rect, views::MenuAnchorPosition::kBubbleRight, views::MenuRunner::HAS_MNEMONICS | views::MenuRunner::USE_TOUCHABLE_LAYOUT | @@ -409,8 +409,8 @@ LogAppLaunchForSuggestedApp(); - RecordSearchResultOpenSource(result(), view_delegate_->GetModel(), - view_delegate_->GetSearchModel()); + RecordSearchResultOpenSource(result(), view_delegate_->GetAppListViewState(), + view_delegate_->IsInTabletMode()); view_delegate_->OpenSearchResult(result()->id(), result()->result_type(), event_flags, AppListLaunchedFrom::kLaunchedFromSearchBox, @@ -505,17 +505,15 @@ AppListMenuModelAdapter::AppListViewAppType SearchResultTileItemView::GetAppType() const { if (IsSuggestedAppTile()) { - if (view_delegate_->GetModel()->state_fullscreen() == - AppListViewState::kPeeking) { + if (view_delegate_->GetAppListViewState() == AppListViewState::kPeeking) { return AppListMenuModelAdapter::PEEKING_SUGGESTED; } else { return AppListMenuModelAdapter::FULLSCREEN_SUGGESTED; } } else { - if (view_delegate_->GetModel()->state_fullscreen() == - AppListViewState::kHalf) { + if (view_delegate_->GetAppListViewState() == AppListViewState::kHalf) { return AppListMenuModelAdapter::HALF_SEARCH_RESULT; - } else if (view_delegate_->GetModel()->state_fullscreen() == + } else if (view_delegate_->GetAppListViewState() == AppListViewState::kFullscreenSearch) { return AppListMenuModelAdapter::FULLSCREEN_SEARCH_RESULT; }
diff --git a/ash/app_list/views/search_result_view.cc b/ash/app_list/views/search_result_view.cc index 5cd1a43..09d1830 100644 --- a/ash/app_list/views/search_result_view.cc +++ b/ash/app_list/views/search_result_view.cc
@@ -667,7 +667,7 @@ metric_params, AppListMenuModelAdapter::SEARCH_RESULT, base::BindOnce(&SearchResultView::OnMenuClosed, weak_ptr_factory_.GetWeakPtr()), - view_delegate_->GetSearchModel()->tablet_mode()); + view_delegate_->IsInTabletMode()); context_menu_->Run(gfx::Rect(point, gfx::Size()), views::MenuAnchorPosition::kTopLeft, views::MenuRunner::HAS_MNEMONICS);
diff --git a/ash/ash_strings.grd b/ash/ash_strings.grd index 2885db1..6f78ec4 100644 --- a/ash/ash_strings.grd +++ b/ash/ash_strings.grd
@@ -1694,6 +1694,12 @@ <message name="IDS_ASH_NETWORK_CELLULAR_SETUP_NOTIFICATION_MESSAGE" desc="Message displayed in the system notification shown post-OOBE if a user has no activated mobile networks."> Tap to complete set up </message> + <message name="IDS_ASH_NETWORK_RESET_EUICC_NOTIFICATION_TITLE" desc="Title used for the system notification shown when the reset euicc operation is initiated."> + eSIM connection unavailable + </message> + <message name="IDS_ASH_NETWORK_RESET_EUICC_NOTIFICATION_MESSAGE" desc="Message displayed in the system notification shown when the reset euicc operation is initiated."> + Your administrator has removed all eSIM profiles. Contact your administrator for more info. + </message> <message name="IDS_ASH_STATUS_TRAY_NETWORK_DISCONNECTED_LABEL" desc="The label text used when network is not connected. [CHAR_LIMIT=14]"> Not connected </message>
diff --git a/ash/ash_strings_grd/IDS_ASH_NETWORK_RESET_EUICC_NOTIFICATION_MESSAGE.png.sha1 b/ash/ash_strings_grd/IDS_ASH_NETWORK_RESET_EUICC_NOTIFICATION_MESSAGE.png.sha1 new file mode 100644 index 0000000..5f372094f --- /dev/null +++ b/ash/ash_strings_grd/IDS_ASH_NETWORK_RESET_EUICC_NOTIFICATION_MESSAGE.png.sha1
@@ -0,0 +1 @@ +79228bebb6a5d609393df1218a8f393c05d72a81 \ No newline at end of file
diff --git a/ash/ash_strings_grd/IDS_ASH_NETWORK_RESET_EUICC_NOTIFICATION_TITLE.png.sha1 b/ash/ash_strings_grd/IDS_ASH_NETWORK_RESET_EUICC_NOTIFICATION_TITLE.png.sha1 new file mode 100644 index 0000000..70ffde1 --- /dev/null +++ b/ash/ash_strings_grd/IDS_ASH_NETWORK_RESET_EUICC_NOTIFICATION_TITLE.png.sha1
@@ -0,0 +1 @@ +7e55cb34a65f3d50948987c050973264a7168ec0 \ No newline at end of file
diff --git a/ash/capture_mode/capture_mode_controller.cc b/ash/capture_mode/capture_mode_controller.cc index 433aa02..357b78b 100644 --- a/ash/capture_mode/capture_mode_controller.cc +++ b/ash/capture_mode/capture_mode_controller.cc
@@ -1263,6 +1263,22 @@ return; } + // During the 3-second count down, screen content might have changed such that + // admin-restricted or HDCP content became present. We must check again. + const CaptureAllowance allowance = + IsCaptureAllowedByEnterprisePolicies(*capture_params); + if (allowance != CaptureAllowance::kAllowed) { + Stop(); + ShowDisabledNotification(allowance); + return; + } + + if (ShouldBlockRecordingForContentProtection(capture_params->window)) { + Stop(); + ShowDisabledNotification(CaptureAllowance::kDisallowedByHdcp); + return; + } + // In Projector mode, the creation of the DriveFS folder that will host the // video is asynchronous. We don't want the user to be able to bail out of the // session at this point, since we don't want to create that folder in vain. @@ -1315,24 +1331,14 @@ capture_mode_session_->ReleaseLayer(); session_layer->set_delegate(nullptr); + // At this point, recording is guaranteed to start, and cannot be prevented by + // DLP or user cancellation. + capture_mode_session_->set_is_stopping_to_start_video_recording(true); + // Stop the capture session now, so the bar doesn't show up in the captured // video. Stop(); - // During the 3-second count down, screen content might have changed such that - // admin-restricted or HDCP content became present. We must check again. - const CaptureAllowance allowance = - IsCaptureAllowedByEnterprisePolicies(capture_params); - if (allowance != CaptureAllowance::kAllowed) { - ShowDisabledNotification(allowance); - return; - } - - if (ShouldBlockRecordingForContentProtection(capture_params.window)) { - ShowDisabledNotification(CaptureAllowance::kDisallowedByHdcp); - return; - } - mojo::PendingRemote<viz::mojom::FrameSinkVideoCaptureOverlay> cursor_capture_overlay; auto cursor_overlay_receiver =
diff --git a/ash/capture_mode/capture_mode_session.cc b/ash/capture_mode/capture_mode_session.cc index b8171e0f..d53c7952e 100644 --- a/ash/capture_mode/capture_mode_session.cc +++ b/ash/capture_mode/capture_mode_session.cc
@@ -21,6 +21,7 @@ #include "ash/constants/ash_features.h" #include "ash/display/mouse_cursor_event_filter.h" #include "ash/display/screen_orientation_controller.h" +#include "ash/projector/projector_controller_impl.h" #include "ash/public/cpp/shell_window_ids.h" #include "ash/resources/vector_icons/vector_icons.h" #include "ash/shell.h" @@ -632,6 +633,11 @@ IDS_ASH_SCREEN_CAPTURE_ALERT_CLOSE); } UpdateAutoclickMenuBoundsIfNeeded(); + + // Stopping the session for any reason other than starting video recording + // means a cancellation to an ongoing projector session (if any). + if (is_in_projector_mode_ && !is_stopping_to_start_video_recording_) + ProjectorControllerImpl::Get()->OnRecordingStartAborted(); } aura::Window* CaptureModeSession::GetSelectedWindow() const {
diff --git a/ash/capture_mode/capture_mode_session.h b/ash/capture_mode/capture_mode_session.h index ee31d69..684c237 100644 --- a/ash/capture_mode/capture_mode_session.h +++ b/ash/capture_mode/capture_mode_session.h
@@ -84,6 +84,9 @@ a11y_alert_on_session_exit_ = value; } bool is_shutting_down() const { return is_shutting_down_; } + void set_is_stopping_to_start_video_recording(bool value) { + is_stopping_to_start_video_recording_ = value; + } // Initializes the capture mode session. This should be called right after the // object is created. @@ -406,6 +409,11 @@ // True once Shutdown() is called. bool is_shutting_down_ = false; + // True when the session is being stopped to start video recording, at which + // point, it's guaranteed that recording will start and will not be blocked by + // any errors, DLP restrictions, or any user cancellation. + bool is_stopping_to_start_video_recording_ = false; + // The object which handles tab focus while in a capture session. std::unique_ptr<CaptureModeSessionFocusCycler> focus_cycler_;
diff --git a/ash/capture_mode/capture_mode_unittests.cc b/ash/capture_mode/capture_mode_unittests.cc index 7de55dd..1cba0dea 100644 --- a/ash/capture_mode/capture_mode_unittests.cc +++ b/ash/capture_mode/capture_mode_unittests.cc
@@ -460,9 +460,9 @@ void WaitForCountDownToFinish() { auto* controller = CaptureModeController::Get(); - DCHECK(controller->IsActive()); DCHECK_EQ(controller->type(), CaptureModeType::kVideo); - while (!controller->is_recording_in_progress()) { + while (controller->IsActive() && + controller->capture_mode_session()->IsInCountDownAnimation()) { base::RunLoop run_loop; base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( FROM_HERE, run_loop.QuitClosure(), base::Milliseconds(100)); @@ -4503,6 +4503,8 @@ window_ = CreateTestWindow(gfx::Rect(20, 30, 200, 200)); CaptureModeController::Get()->SetUserCaptureRegion(kUserRegion, /*by_user=*/true); + EXPECT_CALL(projector_client_, IsDriveFsMounted()) + .WillRepeatedly(testing::Return(true)); } void TearDown() override { @@ -4514,8 +4516,6 @@ auto* projector_session = ProjectorSession::Get(); EXPECT_FALSE(projector_session->is_active()); auto* projector_controller = ProjectorController::Get(); - EXPECT_CALL(projector_client_, IsDriveFsMounted()) - .WillRepeatedly(testing::Return(true)); projector_controller->StartProjectorSession("projector_data"); EXPECT_TRUE(projector_session->is_active()); } @@ -4656,6 +4656,111 @@ controller->EndVideoRecording(EndRecordingReason::kStopRecordingButton); } +TEST_F(ProjectorCaptureModeIntegrationTests, + ProjectorSessionNeverStartsWhenCaptureModeIsBlocked) { + auto* controller = CaptureModeController::Get(); + controller->SetSource(CaptureModeSource::kFullscreen); + + auto* test_delegate = + static_cast<TestCaptureModeDelegate*>(controller->delegate_for_testing()); + test_delegate->set_is_allowed_by_policy(false); + ProjectorController::Get()->StartProjectorSession("projector_data"); + + // Both sessions will never start. + EXPECT_FALSE(controller->IsActive()); + EXPECT_FALSE(ProjectorSession::Get()->is_active()); + EXPECT_FALSE(controller->is_recording_in_progress()); +} + +namespace { + +enum AbortReason { + kBlockedByDlp, + kBlockedByPolicy, + kUserPressedEsc, +}; + +struct { + const std::string scope_trace; + const AbortReason reason; +} kTestCases[] = { + {"Blocked by DLP", kBlockedByDlp}, + {"Blocked by policy", kBlockedByPolicy}, + {"User Pressed Esc", kUserPressedEsc}, +}; + +} // namespace + +TEST_F(ProjectorCaptureModeIntegrationTests, + ProjectorSessionAbortedBeforeCountDownStarts) { + auto* controller = CaptureModeController::Get(); + controller->SetSource(CaptureModeSource::kFullscreen); + + for (const auto& test_case : kTestCases) { + SCOPED_TRACE(test_case.scope_trace); + StartProjectorModeSession(); + auto* test_delegate = static_cast<TestCaptureModeDelegate*>( + controller->delegate_for_testing()); + + switch (test_case.reason) { + case kBlockedByDlp: + test_delegate->set_is_allowed_by_dlp(false); + PressAndReleaseKey(ui::VKEY_RETURN); + break; + case kBlockedByPolicy: + test_delegate->set_is_allowed_by_policy(false); + PressAndReleaseKey(ui::VKEY_RETURN); + break; + case kUserPressedEsc: + PressAndReleaseKey(ui::VKEY_ESCAPE); + break; + } + + // The session will end immediately without a count down. + EXPECT_FALSE(controller->IsActive()); + EXPECT_FALSE(ProjectorSession::Get()->is_active()); + EXPECT_FALSE(controller->is_recording_in_progress()); + + // Prepare for next iteration by resetting things back to default. + test_delegate->ResetAllowancesToDefault(); + } +} + +TEST_F(ProjectorCaptureModeIntegrationTests, + ProjectorSessionAbortedAfterCountDownStarts) { + ui::ScopedAnimationDurationScaleMode animation_scale( + ui::ScopedAnimationDurationScaleMode::FAST_DURATION); + auto* controller = CaptureModeController::Get(); + controller->SetSource(CaptureModeSource::kFullscreen); + + for (const auto& test_case : kTestCases) { + SCOPED_TRACE(test_case.scope_trace); + StartProjectorModeSession(); + PressAndReleaseKey(ui::VKEY_RETURN); + auto* test_delegate = static_cast<TestCaptureModeDelegate*>( + controller->delegate_for_testing()); + + switch (test_case.reason) { + case kBlockedByDlp: + test_delegate->set_is_allowed_by_dlp(false); + break; + case kBlockedByPolicy: + test_delegate->set_is_allowed_by_policy(false); + break; + case kUserPressedEsc: + PressAndReleaseKey(ui::VKEY_ESCAPE); + break; + } + + WaitForCountDownToFinish(); + EXPECT_FALSE(ProjectorSession::Get()->is_active()); + EXPECT_FALSE(controller->is_recording_in_progress()); + + // Prepare for next iteration by resetting things back to default. + test_delegate->ResetAllowancesToDefault(); + } +} + TEST_F(ProjectorCaptureModeIntegrationTests, RecordingOverlayWidget) { auto* controller = CaptureModeController::Get(); controller->SetSource(CaptureModeSource::kFullscreen);
diff --git a/ash/capture_mode/test_capture_mode_delegate.cc b/ash/capture_mode/test_capture_mode_delegate.cc index 6cc7a7b..73d15b0 100644 --- a/ash/capture_mode/test_capture_mode_delegate.cc +++ b/ash/capture_mode/test_capture_mode_delegate.cc
@@ -36,6 +36,11 @@ TestCaptureModeDelegate::~TestCaptureModeDelegate() = default; +void TestCaptureModeDelegate::ResetAllowancesToDefault() { + is_allowed_by_dlp_ = true; + is_allowed_by_policy_ = true; +} + viz::FrameSinkId TestCaptureModeDelegate::GetCurrentFrameSinkId() const { return recording_service_ ? recording_service_->GetCurrentFrameSinkId() : viz::FrameSinkId(); @@ -86,11 +91,11 @@ bool TestCaptureModeDelegate::IsCaptureAllowedByDlp(const aura::Window* window, const gfx::Rect& bounds, bool for_video) const { - return true; + return is_allowed_by_dlp_; } bool TestCaptureModeDelegate::IsCaptureAllowedByPolicy() const { - return true; + return is_allowed_by_policy_; } void TestCaptureModeDelegate::StartObservingRestrictedContent(
diff --git a/ash/capture_mode/test_capture_mode_delegate.h b/ash/capture_mode/test_capture_mode_delegate.h index 6655f98..8fd3d59 100644 --- a/ash/capture_mode/test_capture_mode_delegate.h +++ b/ash/capture_mode/test_capture_mode_delegate.h
@@ -34,6 +34,11 @@ void set_on_recording_started_callback(base::OnceClosure callback) { on_recording_started_callback_ = std::move(callback); } + void set_is_allowed_by_dlp(bool value) { is_allowed_by_dlp_ = value; } + void set_is_allowed_by_policy(bool value) { is_allowed_by_policy_ = value; } + + // Resets |is_allowed_by_policy_| and |is_allowed_by_dlp_| back to true. + void ResetAllowancesToDefault(); // Gets the current frame sink id being captured by the service. viz::FrameSinkId GetCurrentFrameSinkId() const; @@ -81,6 +86,8 @@ std::unique_ptr<recording::RecordingServiceTestApi> recording_service_; base::FilePath fake_downloads_dir_; base::OnceClosure on_recording_started_callback_; + bool is_allowed_by_dlp_ = true; + bool is_allowed_by_policy_ = true; }; } // namespace ash
diff --git a/ash/constants/ash_features.cc b/ash/constants/ash_features.cc index 9714885..d71619d 100644 --- a/ash/constants/ash_features.cc +++ b/ash/constants/ash_features.cc
@@ -862,6 +862,10 @@ const base::Feature kPhoneHubCameraRoll{"PhoneHubCameraRoll", base::FEATURE_DISABLED_BY_DEFAULT}; +// Enables the incoming/ongoing call notification feature in Phone Hub. +const base::Feature kPhoneHubCallNotification{ + "PhoneHubCallNotification", base::FEATURE_DISABLED_BY_DEFAULT}; + // Enables the Recent Apps feature in Phone Hub, which allows users to relaunch // the streamed app. const base::Feature kPhoneHubRecentApps{"PhoneHubRecentApps", @@ -1575,6 +1579,10 @@ return base::FeatureList::IsEnabled(kPhoneHub); } +bool IsPhoneHubCallNotificationEnabled() { + return base::FeatureList::IsEnabled(kPhoneHubCallNotification); +} + bool IsPhoneHubRecentAppsEnabled() { return base::FeatureList::IsEnabled(kPhoneHubRecentApps); }
diff --git a/ash/constants/ash_features.h b/ash/constants/ash_features.h index 24babae..d512de5 100644 --- a/ash/constants/ash_features.h +++ b/ash/constants/ash_features.h
@@ -326,6 +326,8 @@ extern const base::Feature kPerformantSplitViewResizing; COMPONENT_EXPORT(ASH_CONSTANTS) extern const base::Feature kPhoneHub; COMPONENT_EXPORT(ASH_CONSTANTS) extern const base::Feature kPhoneHubCameraRoll; +COMPONENT_EXPORT(ASH_CONSTANTS) +extern const base::Feature kPhoneHubCallNotification; COMPONENT_EXPORT(ASH_CONSTANTS) extern const base::Feature kPhoneHubRecentApps; COMPONENT_EXPORT(ASH_CONSTANTS) extern const base::Feature kPinSetupForManagedUsers; @@ -547,6 +549,7 @@ COMPONENT_EXPORT(ASH_CONSTANTS) bool IsPhoneHubCameraRollEnabled(); COMPONENT_EXPORT(ASH_CONSTANTS) bool IsPerformantSplitViewResizingEnabled(); COMPONENT_EXPORT(ASH_CONSTANTS) bool IsPhoneHubEnabled(); +COMPONENT_EXPORT(ASH_CONSTANTS) bool IsPhoneHubCallNotificationEnabled(); COMPONENT_EXPORT(ASH_CONSTANTS) bool IsPhoneHubRecentAppsEnabled(); COMPONENT_EXPORT(ASH_CONSTANTS) bool IsPinAutosubmitBackfillFeatureEnabled(); COMPONENT_EXPORT(ASH_CONSTANTS) bool IsPinAutosubmitFeatureEnabled();
diff --git a/ash/projector/projector_controller_impl.cc b/ash/projector/projector_controller_impl.cc index d0ce925..9ee9cbba 100644 --- a/ash/projector/projector_controller_impl.cc +++ b/ash/projector/projector_controller_impl.cc
@@ -11,6 +11,7 @@ #include "ash/public/cpp/projector/projector_client.h" #include "ash/public/cpp/projector/projector_session.h" #include "ash/shell.h" +#include "base/bind.h" #include "base/files/file_path.h" #include "base/files/file_util.h" #include "base/strings/stringprintf.h" @@ -77,8 +78,12 @@ auto* controller = CaptureModeController::Get(); if (!controller->is_recording_in_progress()) { - projector_session_->Start(storage_dir); + // A capture mode session can be blocked by many factors, such as policy, + // DLP, ... etc. We don't start a Projector session until we're sure a + // capture session started. controller->Start(CaptureModeEntryType::kProjector); + if (controller->IsActive()) + projector_session_->Start(storage_dir); } } @@ -203,6 +208,21 @@ client_->OpenProjectorApp(); } +void ProjectorControllerImpl::OnRecordingStartAborted() { + DCHECK(projector_session_->is_active()); + + // Delete the DriveFS path that might have been created for this aborted + // session if any. + if (projector_session_->screencast_container_path()) { + base::ThreadPool::PostTask( + FROM_HERE, {base::MayBlock()}, + base::BindOnce(base::GetDeletePathRecursivelyCallback(), + *projector_session_->screencast_container_path())); + } + + projector_session_->Stop(); +} + void ProjectorControllerImpl::OnLaserPointerPressed() { ui_controller_->OnLaserPointerPressed(); }
diff --git a/ash/projector/projector_controller_impl.h b/ash/projector/projector_controller_impl.h index 813aaff..1ada094 100644 --- a/ash/projector/projector_controller_impl.h +++ b/ash/projector/projector_controller_impl.h
@@ -76,6 +76,11 @@ void OnRecordingStarted(); void OnRecordingEnded(); + // Called by Capture Mode to notify us that a Projector-initiated recording + // session was aborted (i.e. recording was never started) due to e.g. user + // cancellation, an error, or a DLP/HDCP restriction. + void OnRecordingStartAborted(); + // Invoked when laser pointer button is pressed. void OnLaserPointerPressed(); // Invoked when marker button is pressed.
diff --git a/ash/style/button_style.cc b/ash/style/button_style.cc new file mode 100644 index 0000000..8873caf --- /dev/null +++ b/ash/style/button_style.cc
@@ -0,0 +1,192 @@ +// Copyright 2021 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/style/button_style.h" + +#include "ash/style/ash_color_provider.h" +#include "base/bind.h" +#include "ui/base/metadata/metadata_impl_macros.h" +#include "ui/gfx/paint_vector_icon.h" +#include "ui/views/animation/flood_fill_ink_drop_ripple.h" +#include "ui/views/animation/ink_drop.h" +#include "ui/views/animation/ink_drop_highlight.h" +#include "ui/views/background.h" +#include "ui/views/controls/highlight_path_generator.h" + +namespace ash { + +namespace { + +constexpr gfx::Size kPillButtonSize(32, 32); +constexpr int kIconSize = 20; +constexpr int kIconPillButtonImageLabelSpacingDp = 8; + +constexpr gfx::Insets kInkDropInsets(4); + +SkColor GetPillButtonBackgroundColor(PillButton::Type type) { + AshColorProvider::ControlsLayerType color_id = + AshColorProvider::ControlsLayerType::kControlBackgroundColorInactive; + switch (type) { + case PillButton::Type::kIcon: + case PillButton::Type::kIconless: + case PillButton::Type::kIconlessAccent: + break; + case PillButton::Type::kIconlessAlert: + color_id = + AshColorProvider::ControlsLayerType::kControlBackgroundColorAlert; + break; + case PillButton::Type::kIconlessProminent: + color_id = + AshColorProvider::ControlsLayerType::kControlBackgroundColorActive; + break; + } + return AshColorProvider::Get()->GetControlsLayerColor(color_id); +} + +SkColor GetPillButtonTextColor(PillButton::Type type) { + AshColorProvider::ContentLayerType color_id = + AshColorProvider::ContentLayerType::kButtonLabelColor; + switch (type) { + case PillButton::Type::kIcon: + case PillButton::Type::kIconless: + case PillButton::Type::kIconlessProminent: + break; + case PillButton::Type::kIconlessAlert: + color_id = AshColorProvider::ContentLayerType::kButtonLabelColorPrimary; + break; + case PillButton::Type::kIconlessAccent: + color_id = AshColorProvider::ContentLayerType::kButtonLabelColorBlue; + break; + } + return AshColorProvider::Get()->GetContentLayerColor(color_id); +} + +gfx::Insets GetInkDropInsets(TrayPopupInkDropStyle ink_drop_style) { + if (ink_drop_style == TrayPopupInkDropStyle::HOST_CENTERED || + ink_drop_style == TrayPopupInkDropStyle::INSET_BOUNDS) { + return kInkDropInsets; + } + return gfx::Insets(); +} + +gfx::Size GetPillButtonSize(bool has_icon) { + gfx::Size button_size(kPillButtonSize); + if (has_icon) { + button_size.set_width(button_size.width() + kIconSize + + kIconPillButtonImageLabelSpacingDp); + } + return button_size; +} + +std::unique_ptr<views::InkDrop> CreateInkDrop(views::Button* host, + bool highlight_on_hover, + bool highlight_on_focus) { + return views::InkDrop::CreateInkDropForFloodFillRipple( + views::InkDrop::Get(host), highlight_on_hover, highlight_on_focus); +} + +std::unique_ptr<views::InkDropRipple> CreateInkDropRipple( + TrayPopupInkDropStyle ink_drop_style, + const views::Button* host) { + const AshColorProvider::RippleAttributes ripple_attributes = + AshColorProvider::Get()->GetRippleAttributes(); + return std::make_unique<views::FloodFillInkDropRipple>( + host->size(), GetInkDropInsets(ink_drop_style), + views::InkDrop::Get(host)->GetInkDropCenterBasedOnLastEvent(), + ripple_attributes.base_color, ripple_attributes.inkdrop_opacity); +} + +std::unique_ptr<views::InkDropHighlight> CreateInkDropHighlight( + const views::View* host) { + const AshColorProvider::RippleAttributes ripple_attributes = + AshColorProvider::Get()->GetRippleAttributes(); + auto highlight = std::make_unique<views::InkDropHighlight>( + gfx::SizeF(host->size()), ripple_attributes.base_color); + highlight->set_visible_opacity(ripple_attributes.highlight_opacity); + return highlight; +} + +} // namespace + +// static +void PillButton::ConfigureInkDrop(views::Button* button, + TrayPopupInkDropStyle ink_drop_style, + bool highlight_on_hover, + bool highlight_on_focus) { + button->SetInstallFocusRingOnFocus(true); + views::InkDropHost* const ink_drop = views::InkDrop::Get(button); + ink_drop->SetMode(views::InkDropHost::InkDropMode::ON); + button->SetHasInkDropActionOnClick(true); + ink_drop->SetCreateInkDropCallback(base::BindRepeating( + &CreateInkDrop, button, highlight_on_hover, highlight_on_focus)); + ink_drop->SetCreateRippleCallback( + base::BindRepeating(&CreateInkDropRipple, ink_drop_style, button)); + ink_drop->SetCreateHighlightCallback( + base::BindRepeating(&CreateInkDropHighlight, button)); +} + +PillButton::PillButton(PressedCallback callback, + const std::u16string& text, + PillButton::Type type, + const gfx::VectorIcon* icon) + : views::LabelButton(std::move(callback), text), + type_(type), + button_size_(GetPillButtonSize(type_ == PillButton::Type::kIcon)), + icon_(icon) { + SetHorizontalAlignment(gfx::ALIGN_CENTER); + SetBorder(views::CreateEmptyBorder(gfx::Insets())); + label()->SetElideBehavior(gfx::NO_ELIDE); + label()->SetSubpixelRenderingEnabled(false); + // TODO: Unify the font size, weight under ash/style as well. + label()->SetFontList(views::Label::GetDefaultFontList().Derive( + 1, gfx::Font::NORMAL, gfx::Font::Weight::MEDIUM)); + ConfigureInkDrop(this, TrayPopupInkDropStyle::FILL_BOUNDS, + /*highlight_on_hover=*/false, /*highlight_on_focus=*/false); + views::InstallRoundRectHighlightPathGenerator(this, gfx::Insets(), + button_size_.height() / 2.f); + SetBackground(views::CreateRoundedRectBackground( + GetPillButtonBackgroundColor(type), button_size_.height() / 2.f)); +} + +PillButton::~PillButton() = default; + +gfx::Size PillButton::CalculatePreferredSize() const { + return gfx::Size(label()->GetPreferredSize().width() + button_size_.width(), + button_size_.height()); +} + +int PillButton::GetHeightForWidth(int width) const { + return button_size_.height(); +} + +void PillButton::OnThemeChanged() { + views::LabelButton::OnThemeChanged(); + + auto* color_provider = AshColorProvider::Get(); + if (type_ == PillButton::Type::kIcon) { + DCHECK(icon_); + const SkColor enabled_icon_color = color_provider->GetContentLayerColor( + AshColorProvider::ContentLayerType::kButtonIconColor); + SetImage(views::Button::STATE_NORMAL, + gfx::CreateVectorIcon(*icon_, kIconSize, enabled_icon_color)); + SetImage(views::Button::STATE_DISABLED, + gfx::CreateVectorIcon( + *icon_, kIconSize, + AshColorProvider::GetDisabledColor(enabled_icon_color))); + SetImageLabelSpacing(kIconPillButtonImageLabelSpacingDp); + } + + const SkColor enabled_text_color = GetPillButtonTextColor(type_); + SetEnabledTextColors(enabled_text_color); + SetTextColor(views::Button::STATE_DISABLED, + AshColorProvider::GetDisabledColor(enabled_text_color)); + views::FocusRing::Get(this)->SetColor(color_provider->GetControlsLayerColor( + AshColorProvider::ControlsLayerType::kFocusRingColor)); + background()->SetNativeControlColor(GetPillButtonBackgroundColor(type_)); +} + +BEGIN_METADATA(PillButton, views::LabelButton) +END_METADATA + +} // namespace ash
diff --git a/ash/style/button_style.h b/ash/style/button_style.h new file mode 100644 index 0000000..ea0c7c2a1 --- /dev/null +++ b/ash/style/button_style.h
@@ -0,0 +1,68 @@ +// Copyright 2021 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_STYLE_BUTTON_STYLE_H_ +#define ASH_STYLE_BUTTON_STYLE_H_ + +#include "ash/system/tray/tray_popup_ink_drop_style.h" +#include "ui/base/metadata/metadata_header_macros.h" +#include "ui/views/controls/button/label_button.h" + +namespace ash { + +// A label button with a rounded rectangle background. It can have an icon +// inside as well, and its text and background colors will be different based on +// the type of the button. +class PillButton : public views::LabelButton { + public: + METADATA_HEADER(PillButton); + + // Types of the PillButton. + enum class Type { + // PillButton with an icon, default text and background colors. + kIcon, + // PillButton without an icon, default text and background colors. + kIconless, + // PillButton without an icon, `kButtonLabelColorPrimary` as the text color + // and `kControlBackgroundColorAlert` as the background color. + kIconlessAlert, + // PillButton without an icon, `kButtonLabelColorBlue` as the text color and + // default background color. + kIconlessAccent, + // PillButton without an icon, default text color and + // `kControlBackgroundColorActive` as the background color. + kIconlessProminent + }; + + // TODO: Move this function outside of PillButton after we built up more + // button styles under this file. And remove all the corresponding functions + // from TrayPopupUtils to make all the clients get the ink drop styles from + // ash/style. + static void ConfigureInkDrop(views::Button* button, + TrayPopupInkDropStyle style, + bool highlight_on_hover, + bool highlight_on_focus); + + PillButton(PressedCallback callback, + const std::u16string& text, + Type type, + const gfx::VectorIcon* icon); + PillButton(const PillButton&) = delete; + PillButton& operator=(const PillButton&) = delete; + ~PillButton() override; + + // views::LabelButton: + gfx::Size CalculatePreferredSize() const override; + int GetHeightForWidth(int width) const override; + void OnThemeChanged() override; + + private: + const Type type_; + gfx::Size button_size_; + const gfx::VectorIcon* const icon_; +}; + +} // namespace ash + +#endif // ASH_STYLE_BUTTON_STYLE_H_
diff --git a/ash/system/night_light/night_light_controller_unittest.cc b/ash/system/night_light/night_light_controller_unittest.cc index a299a027..6a2e07b 100644 --- a/ash/system/night_light/night_light_controller_unittest.cc +++ b/ash/system/night_light/night_light_controller_unittest.cc
@@ -1919,7 +1919,7 @@ } // Turn color temperature down. - float ambient_temperature = SimulateAmbientColorFromPowerd(8000, 7350.0f); + SimulateAmbientColorFromPowerd(8000, 7350.0f); auto internal_rgb = GetDisplayCompositorRGBScaleFactors(kInternalDisplayId); auto external_rgb = GetDisplayCompositorRGBScaleFactors(kExternalDisplayId); @@ -1932,7 +1932,7 @@ EXPECT_TRUE((external_rgb - gfx::Vector3dF(1.0f, 1.0f, 1.0f)).IsZero()); // Turn color temperature up. - ambient_temperature = SimulateAmbientColorFromPowerd(2700, 5800.0f); + SimulateAmbientColorFromPowerd(2700, 5800.0f); internal_rgb = GetDisplayCompositorRGBScaleFactors(kInternalDisplayId); external_rgb = GetDisplayCompositorRGBScaleFactors(kExternalDisplayId);
diff --git a/ash/system/unified/sign_out_button.cc b/ash/system/unified/sign_out_button.cc deleted file mode 100644 index 4818178..0000000 --- a/ash/system/unified/sign_out_button.cc +++ /dev/null
@@ -1,25 +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 "ash/system/unified/sign_out_button.h" - -#include "ash/session/session_controller_impl.h" -#include "ash/shell.h" -#include "ash/system/user/login_status.h" - -namespace ash { - -SignOutButton::SignOutButton(PressedCallback callback) - : RoundedLabelButton(std::move(callback), - user::GetLocalizedSignOutStringForStatus( - Shell::Get()->session_controller()->login_status(), - false /* multiline */)) {} - -SignOutButton::~SignOutButton() = default; - -const char* SignOutButton::GetClassName() const { - return "SignOutButton"; -} - -} // namespace ash
diff --git a/ash/system/unified/sign_out_button.h b/ash/system/unified/sign_out_button.h deleted file mode 100644 index 8aac6dc..0000000 --- a/ash/system/unified/sign_out_button.h +++ /dev/null
@@ -1,31 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef ASH_SYSTEM_UNIFIED_SIGN_OUT_BUTTON_H_ -#define ASH_SYSTEM_UNIFIED_SIGN_OUT_BUTTON_H_ - -#include "ash/system/unified/rounded_label_button.h" -#include "base/macros.h" - -namespace ash { - -// Sign out button to be shown in TopShortcutView with TopShortcutButtons. -// Shows the label like "Sign out", "Exit guest", etc. depending on the session -// status. -class SignOutButton : public RoundedLabelButton { - public: - explicit SignOutButton(PressedCallback callback); - - SignOutButton(const SignOutButton&) = delete; - SignOutButton& operator=(const SignOutButton&) = delete; - - ~SignOutButton() override; - - // views::RoundedLabelButton: - const char* GetClassName() const override; -}; - -} // namespace ash - -#endif // ASH_SYSTEM_UNIFIED_SIGN_OUT_BUTTON_H_
diff --git a/ash/system/unified/top_shortcuts_view.cc b/ash/system/unified/top_shortcuts_view.cc index 0da1adc..574a056 100644 --- a/ash/system/unified/top_shortcuts_view.cc +++ b/ash/system/unified/top_shortcuts_view.cc
@@ -15,14 +15,16 @@ #include "ash/shutdown_controller_impl.h" #include "ash/strings/grit/ash_strings.h" #include "ash/style/ash_color_provider.h" +#include "ash/style/button_style.h" #include "ash/system/tray/tray_constants.h" #include "ash/system/tray/tray_popup_utils.h" #include "ash/system/unified/collapse_button.h" -#include "ash/system/unified/sign_out_button.h" +#include "ash/system/unified/rounded_label_button.h" #include "ash/system/unified/top_shortcut_button.h" #include "ash/system/unified/unified_system_tray_controller.h" #include "ash/system/unified/user_chooser_detailed_view_controller.h" #include "ash/system/unified/user_chooser_view.h" +#include "ash/system/user/login_status.h" #include "base/bind.h" #include "base/numerics/ranges.h" #include "components/prefs/pref_registry_simple.h" @@ -198,9 +200,14 @@ UserChooserDetailedViewController::IsUserChooserEnabled()); container_->AddUserAvatarButton(user_avatar_button_); - sign_out_button_ = new SignOutButton( + sign_out_button_ = new PillButton( base::BindRepeating(&UnifiedSystemTrayController::HandleSignOutAction, - base::Unretained(controller))); + base::Unretained(controller)), + user::GetLocalizedSignOutStringForStatus( + Shell::Get()->session_controller()->login_status(), + /*multiline=*/false), + PillButton::Type::kIconless, + /*icon=*/nullptr); container_->AddSignOutButton(sign_out_button_); }
diff --git a/ash/system/unified/top_shortcuts_view.h b/ash/system/unified/top_shortcuts_view.h index 579a417..74ef741 100644 --- a/ash/system/unified/top_shortcuts_view.h +++ b/ash/system/unified/top_shortcuts_view.h
@@ -19,7 +19,6 @@ namespace ash { class CollapseButton; -class SignOutButton; class TopShortcutButton; class TopShortcutsViewTest; class UnifiedSystemTrayController; @@ -75,7 +74,7 @@ // Owned by views hierarchy. views::Button* user_avatar_button_ = nullptr; - SignOutButton* sign_out_button_ = nullptr; + views::Button* sign_out_button_ = nullptr; TopShortcutButtonContainer* container_ = nullptr; TopShortcutButton* lock_button_ = nullptr; TopShortcutButton* settings_button_ = nullptr;
diff --git a/ash/system/unified/top_shortcuts_view_unittest.cc b/ash/system/unified/top_shortcuts_view_unittest.cc index d2ec5faf5..ad2a8a3 100644 --- a/ash/system/unified/top_shortcuts_view_unittest.cc +++ b/ash/system/unified/top_shortcuts_view_unittest.cc
@@ -7,7 +7,6 @@ #include "ash/constants/ash_pref_names.h" #include "ash/session/test_session_controller_client.h" #include "ash/system/unified/collapse_button.h" -#include "ash/system/unified/sign_out_button.h" #include "ash/system/unified/top_shortcut_button.h" #include "ash/system/unified/unified_system_tray_controller.h" #include "ash/system/unified/unified_system_tray_model.h"
diff --git a/ash/webui/diagnostics_ui/diagnostics_ui.cc b/ash/webui/diagnostics_ui/diagnostics_ui.cc index ece4396..f3b5f67 100644 --- a/ash/webui/diagnostics_ui/diagnostics_ui.cc +++ b/ash/webui/diagnostics_ui/diagnostics_ui.cc
@@ -328,13 +328,7 @@ const diagnostics::SessionLogHandler::SelectFilePolicyCreator& select_file_policy_creator, HoldingSpaceClient* holding_space_client) - : ui::MojoWebDialogUI(web_ui), - session_log_handler_(std::make_unique<diagnostics::SessionLogHandler>( - select_file_policy_creator, - holding_space_client)) { - diagnostics_manager_ = std::make_unique<diagnostics::DiagnosticsManager>( - session_log_handler_.get()); - + : ui::MojoWebDialogUI(web_ui) { auto html_source = base::WrapUnique( content::WebUIDataSource::Create(kChromeUIDiagnosticsAppHost)); html_source->OverrideContentSecurityPolicy(
diff --git a/ash/webui/diagnostics_ui/diagnostics_ui.h b/ash/webui/diagnostics_ui/diagnostics_ui.h index f2d6f95..ce52f2d 100644 --- a/ash/webui/diagnostics_ui/diagnostics_ui.h +++ b/ash/webui/diagnostics_ui/diagnostics_ui.h
@@ -58,7 +58,6 @@ // metrics. base::Time open_timestamp_; - std::unique_ptr<diagnostics::SessionLogHandler> session_log_handler_; std::unique_ptr<diagnostics::DiagnosticsManager> diagnostics_manager_; };
diff --git a/ash/webui/diagnostics_ui/resources/overview_card.html b/ash/webui/diagnostics_ui/resources/overview_card.html index d9cfc0f..006e924 100644 --- a/ash/webui/diagnostics_ui/resources/overview_card.html +++ b/ash/webui/diagnostics_ui/resources/overview_card.html
@@ -5,13 +5,14 @@ } #overviewCardContainer { + align-items: center; display: flex; height: 48px; justify-content: center; } #overviewChip { - margin-top: 14px; + margin-top: 8px; } </style> <div id="overviewCardContainer" tabindex="0"
diff --git a/ash/webui/scanning/resources/scan_preview.js b/ash/webui/scanning/resources/scan_preview.js index 8f465a87..f1caa35 100644 --- a/ash/webui/scanning/resources/scan_preview.js +++ b/ash/webui/scanning/resources/scan_preview.js
@@ -61,6 +61,15 @@ /** @private {number} */ actionToolbarWidth_: 0, + /** + * Stores the y value of the bottom of each scanned image in the preview div. + * The values are stored in the array in scanned image order so the value at + * [0] refers to the first scanned image, the value at [1] the second scanned + * image, etc. + * @private {!Array<number>} + */ + scrollingIntervals_: [], + properties: { /** @type {!AppState} */ appState: { @@ -338,7 +347,7 @@ } // If the current page in view stays the same, do nothing. - const pageIndexInView = this.getCurrentPageInView_(scannedImages); + const pageIndexInView = this.getCurrentPageInView_(); if (pageIndexInView === this.currentPageIndexInView_) { return; } @@ -347,28 +356,32 @@ }, /** - * Calculates the current page in view. Returns the page index of the highest - * page in the viewport unless that page is scrolled halfway outside the - * viewport, then it'll return the following page number. Assumes each scanned - * image is the same height. - * @param {!HTMLCollection} scannedImages + * Calculates the index of the current page in view based on where the current + * position of the scroll bar is found in |scrollingIntervals_|. * @return {number} * @private */ - getCurrentPageInView_(scannedImages) { + getCurrentPageInView_() { assert(this.isMultiPageScan); - const imageHeight = scannedImages[0].height; - const scrollTop = this.$$('#previewDiv').scrollTop - (imageHeight * .5); - - // This is a special case for the first page since there is no margin or - // previous page above it. - if (scrollTop < 0) { + if (this.objectUrls.length === 1) { return 0; } - return 1 + - Math.floor(scrollTop / (imageHeight + SCANNED_IMG_MARGIN_BOTTOM_PX)); + // |scrollTop| is a height value that ranges from 0 to the height at the + // bottom of div with all the scanned images. The height intervals in + // |scrollingIntervals_| are in order so the value at [0] refers to the + // first scanned image, at [1] the second scanned image, etc. + const scrollTop = this.$$('#previewDiv').scrollTop; + for (let i = 0; i < this.scrollingIntervals_.length; i++) { + // TODO(gavinwill): Convert from linear search to binary search. + if (scrollTop <= this.scrollingIntervals_[i]) { + return i; + } + } + + // The last image is the catch-all interval. + return this.objectUrls.length - 1; }, /** @@ -425,8 +438,7 @@ const scannedImages = this.$$('#scannedImages').getElementsByClassName('scanned-image'); - this.setFocusedScannedImage_( - scannedImages, this.getCurrentPageInView_(scannedImages)); + this.setFocusedScannedImage_(scannedImages, this.getCurrentPageInView_()); this.updatePreviewElements_(); @@ -584,7 +596,7 @@ } assert(pageIndex >= 0 && pageIndex < scannedImages.length); - const imageHeight = scannedImages[0].height; + const imageHeight = scannedImages[0].offsetHeight; // Use |pageIndex| to calculate the number of pages needed to scroll by to // get to our desired page. Ex: If we want to scroll to the page with @@ -638,6 +650,7 @@ * @private */ updatePreviewElements_() { + this.buildScrollingIntervals_(); this.setMultiPageScanProgressHeight_(); this.setActionToolbarPosition_(); }, @@ -676,4 +689,34 @@ return this.i18n( 'multiPageImageAriaLabel', index + 1, this.objectUrls.length); }, + + /** + * Divides the total scroll area of the scanned images into proportionate + * intervals based on each individual image's height. These intervals are used + * to determine which image should be focused on based on the position of the + * scroll bar. + * @private + */ + buildScrollingIntervals_() { + const scannedImages = + this.$$('#scannedImages').getElementsByClassName('scanned-image'); + if (scannedImages.length === 0) { + return; + } + + const totalImagesHeight = this.$$('#previewDiv').scrollHeight; + const maxScrollTop = + totalImagesHeight - this.$$('#previewDiv').offsetHeight; + this.scrollingIntervals_ = []; + let currentIntervalHeight = 0; + + // Only the first n - 1 images require intervals since the last image is the + // catch-all interval. + for (let i = 0; i < scannedImages.length - 1; i++) { + const scrollHeightProportion = + scannedImages[i].offsetHeight / totalImagesHeight; + currentIntervalHeight += maxScrollTop * scrollHeightProportion; + this.scrollingIntervals_.push(currentIntervalHeight); + } + }, });
diff --git a/ash/wm/desks/templates/desks_templates_delete_button.cc b/ash/wm/desks/templates/desks_templates_delete_button.cc new file mode 100644 index 0000000..9860e748 --- /dev/null +++ b/ash/wm/desks/templates/desks_templates_delete_button.cc
@@ -0,0 +1,33 @@ +// Copyright 2021 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/templates/desks_templates_delete_button.h" + +#include "ash/resources/vector_icons/vector_icons.h" +#include "ash/style/element_style.h" +#include "ui/base/l10n/l10n_util.h" +#include "ui/base/metadata/metadata_impl_macros.h" +#include "ui/strings/grit/ui_strings.h" + +namespace ash { + +DesksTemplatesDeleteButton::DesksTemplatesDeleteButton() { + views::Builder<DesksTemplatesDeleteButton>(this) + .SetImageHorizontalAlignment(views::ImageButton::ALIGN_CENTER) + .SetImageVerticalAlignment(views::ImageButton::ALIGN_MIDDLE) + .SetTooltipText(l10n_util::GetStringUTF16(IDS_APP_DELETE)) + .BuildChildren(); +} + +DesksTemplatesDeleteButton::~DesksTemplatesDeleteButton() = default; + +void DesksTemplatesDeleteButton::OnThemeChanged() { + views::ImageButton::OnThemeChanged(); + element_style::DecorateMediumCloseButton(this, kTrashCanIcon); +} + +BEGIN_METADATA(DesksTemplatesDeleteButton, views::ImageButton) +END_METADATA + +} // namespace ash
diff --git a/ash/wm/desks/templates/desks_templates_delete_button.h b/ash/wm/desks/templates/desks_templates_delete_button.h new file mode 100644 index 0000000..261b444 --- /dev/null +++ b/ash/wm/desks/templates/desks_templates_delete_button.h
@@ -0,0 +1,38 @@ +// Copyright 2021 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_TEMPLATES_DESKS_TEMPLATES_DELETE_BUTTON_H_ +#define ASH_WM_DESKS_TEMPLATES_DESKS_TEMPLATES_DELETE_BUTTON_H_ + +#include "ui/base/metadata/metadata_header_macros.h" +#include "ui/views/controls/button/image_button.h" + +namespace ash { + +// A button view that shows up when hovering over the associated grid item. +// Allows the user to delete the template. +class DesksTemplatesDeleteButton : public views::ImageButton { + public: + METADATA_HEADER(DesksTemplatesDeleteButton); + + DesksTemplatesDeleteButton(); + DesksTemplatesDeleteButton(const DesksTemplatesDeleteButton&) = delete; + DesksTemplatesDeleteButton& operator=(const DesksTemplatesDeleteButton&) = + delete; + ~DesksTemplatesDeleteButton() override; + + // views::ImageButton: + void OnThemeChanged() override; +}; + +BEGIN_VIEW_BUILDER(/* no export */, + DesksTemplatesDeleteButton, + views::ImageButton) +END_VIEW_BUILDER + +} // namespace ash + +DEFINE_VIEW_BUILDER(/* no export */, ash::DesksTemplatesDeleteButton) + +#endif // ASH_WM_DESKS_TEMPLATES_DESKS_TEMPLATES_DELETE_BUTTON_H_
diff --git a/ash/wm/desks/templates/desks_templates_grid_view.cc b/ash/wm/desks/templates/desks_templates_grid_view.cc index 13db15f5..afcb7be 100644 --- a/ash/wm/desks/templates/desks_templates_grid_view.cc +++ b/ash/wm/desks/templates/desks_templates_grid_view.cc
@@ -58,9 +58,11 @@ layout->StartRowWithPadding(fixed_size, kColumnSetId, fixed_size, kGridPaddingDp); } - - for (int j = 0; j < kNumColumns; ++j) - layout->AddView(std::make_unique<DesksTemplatesItemView>()); + for (int j = 0; j < kNumColumns; ++j) { + DesksTemplatesItemView* grid_item = + layout->AddView(std::make_unique<DesksTemplatesItemView>()); + grid_items_.push_back(grid_item); + } } } @@ -100,6 +102,45 @@ return widget; } +void DesksTemplatesGridView::OnMouseEvent(ui::MouseEvent* event) { + OnLocatedEvent(event, /*is_touch=*/false); +} + +void DesksTemplatesGridView::OnGestureEvent(ui::GestureEvent* event) { + OnLocatedEvent(event, /*is_touch=*/true); +} + +void DesksTemplatesGridView::AddedToWidget() { + // Adding a pre-target handler to ensure that events are not accidentally + // captured by the child views. Also, `this` is added as the pre-target + // handler to the window as opposed to `Env` to ensure that we only get events + // that are on this window. + widget_window_ = GetWidget()->GetNativeWindow(); + widget_window_->AddPreTargetHandler(this); +} + +void DesksTemplatesGridView::RemovedFromWidget() { + DCHECK(widget_window_); + widget_window_->RemovePreTargetHandler(this); + widget_window_ = nullptr; +} + +void DesksTemplatesGridView::OnLocatedEvent(ui::LocatedEvent* event, + bool is_touch) { + switch (event->type()) { + case ui::ET_MOUSE_MOVED: + case ui::ET_MOUSE_ENTERED: + case ui::ET_MOUSE_EXITED: + case ui::ET_GESTURE_LONG_PRESS: + case ui::ET_GESTURE_LONG_TAP: + for (auto* grid_item : grid_items_) + grid_item->UpdateDeleteButtonVisibility(); + return; + default: + return; + } +} + BEGIN_METADATA(DesksTemplatesGridView, views::View) END_METADATA
diff --git a/ash/wm/desks/templates/desks_templates_grid_view.h b/ash/wm/desks/templates/desks_templates_grid_view.h index 88b4d66..2e55dbf4 100644 --- a/ash/wm/desks/templates/desks_templates_grid_view.h +++ b/ash/wm/desks/templates/desks_templates_grid_view.h
@@ -11,8 +11,10 @@ namespace ash { +class DesksTemplatesItemView; + // A view that acts as the content view of the desks templates widget. -// TODO(sammiequon): Add details and ASCII. +// TODO(richui): Add details and ASCII. class DesksTemplatesGridView : public views::View { public: METADATA_HEADER(DesksTemplatesGridView); @@ -29,6 +31,22 @@ static views::UniqueWidgetPtr CreateDesksTemplatesGridWidget( aura::Window* root, const gfx::Rect& grid_bounds); + + // views::View: + void OnMouseEvent(ui::MouseEvent* event) override; + void OnGestureEvent(ui::GestureEvent* event) override; + void AddedToWidget() override; + void RemovedFromWidget() override; + + private: + // Helper to unify mouse/touch events. + void OnLocatedEvent(ui::LocatedEvent* event, bool is_touch); + + // The views representing templates. They're owned by views hierarchy. + std::vector<DesksTemplatesItemView*> grid_items_; + + // The underlying window of the templates grid widget. + aura::Window* widget_window_ = nullptr; }; } // namespace ash
diff --git a/ash/wm/desks/templates/desks_templates_item_view.cc b/ash/wm/desks/templates/desks_templates_item_view.cc index 287c15ab..31c9cbe 100644 --- a/ash/wm/desks/templates/desks_templates_item_view.cc +++ b/ash/wm/desks/templates/desks_templates_item_view.cc
@@ -4,8 +4,13 @@ #include "ash/wm/desks/templates/desks_templates_item_view.h" +#include "ash/accessibility/accessibility_controller_impl.h" +#include "ash/shell.h" +#include "ash/wm/desks/templates/desks_templates_delete_button.h" +#include "base/notreached.h" #include "ui/base/metadata/metadata_impl_macros.h" #include "ui/views/border.h" +#include "ui/views/layout/box_layout_view.h" namespace ash { @@ -18,42 +23,74 @@ constexpr gfx::Size kPreferredSize(250, 150); constexpr int kIconSpacingDp = 10; constexpr gfx::Size kPreviewIconSize(40, 40); +constexpr int kDeleteButtonMargin = 8; +constexpr int kDeleteButtonSize = 24; } // namespace DesksTemplatesItemView::DesksTemplatesItemView() { // TODO(richui): Remove all the borders. It is only used for visualizing // bounds while it is a placeholder. + auto delete_button_callback = base::BindRepeating( + &DesksTemplatesItemView::OnDeleteButtonPressed, base::Unretained(this)); + views::View* spacer; + views::BoxLayoutView* container; views::Builder<DesksTemplatesItemView>(this) - .SetOrientation(views::BoxLayout::Orientation::kVertical) - .SetCrossAxisAlignment(views::BoxLayout::CrossAxisAlignment::kStart) .SetPreferredSize(kPreferredSize) + .SetUseDefaultFillLayout(true) .SetBorder(views::CreateSolidBorder(/*thickness=*/2, SK_ColorDKGRAY)) .AddChildren( - views::Builder<views::View>() - .CopyAddressTo(&name_view_) - .SetPreferredSize(kViewSize) - .SetBorder(views::CreateSolidBorder( - /*thickness=*/2, SK_ColorGRAY)), - views::Builder<views::View>() - .CopyAddressTo(&time_view_) - .SetPreferredSize(kViewSize) - .SetBorder(views::CreateSolidBorder( - /*thickness=*/2, SK_ColorGRAY)), - views::Builder<views::View>().CopyAddressTo(&spacer), views::Builder<views::BoxLayoutView>() - .CopyAddressTo(&preview_view_) - .SetOrientation(views::BoxLayout::Orientation::kHorizontal) - .SetBetweenChildSpacing(kIconSpacingDp)) + .CopyAddressTo(&container) + .SetOrientation(views::BoxLayout::Orientation::kVertical) + .SetCrossAxisAlignment( + views::BoxLayout::CrossAxisAlignment::kStart) + .AddChildren(views::Builder<views::View>() + .CopyAddressTo(&name_view_) + .SetPreferredSize(kViewSize) + .SetBorder(views::CreateSolidBorder( + /*thickness=*/2, SK_ColorGRAY)), + views::Builder<views::View>() + .CopyAddressTo(&time_view_) + .SetPreferredSize(kViewSize) + .SetBorder(views::CreateSolidBorder( + /*thickness=*/2, SK_ColorGRAY)), + views::Builder<views::View>().CopyAddressTo(&spacer), + views::Builder<views::BoxLayoutView>() + .CopyAddressTo(&preview_view_) + .SetOrientation( + views::BoxLayout::Orientation::kHorizontal) + .SetBetweenChildSpacing(kIconSpacingDp)), + views::Builder<DesksTemplatesDeleteButton>() + .CopyAddressTo(&delete_button_) + .SetCallback(delete_button_callback)) .BuildChildren(); - SetFlexForView(spacer, 1); + container->SetFlexForView(spacer, 1); + UpdateDeleteButtonVisibility(); SetIcons(); } DesksTemplatesItemView::~DesksTemplatesItemView() = default; +void DesksTemplatesItemView::UpdateDeleteButtonVisibility() { + // For switch access, setting the delete button to visible allows users to + // navigate to it. + // TODO(richui): update `force_show_delete_button_` based on touch events. + delete_button_->SetVisible( + (IsMouseHovered() || force_show_delete_button_ || + Shell::Get()->accessibility_controller()->IsSwitchAccessRunning())); +} + +void DesksTemplatesItemView::Layout() { + views::View::Layout(); + + delete_button_->SetBoundsRect( + gfx::Rect(width() - kDeleteButtonSize - kDeleteButtonMargin, + kDeleteButtonMargin, kDeleteButtonSize, kDeleteButtonSize)); +} + void DesksTemplatesItemView::SetIcons() { for (int i = 0; i < kMaxIcons; ++i) { preview_view_->AddChildView(views::Builder<views::View>() @@ -64,7 +101,12 @@ } } -BEGIN_METADATA(DesksTemplatesItemView, views::BoxLayoutView) +void DesksTemplatesItemView::OnDeleteButtonPressed() { + // TODO(richui): Hook this up to the presenter. + NOTIMPLEMENTED(); +} + +BEGIN_METADATA(DesksTemplatesItemView, views::View) END_METADATA } // namespace ash
diff --git a/ash/wm/desks/templates/desks_templates_item_view.h b/ash/wm/desks/templates/desks_templates_item_view.h index 496ddf85..a2b5f27 100644 --- a/ash/wm/desks/templates/desks_templates_item_view.h +++ b/ash/wm/desks/templates/desks_templates_item_view.h
@@ -6,13 +6,19 @@ #define ASH_WM_DESKS_TEMPLATES_DESKS_TEMPLATES_ITEM_VIEW_H_ #include "ui/base/metadata/metadata_header_macros.h" -#include "ui/views/layout/box_layout_view.h" +#include "ui/views/view.h" + +namespace views { +class BoxLayoutView; +} namespace ash { +class DesksTemplatesDeleteButton; + // A view that represents each individual template item in the desks templates // grid. -class DesksTemplatesItemView : public views::BoxLayoutView { +class DesksTemplatesItemView : public views::View { public: METADATA_HEADER(DesksTemplatesItemView); @@ -21,19 +27,31 @@ DesksTemplatesItemView& operator=(const DesksTemplatesItemView&) = delete; ~DesksTemplatesItemView() override; + // Updates the visibility state of the delete button depending on whether this + // view is mouse hovered, or if switch access is enabled. + void UpdateDeleteButtonVisibility(); + + // views::View: + void Layout() override; + private: // TODO(richui): Pass a list of icons as the parameter. void SetIcons(); + void OnDeleteButtonPressed(); + // Owned by the views hierarchy. views::View* name_view_ = nullptr; views::View* time_view_ = nullptr; views::BoxLayoutView* preview_view_ = nullptr; + DesksTemplatesDeleteButton* delete_button_ = nullptr; + + // We force showing the delete button when `this` is long pressed or tapped + // using touch gestures. + bool force_show_delete_button_ = false; }; -BEGIN_VIEW_BUILDER(/* no export */, - DesksTemplatesItemView, - views::BoxLayoutView) +BEGIN_VIEW_BUILDER(/* no export */, DesksTemplatesItemView, views::View) END_VIEW_BUILDER } // namespace ash
diff --git a/ash/wm/overview/overview_controller.cc b/ash/wm/overview/overview_controller.cc index 18738bb..2707a37 100644 --- a/ash/wm/overview/overview_controller.cc +++ b/ash/wm/overview/overview_controller.cc
@@ -202,8 +202,9 @@ std::unique_ptr<DelayedAnimationObserver> animation_observer) { // No delayed animations should be created when overview mode is set to exit // immediately. - DCHECK_NE(overview_session_->enter_exit_overview_type(), - OverviewEnterExitType::kImmediateExit); + DCHECK(IsCompletingShutdownAnimations() || + overview_session_->enter_exit_overview_type() != + OverviewEnterExitType::kImmediateExit); animation_observer->SetOwner(this); delayed_animations_.push_back(std::move(animation_observer));
diff --git a/ash/wm/overview/overview_grid.cc b/ash/wm/overview/overview_grid.cc index a3942ef7..3a1a462 100644 --- a/ash/wm/overview/overview_grid.cc +++ b/ash/wm/overview/overview_grid.cc
@@ -463,8 +463,8 @@ window_list_.clear(); - if (desks_templates_grid_) - desks_templates_grid_->CloseNow(); + if (desks_templates_grid_widget_) + desks_templates_grid_widget_->CloseNow(); overview_session_ = nullptr; @@ -857,17 +857,18 @@ } void OverviewGrid::ShowDesksTemplatesGrid() { - if (!desks_templates_grid_) { - desks_templates_grid_ = + if (!desks_templates_grid_widget_) { + desks_templates_grid_widget_ = DesksTemplatesGridView::CreateDesksTemplatesGridWidget( root_window_, GetGridEffectiveBounds()); } - desks_templates_grid_->Show(); + desks_templates_grid_widget_->Show(); } bool OverviewGrid::IsShowingDesksTemplatesGrid() const { - return desks_templates_grid_ && desks_templates_grid_->IsVisible(); + return desks_templates_grid_widget_ && + desks_templates_grid_widget_->IsVisible(); } void OverviewGrid::UpdateNoWindowsWidget(bool no_items) { @@ -1060,8 +1061,8 @@ UpdateCannotSnapWarningVisibility(); - if (desks_templates_grid_) - desks_templates_grid_->SetBounds(GetGridEffectiveBounds()); + if (desks_templates_grid_widget_) + desks_templates_grid_widget_->SetBounds(GetGridEffectiveBounds()); // In case of split view mode, the grid bounds and item positions will be // updated in |OnSplitViewDividerPositionChanged|.
diff --git a/ash/wm/overview/overview_grid.h b/ash/wm/overview/overview_grid.h index f3f7df9..79835301 100644 --- a/ash/wm/overview/overview_grid.h +++ b/ash/wm/overview/overview_grid.h
@@ -550,7 +550,7 @@ aura::Window* dragged_window_ = nullptr; // The widget that contains the view for all the existing templates. - views::UniqueWidgetPtr desks_templates_grid_; + views::UniqueWidgetPtr desks_templates_grid_widget_; // A widget that contains a button which creates a new desk template when // pressed.
diff --git a/ash/wm/splitview/split_view_constants.h b/ash/wm/splitview/split_view_constants.h index aaf1221..8768096 100644 --- a/ash/wm/splitview/split_view_constants.h +++ b/ash/wm/splitview/split_view_constants.h
@@ -74,6 +74,15 @@ constexpr float kPreviewAreaHighlightOpacity = 0.18f; constexpr float kDarkLightPreviewAreaHighlightOpacity = 0.2f; +// In portrait mode split view, if the caret in the bottom window is less than +// `kMinCaretKeyboardDist` dip above the upper bounds of the virtual keyboard, +// then we push up the bottom window above the virtual keyboard to avoid the +// input field being occluded by the virtual keyboard. The upper bounds of the +// bottom window after being pushed up cannot exceeds 1 - +// `kMinDividerPositionRatio` of screen height. +constexpr int kMinCaretKeyboardDist = 16; +constexpr float kMinDividerPositionRatio = 0.15f; + } // namespace ash #endif // ASH_WM_SPLITVIEW_SPLIT_VIEW_CONSTANTS_H_
diff --git a/ash/wm/splitview/split_view_controller.cc b/ash/wm/splitview/split_view_controller.cc index e4f0426..c410430d 100644 --- a/ash/wm/splitview/split_view_controller.cc +++ b/ash/wm/splitview/split_view_controller.cc
@@ -24,9 +24,11 @@ #include "ash/style/default_colors.h" #include "ash/wm/desks/desks_controller.h" #include "ash/wm/mru_window_tracker.h" +#include "ash/wm/overview/delayed_animation_observer_impl.h" #include "ash/wm/overview/overview_controller.h" #include "ash/wm/overview/overview_grid.h" #include "ash/wm/overview/overview_item.h" +#include "ash/wm/overview/overview_types.h" #include "ash/wm/overview/overview_utils.h" #include "ash/wm/splitview/split_view_constants.h" #include "ash/wm/splitview/split_view_divider.h" @@ -97,15 +99,6 @@ constexpr float kBlackScrimFadeInRatio = 0.1f; constexpr float kBlackScrimOpacity = 0.4f; -// In portrait mode split view, if the caret in the bottom window is less than -// `kMinCaretKeyboardDist` dip above the upper bounds of the virtual keyboard, -// then we push up the bottom window above the virtual keyboard to avoid the -// input field being occluded by the virtual keyboard. The upper bounds of the -// bottom window after being pushed up cannot exceeds 1 - -// `kMinDividerPositionRatio` of screen height. -constexpr int kMinCaretKeyboardDist = 16; -constexpr float kMinDividerPositionRatio = 0.15f; - // If performant split view resizing is enabled, the speed at which the divider // is moved controls whether windows are scaled or translated. If the divider is // moved more than this many pixels per second, the "fast" mode is enabled. @@ -887,7 +880,6 @@ OverviewSession* overview_session = GetOverviewSession(); RemoveSnappingWindowFromOverviewIfApplicable(overview_session, window); - bool do_divider_spawn_animation = false; if (state_ == State::kNoSnap) { // Add observers when the split view mode starts. Shell::Get()->AddShellObserver(this); @@ -908,20 +900,6 @@ // There is no divider bar in clamshell splitview mode. if (split_view_type_ == SplitViewType::kTabletType) { split_view_divider_ = std::make_unique<SplitViewDivider>(this); - // The divider spawn animation adds a finishing touch to the |window| - // animation that generally accommodates snapping by dragging, but if - // |window| is currently minimized then it will undergo the unminimizing - // animation instead. Therefore skip the divider spawn animation if - // |window| is minimized. - if (!WindowState::Get(window)->IsMinimized() && - !window->transform().IsIdentity()) { - // For the divider spawn animation, at the end of the delay, the divider - // shall be visually aligned with an edge of |window|. This effect will - // be more easily achieved after |window| has been snapped and the - // corresponding transform animation has begun. So for now, just set a - // flag to indicate that the divider spawn animation should be done. - do_divider_spawn_animation = true; - } } splitview_start_time_ = base::Time::Now(); @@ -2510,12 +2488,33 @@ if (new_start_transform != window_iter->layer()->GetTargetTransform()) window_iter->SetTransform(new_start_transform); - DoSplitviewTransformAnimation( - window_iter->layer(), SPLITVIEW_ANIMATION_SET_WINDOW_TRANSFORM, - new_target_transform, - window_iter == window - ? std::make_unique<WindowTransformAnimationObserver>(window) - : nullptr); + std::vector<ui::ImplicitAnimationObserver*> animation_observers; + if (window_iter == window) { + animation_observers.push_back( + new WindowTransformAnimationObserver(window)); + + // If the overview exit animation is in progress or is about to start, add + // the |window| snap animation as one of the animations to be completed + // before |OverviewController::OnEndingAnimationComplete| should be called + // to unpause occlusion tracking, unblur the wallpaper, etc. + OverviewController* overview_controller = + Shell::Get()->overview_controller(); + if (overview_controller->IsCompletingShutdownAnimations() || + (overview_controller->overview_session() && + overview_controller->overview_session()->is_shutting_down() && + overview_controller->overview_session() + ->enter_exit_overview_type() != + OverviewEnterExitType::kImmediateExit)) { + auto overview_exit_animation_observer = + std::make_unique<ExitAnimationObserver>(); + animation_observers.push_back(overview_exit_animation_observer.get()); + overview_controller->AddExitAnimationObserver( + std::move(overview_exit_animation_observer)); + } + } + DoSplitviewTransformAnimation(window_iter->layer(), + SPLITVIEW_ANIMATION_SET_WINDOW_TRANSFORM, + new_target_transform, animation_observers); } }
diff --git a/ash/wm/splitview/split_view_controller.h b/ash/wm/splitview/split_view_controller.h index 255d3ec0c..fe125df6 100644 --- a/ash/wm/splitview/split_view_controller.h +++ b/ash/wm/splitview/split_view_controller.h
@@ -7,6 +7,7 @@ #include <limits> #include <memory> +#include <vector> #include "ash/accessibility/accessibility_observer.h" #include "ash/ash_export.h"
diff --git a/ash/wm/splitview/split_view_controller_unittest.cc b/ash/wm/splitview/split_view_controller_unittest.cc index 5ba35f1..a416bdc 100644 --- a/ash/wm/splitview/split_view_controller_unittest.cc +++ b/ash/wm/splitview/split_view_controller_unittest.cc
@@ -13,8 +13,11 @@ #include "ash/accessibility/magnifier/docked_magnifier_controller.h" #include "ash/app_list/app_list_controller_impl.h" #include "ash/constants/app_types.h" +#include "ash/constants/ash_features.h" #include "ash/display/screen_orientation_controller.h" #include "ash/display/screen_orientation_controller_test_api.h" +#include "ash/keyboard/ui/keyboard_ui_controller.h" +#include "ash/keyboard/ui/test/keyboard_test_util.h" #include "ash/public/cpp/fps_counter.h" #include "ash/public/cpp/presentation_time_recorder.h" #include "ash/public/cpp/shelf_config.h" @@ -31,6 +34,7 @@ #include "ash/system/status_area_widget_test_helper.h" #include "ash/test/ash_test_base.h" #include "ash/test/test_window_builder.h" +#include "ash/wallpaper/wallpaper_widget_controller.h" #include "ash/wm/desks/desks_util.h" #include "ash/wm/drag_window_resizer.h" #include "ash/wm/mru_window_tracker.h" @@ -39,6 +43,7 @@ #include "ash/wm/overview/overview_item.h" #include "ash/wm/overview/overview_observer.h" #include "ash/wm/overview/overview_test_util.h" +#include "ash/wm/splitview/split_view_constants.h" #include "ash/wm/splitview/split_view_divider.h" #include "ash/wm/splitview/split_view_drag_indicators.h" #include "ash/wm/splitview/split_view_metrics_controller.h" @@ -62,6 +67,7 @@ #include "ui/aura/test/test_window_delegate.h" #include "ui/aura/test/test_windows.h" #include "ui/base/hit_test.h" +#include "ui/base/ime/dummy_text_input_client.h" #include "ui/compositor/scoped_animation_duration_scale_mode.h" #include "ui/compositor/test/test_utils.h" #include "ui/compositor_extra/shadow.h" @@ -77,6 +83,8 @@ namespace { +constexpr int kCaretHeightForTest = 8; + // The observer to observe the overview states in |root_window_|. class OverviewStatesObserver : public OverviewObserver { public: @@ -126,6 +134,57 @@ ~TestBubbleDialogDelegateView() override {} }; +// Helper class to simulate the text input field in a window. When the text +// input field is focused, the attached window will also be focused and show the +// virtual keyboard. If the text input field is unfocused, it will hide the +// virtual keyboard. +class TestTextInputClient : public ui::DummyTextInputClient { + public: + explicit TestTextInputClient(aura::Window* window) + : ui::DummyTextInputClient(ui::TEXT_INPUT_TYPE_TEXT), window_(window) { + DCHECK(window_); + } + TestTextInputClient(const TestTextInputClient&) = delete; + TestTextInputClient& operator=(const TestTextInputClient&) = delete; + ~TestTextInputClient() override { + auto* ime = keyboard::KeyboardUIController::Get()->GetInputMethodForTest(); + ime->DetachTextInputClient(this); + } + + // ui::DummyTextInputClient: + gfx::Rect GetCaretBounds() const override { return caret_bounds_; } + + void set_caret_bounds(gfx::Rect caret_bounds) { + caret_bounds_ = caret_bounds; + } + + // When the text client is focused, the attached window will also be focused + // and the virtual keyboard is enabled. + void Focus() { + auto* ime = keyboard::KeyboardUIController::Get()->GetInputMethodForTest(); + ime->SetFocusedTextInputClient(this); + + if (window_) + window_->Focus(); + + ime->ShowVirtualKeyboardIfEnabled(); + ASSERT_TRUE(keyboard::WaitUntilShown()); + } + + // When the text client is unfocused, hide the virtual keyboard. + void UnFocus() { + auto* ime = keyboard::KeyboardUIController::Get()->GetInputMethodForTest(); + ime->DetachTextInputClient(this); + keyboard::KeyboardUIController::Get()->HideKeyboardExplicitlyBySystem(); + } + + private: + // The window to which the text client attaches to. + aura::Window* window_; + // The bounds of the caret. + gfx::Rect caret_bounds_; +}; + bool IsTabletMode() { return Shell::Get()->tablet_mode_controller()->InTabletMode(); } @@ -628,6 +687,34 @@ CheckOverviewEnterExitHistogram("ExitInSplitView", {1, 0}, {0, 1}); } +// Tests that in split view with a single overview window, when overview is +// ended, the wallpaper stays blurred until the window finishes animating. +TEST_F(SplitViewControllerTest, + WallpaperUnblurredAfterLoneOverviewWindowSnapAnimationCompleted) { + const gfx::Rect bounds(400, 400); + std::unique_ptr<aura::Window> window1(CreateWindow(bounds)); + std::unique_ptr<aura::Window> window2(CreateWindow(bounds)); + ToggleOverview(); + split_view_controller()->SnapWindow(window1.get(), SplitViewController::LEFT); + + WallpaperWidgetController* wallpaper_widget_controller = + Shell::GetPrimaryRootWindowController()->wallpaper_widget_controller(); + EXPECT_GT(wallpaper_widget_controller->GetWallpaperBlur(), 0); + EXPECT_FALSE(wallpaper_widget_controller->IsAnimating()); + + ui::ScopedAnimationDurationScaleMode animation_scale( + ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION); + ToggleOverview(); + EXPECT_GT(wallpaper_widget_controller->GetWallpaperBlur(), 0); + EXPECT_FALSE(wallpaper_widget_controller->IsAnimating()); + + WaitForOverviewExitAnimation(); + // The wallpaper is unblurred without animation, because the wallpaper is + // covered by the windows and the split view divider. + EXPECT_EQ(wallpaper_widget_controller->GetWallpaperBlur(), 0); + EXPECT_FALSE(wallpaper_widget_controller->IsAnimating()); +} + // Tests that if split view mode is active when entering overview, the overview // windows grid should show in the non-default side of the screen, and the // default snapped window should not be shown in the overview window grid. @@ -5414,4 +5501,287 @@ EXPECT_EQ(backdrop_window->bounds(), active_desk_container->bounds()); } +// The test class that enables the feature flag of portrait mode split view +// virtual keyboard improvement and the virtual keyboard. +class SplitViewKeyboardTest : public SplitViewControllerTest { + public: + SplitViewKeyboardTest() = default; + + SplitViewKeyboardTest(const SplitViewKeyboardTest&) = delete; + SplitViewKeyboardTest& operator=(const SplitViewKeyboardTest&) = delete; + + ~SplitViewKeyboardTest() override = default; + + // SplitViewControllerTest: + void SetUp() override { + SplitViewControllerTest::SetUp(); + scoped_feature_list_.InitAndEnableFeature(features::kAdjustSplitViewForVK); + SetVirtualKeyboardEnabled(true); + } + + keyboard::KeyboardUIController* keyboard_controller() { + return keyboard::KeyboardUIController::Get(); + } + + private: + base::test::ScopedFeatureList scoped_feature_list_; +}; + +// Tests that when the input field in the bottom window is blocked by the +// virtual keyboard (the bottom of the caret is less than +// `kMinCaretKeyboardDist` above the virtual keyboard), the bottom window will +// be pushed above the virtual keyboard. +TEST_F(SplitViewKeyboardTest, PushUpBottomWindow) { + UpdateDisplay("1200x800"); + + int64_t display_id = display::Screen::GetScreen()->GetPrimaryDisplay().id(); + display::DisplayManager* display_manager = Shell::Get()->display_manager(); + display::test::ScopedSetInternalDisplayId set_internal(display_manager, + display_id); + ScreenOrientationControllerTestApi test_api( + Shell::Get()->screen_orientation_controller()); + ASSERT_EQ(chromeos::OrientationType::kLandscapePrimary, + test_api.GetCurrentOrientation()); + + gfx::Rect bounds(0, 0, 400, 400); + std::unique_ptr<aura::Window> bottom_window(CreateWindow(bounds)); + auto bottom_client = + std::make_unique<TestTextInputClient>(bottom_window.get()); + split_view_controller()->SnapWindow(bottom_window.get(), + SplitViewController::RIGHT); + + test_api.SetDisplayRotation(display::Display::ROTATE_270, + display::Display::RotationSource::ACTIVE); + EXPECT_EQ(chromeos::OrientationType::kPortraitPrimary, + test_api.GetCurrentOrientation()); + EXPECT_FALSE(split_view_controller()->IsPhysicalLeftOrTop( + SplitViewController::RIGHT, bottom_window.get())); + + const gfx::Rect keyboard_bounds = + keyboard_controller()->GetKeyboardWindow()->GetBoundsInScreen(); + const gfx::Rect orig_bottom_bounds = bottom_window->GetBoundsInScreen(); + const gfx::Rect orig_divider_bounds = split_view_controller() + ->split_view_divider() + ->divider_widget() + ->GetWindowBoundsInScreen(); + + // Set the caret position in bottom window above the upper bounds of the + // virtual keyboard. When the virtual keyboard is enabled, the bottom window + // will not shift. + bottom_client->set_caret_bounds(gfx::Rect( + keyboard_bounds.top_center() + + gfx::Vector2d(0, -kMinCaretKeyboardDist - kCaretHeightForTest - 10), + gfx::Size(0, kCaretHeightForTest))); + bottom_client->Focus(); + EXPECT_TRUE(keyboard_controller()->IsKeyboardVisible()); + EXPECT_EQ(orig_bottom_bounds, bottom_window->GetBoundsInScreen()); + // The split view divider is adjustable and not moved. + EXPECT_EQ(orig_divider_bounds, split_view_controller() + ->split_view_divider() + ->divider_widget() + ->GetWindowBoundsInScreen()); + EXPECT_TRUE(split_view_controller()->split_view_divider()->IsAdjustable()); + + // Disable the keyboard. + bottom_client->UnFocus(); + EXPECT_FALSE(keyboard_controller()->IsKeyboardVisible()); + + const gfx::Rect shift_bottom_bounds( + keyboard_bounds.origin() + gfx::Vector2d(0, -orig_bottom_bounds.height()), + orig_bottom_bounds.size()); + const gfx::Rect shift_divider_bounds( + shift_bottom_bounds.origin() + + gfx::Vector2d(0, -orig_divider_bounds.height()), + orig_divider_bounds.size()); + // Set the caret position in bottom window below the upper bounds of the + // virtual keyboard. When the virtual keyboard is enabled, the bottom window + // will shift above the virtual keyboard. + bottom_client->set_caret_bounds( + gfx::Rect(keyboard_bounds.top_center() + gfx::Vector2d(0, 10), + gfx::Size(0, kCaretHeightForTest))); + bottom_client->Focus(); + EXPECT_TRUE(keyboard_controller()->IsKeyboardVisible()); + EXPECT_EQ(shift_bottom_bounds, bottom_window->GetBoundsInScreen()); + // The split view divider will also be shifted and become unadjustable. + EXPECT_EQ(shift_divider_bounds, split_view_controller() + ->split_view_divider() + ->divider_widget() + ->GetWindowBoundsInScreen()); + EXPECT_FALSE(split_view_controller()->split_view_divider()->IsAdjustable()); + + // Disable the keyboard. The bottom window will restore to original bounds. + // The split view divider will also be adjustable and restore to original + // bounds. + bottom_client->UnFocus(); + EXPECT_FALSE(keyboard_controller()->IsKeyboardVisible()); + EXPECT_EQ(orig_bottom_bounds, bottom_window->GetBoundsInScreen()); + EXPECT_EQ(orig_divider_bounds, split_view_controller() + ->split_view_divider() + ->divider_widget() + ->GetWindowBoundsInScreen()); + EXPECT_TRUE(split_view_controller()->split_view_divider()->IsAdjustable()); +} + +// When the bottom window is pushed up due to the virtual keyboard and the +// shifted window position cannot exceed `1 - kMinDividerPositionRatio` of the +// screen height. +TEST_F(SplitViewKeyboardTest, PushUpBottomWindowLimitHeight) { + UpdateDisplay("1200x800"); + + int64_t display_id = display::Screen::GetScreen()->GetPrimaryDisplay().id(); + display::DisplayManager* display_manager = Shell::Get()->display_manager(); + display::test::ScopedSetInternalDisplayId set_internal(display_manager, + display_id); + ScreenOrientationControllerTestApi test_api( + Shell::Get()->screen_orientation_controller()); + ASSERT_EQ(chromeos::OrientationType::kLandscapePrimary, + test_api.GetCurrentOrientation()); + + gfx::Rect bounds(0, 0, 200, 200); + std::unique_ptr<aura::Window> bottom_window(CreateWindow(bounds)); + auto bottom_client = + std::make_unique<TestTextInputClient>(bottom_window.get()); + split_view_controller()->SnapWindow(bottom_window.get(), + SplitViewController::RIGHT); + + test_api.SetDisplayRotation(display::Display::ROTATE_270, + display::Display::RotationSource::ACTIVE); + EXPECT_EQ(chromeos::OrientationType::kPortraitPrimary, + test_api.GetCurrentOrientation()); + EXPECT_FALSE(split_view_controller()->IsPhysicalLeftOrTop( + SplitViewController::RIGHT, bottom_window.get())); + + const gfx::Rect keyboard_bounds = + keyboard_controller()->GetKeyboardWindow()->GetBoundsInScreen(); + const gfx::Rect divider_bounds = + split_view_divider()->GetDividerBoundsInScreen(false /* is_dragging */); + const gfx::Rect screen_bounds = + screen_util::GetDisplayWorkAreaBoundsInParent(bottom_window.get()); + const int screen_height = screen_bounds.height(); + const int limit_y = screen_height * kMinDividerPositionRatio; + + // Resize divider to a position that when the bottom window is pushed up, its + // position will exceeds `1-kMinDividerPositionRatio` of screen height. + split_view_controller()->StartResize(divider_bounds.CenterPoint()); + split_view_controller()->Resize(gfx::Point(0, screen_height * 0.15f)); + + const gfx::Rect orig_bottom_bounds = bottom_window->GetBoundsInScreen(); + EXPECT_LT(keyboard_bounds.y() - orig_bottom_bounds.height(), limit_y); + + const gfx::Rect orig_divider_bounds = split_view_controller() + ->split_view_divider() + ->divider_widget() + ->GetWindowBoundsInScreen(); + + // Set the caret position in bottom window below the upper bounds of the + // virtual keyboard. When the virtual keyboard is enabled, the bottom window + // will shift above the virtual keyboard but the upper bounds will be limited + // to `kMinDividerPositionRatio` of the screen height. + const gfx::Rect shift_bottom_bounds(0, limit_y, keyboard_bounds.width(), + keyboard_bounds.y() - limit_y); + const gfx::Rect shift_divider_bounds( + shift_bottom_bounds.origin() + + gfx::Vector2d(0, -orig_divider_bounds.height()), + orig_divider_bounds.size()); + + bottom_client->set_caret_bounds(gfx::Rect(keyboard_bounds.top_center(), + gfx::Size(0, kCaretHeightForTest))); + bottom_client->Focus(); + EXPECT_TRUE(keyboard_controller()->IsKeyboardVisible()); + EXPECT_EQ(shift_bottom_bounds, bottom_window->GetBoundsInScreen()); + // The split view divider will also be shifted and become unadjustable. + EXPECT_EQ(shift_divider_bounds, split_view_controller() + ->split_view_divider() + ->divider_widget() + ->GetWindowBoundsInScreen()); + EXPECT_FALSE(split_view_controller()->split_view_divider()->IsAdjustable()); + + // Disable the keyboard. The bottom window will restore to original bounds. + // The split view divider will also be adjustable and restore to original + // bounds. + bottom_client->UnFocus(); + EXPECT_FALSE(keyboard_controller()->IsKeyboardVisible()); + EXPECT_EQ(orig_bottom_bounds, bottom_window->GetBoundsInScreen()); + EXPECT_EQ(orig_divider_bounds, split_view_controller() + ->split_view_divider() + ->divider_widget() + ->GetWindowBoundsInScreen()); + EXPECT_TRUE(split_view_controller()->split_view_divider()->IsAdjustable()); +} + +// Tests that when the bottom window is pushed up due to the virtual keyboard +// and the top window is activated, then the bottom window should restore to the +// original layout. +TEST_F(SplitViewKeyboardTest, RestoreByActivatingTopWindow) { + UpdateDisplay("1200x800"); + + int64_t display_id = display::Screen::GetScreen()->GetPrimaryDisplay().id(); + display::DisplayManager* display_manager = Shell::Get()->display_manager(); + display::test::ScopedSetInternalDisplayId set_internal(display_manager, + display_id); + ScreenOrientationControllerTestApi test_api( + Shell::Get()->screen_orientation_controller()); + ASSERT_EQ(chromeos::OrientationType::kLandscapePrimary, + test_api.GetCurrentOrientation()); + + gfx::Rect bounds(0, 0, 400, 400); + std::unique_ptr<aura::Window> top_window(CreateWindow(bounds)); + std::unique_ptr<aura::Window> bottom_window(CreateWindow(bounds)); + auto top_client = std::make_unique<TestTextInputClient>(top_window.get()); + auto bottom_client = + std::make_unique<TestTextInputClient>(bottom_window.get()); + split_view_controller()->SnapWindow(top_window.get(), + SplitViewController::LEFT); + split_view_controller()->SnapWindow(bottom_window.get(), + SplitViewController::RIGHT); + + test_api.SetDisplayRotation(display::Display::ROTATE_270, + display::Display::RotationSource::ACTIVE); + EXPECT_EQ(chromeos::OrientationType::kPortraitPrimary, + test_api.GetCurrentOrientation()); + EXPECT_TRUE(split_view_controller()->IsPhysicalLeftOrTop( + SplitViewController::LEFT, top_window.get())); + + const gfx::Rect keyboard_bounds = + keyboard_controller()->GetKeyboardWindow()->GetBoundsInScreen(); + const gfx::Rect orig_bottom_bounds = bottom_window->GetBoundsInScreen(); + const gfx::Rect shift_bottom_bounds( + keyboard_bounds.origin() + gfx::Vector2d(0, -orig_bottom_bounds.height()), + orig_bottom_bounds.size()); + const gfx::Rect orig_divider_bounds = split_view_controller() + ->split_view_divider() + ->divider_widget() + ->GetWindowBoundsInScreen(); + const gfx::Rect shift_divider_bounds( + shift_bottom_bounds.origin() + + gfx::Vector2d(0, -orig_divider_bounds.height()), + orig_divider_bounds.size()); + + // Set the caret position in bottom window below the upper bounds of the + // virtual keyboard. When the virtual keyboard is enabled, the bottom window + // will shift. + bottom_client->set_caret_bounds( + gfx::Rect(keyboard_bounds.top_center() + gfx::Vector2d(0, 10), + gfx::Size(0, kCaretHeightForTest))); + bottom_client->Focus(); + EXPECT_TRUE(keyboard_controller()->IsKeyboardVisible()); + EXPECT_EQ(shift_bottom_bounds, bottom_window->GetBoundsInScreen()); + // The split view divider will also be shifted and become unadjustable. + EXPECT_EQ(shift_divider_bounds, split_view_controller() + ->split_view_divider() + ->divider_widget() + ->GetWindowBoundsInScreen()); + EXPECT_FALSE(split_view_controller()->split_view_divider()->IsAdjustable()); + + // Activate the top window. The bottom window will restore to original bounds. + top_client->Focus(); + EXPECT_TRUE(keyboard_controller()->IsKeyboardVisible()); + EXPECT_EQ(orig_bottom_bounds, bottom_window->GetBoundsInScreen()); + EXPECT_EQ(orig_divider_bounds, split_view_controller() + ->split_view_divider() + ->divider_widget() + ->GetWindowBoundsInScreen()); + EXPECT_TRUE(split_view_controller()->split_view_divider()->IsAdjustable()); +} + } // namespace ash
diff --git a/ash/wm/splitview/split_view_drag_indicators.cc b/ash/wm/splitview/split_view_drag_indicators.cc index 264bd04..8461154 100644 --- a/ash/wm/splitview/split_view_drag_indicators.cc +++ b/ash/wm/splitview/split_view_drag_indicators.cc
@@ -5,6 +5,7 @@ #include "ash/wm/splitview/split_view_drag_indicators.h" #include <utility> +#include <vector> #include "ash/display/screen_orientation_controller.h" #include "ash/public/cpp/shell_window_ids.h" @@ -583,11 +584,11 @@ DoSplitviewTransformAnimation( preview_label_layer, SPLITVIEW_ANIMATION_PREVIEW_AREA_TEXT_SLIDE_OUT, - preview_label_transform, /*animation_observer=*/nullptr); + preview_label_transform, /*animation_observers=*/{}); DoSplitviewTransformAnimation( other_highlight_label_layer, SPLITVIEW_ANIMATION_OTHER_HIGHLIGHT_TEXT_SLIDE_OUT, - other_highlight_label_transform, /*animation_observer=*/nullptr); + other_highlight_label_transform, /*animation_observers=*/{}); } else { // Put the labels where they belong. preview_label_layer->SetTransform(preview_label_transform); @@ -606,11 +607,11 @@ // Animate the labels sliding in. DoSplitviewTransformAnimation( preview_label_layer, SPLITVIEW_ANIMATION_PREVIEW_AREA_TEXT_SLIDE_IN, - gfx::Transform(), /*animation_observer=*/nullptr); + gfx::Transform(), /*animation_observers=*/{}); DoSplitviewTransformAnimation( other_highlight_label_layer, SPLITVIEW_ANIMATION_OTHER_HIGHLIGHT_TEXT_SLIDE_IN, gfx::Transform(), - /*animation_observer=*/nullptr); + /*animation_observers=*/{}); } else { // Put the labels where they belong. preview_label_layer->SetTransform(gfx::Transform());
diff --git a/ash/wm/splitview/split_view_utils.cc b/ash/wm/splitview/split_view_utils.cc index 2933315..7ebefa0c7 100644 --- a/ash/wm/splitview/split_view_utils.cc +++ b/ash/wm/splitview/split_view_utils.cc
@@ -245,7 +245,7 @@ ui::Layer* layer, SplitviewAnimationType type, const gfx::Transform& target_transform, - std::unique_ptr<ui::ImplicitAnimationObserver> animation_observer) { + const std::vector<ui::ImplicitAnimationObserver*>& animation_observers) { if (layer->GetTargetTransform() == target_transform) return; @@ -271,8 +271,8 @@ ui::LayerAnimator* animator = layer->GetAnimator(); ui::ScopedLayerAnimationSettings settings(animator); - if (animation_observer.get()) - settings.AddObserver(animation_observer.release()); + for (ui::ImplicitAnimationObserver* animation_observer : animation_observers) + settings.AddObserver(animation_observer); ApplyAnimationSettings(&settings, animator, ui::LayerAnimationElement::TRANSFORM, duration, tween, preemption_strategy, delay);
diff --git a/ash/wm/splitview/split_view_utils.h b/ash/wm/splitview/split_view_utils.h index 80b5a6c..15b1754 100644 --- a/ash/wm/splitview/split_view_utils.h +++ b/ash/wm/splitview/split_view_utils.h
@@ -5,6 +5,8 @@ #ifndef ASH_WM_SPLITVIEW_SPLIT_VIEW_UTILS_H_ #define ASH_WM_SPLITVIEW_SPLIT_VIEW_UTILS_H_ +#include <vector> + #include "ash/ash_export.h" #include "ash/wm/splitview/split_view_controller.h" #include "third_party/abseil-cpp/absl/types/optional.h" @@ -113,7 +115,7 @@ ui::Layer* layer, SplitviewAnimationType type, const gfx::Transform& target_transform, - std::unique_ptr<ui::ImplicitAnimationObserver> animation_observer); + const std::vector<ui::ImplicitAnimationObserver*>& animation_observers); // Animates |layer|'s clip rect based on |type|. void DoSplitviewClipRectAnimation(
diff --git a/ash/wm/workspace/workspace_window_resizer.cc b/ash/wm/workspace/workspace_window_resizer.cc index 5ef51e7e..e96a2eb 100644 --- a/ash/wm/workspace/workspace_window_resizer.cc +++ b/ash/wm/workspace/workspace_window_resizer.cc
@@ -1043,7 +1043,6 @@ // TODO: figure out how to deal with window going off the edge. // Calculate sizes so that we can maintain the ratios if we need to resize. - int total_available = 0; for (size_t i = 0; i < attached_windows_.size(); ++i) { gfx::Size min(attached_windows_[i]->delegate() ? attached_windows_[i]->delegate()->GetMinimumSize() @@ -1056,7 +1055,6 @@ std::max(PrimaryAxisSize(min), kMinOnscreenSize)); total_min_ += min_size; total_initial_size_ += initial_size; - total_available += std::max(min_size, initial_size) - min_size; } instance = this;
diff --git a/base/android/library_loader/library_prefetcher.cc b/base/android/library_loader/library_prefetcher.cc index 2a64694..88dd068a 100644 --- a/base/android/library_loader/library_prefetcher.cc +++ b/base/android/library_loader/library_prefetcher.cc
@@ -183,6 +183,7 @@ // loop. dummy ^= *static_cast<volatile unsigned char*>(ptr); } + ALLOW_UNUSED_LOCAL(dummy); } // These values were used in the past for recording
diff --git a/base/command_line.h b/base/command_line.h index 706726a..ad028128 100644 --- a/base/command_line.h +++ b/base/command_line.h
@@ -19,6 +19,7 @@ #include <stddef.h> #include <functional> #include <map> +#include <memory> #include <string> #include <vector>
diff --git a/base/task/sequence_manager/task_queue_impl.cc b/base/task/sequence_manager/task_queue_impl.cc index f1c4ff5..31039cc 100644 --- a/base/task/sequence_manager/task_queue_impl.cc +++ b/base/task/sequence_manager/task_queue_impl.cc
@@ -957,12 +957,9 @@ // immediate tasks inside UpdateDelayedWakeUp(). UpdateDelayedWakeUp(&lazy_now); - bool has_pending_immediate_work = false; - { base::internal::CheckedAutoLock lock(any_thread_lock_); UpdateCrossThreadQueueStateLocked(); - has_pending_immediate_work = HasTaskToRunImmediatelyLocked(); // Copy over the task-reporting related state. any_thread_.tracing_only.is_enabled = enabled;
diff --git a/base/timer/timer.cc b/base/timer/timer.cc index 20f95b10..c770a47 100644 --- a/base/timer/timer.cc +++ b/base/timer/timer.cc
@@ -12,11 +12,9 @@ #include "base/feature_list.h" #include "base/memory/ptr_util.h" #include "base/memory/ref_counted.h" -#include "base/metrics/histogram_macros.h" #include "base/threading/platform_thread.h" #include "base/threading/sequenced_task_runner_handle.h" #include "base/time/tick_clock.h" -#include "build/build_config.h" namespace base { namespace internal { @@ -30,25 +28,6 @@ constexpr Feature kAlwaysAbandonScheduledTask{"AlwaysAbandonScheduledTask", FEATURE_DISABLED_BY_DEFAULT}; -// The reason for which the timer's scheduled task was invoked. -enum ScheduledTaskInvokedReason { - kStopped, // The timer fired for a stopped timer so nothing was done. - kRescheduled, // The timer fired before the desired run time so the user task - // was rescheduled for later. This can happens when the timer - // is restarted while it is already running. - kReady, // The timer fired at the desired run time so the task is ready - // to be invoked. - kMaxValue -}; - -void RecordScheduledTaskInvokedReason(ScheduledTaskInvokedReason reason) { - // Recording this histogram breaks a fuchsia test. -#if !defined(OS_FUCHSIA) - UMA_HISTOGRAM_ENUMERATION("Scheduler.TimerBase.ScheduledTaskInvokedReason", - reason); -#endif -} - } // namespace // TaskDestructionDetector's role is to detect when the scheduled task is @@ -234,7 +213,6 @@ // The timer may have been stopped. if (!is_running_) { DCHECK(!FeatureList::IsEnabled(kAlwaysAbandonScheduledTask)); - RecordScheduledTaskInvokedReason(ScheduledTaskInvokedReason::kStopped); return; } @@ -247,15 +225,12 @@ // task if the |desired_run_time_| is in the future. if (desired_run_time_ > now) { DCHECK(!FeatureList::IsEnabled(kAlwaysAbandonScheduledTask)); - RecordScheduledTaskInvokedReason( - ScheduledTaskInvokedReason::kRescheduled); // Post a new task to span the remaining time. ScheduleNewTask(desired_run_time_ - now); return; } } - RecordScheduledTaskInvokedReason(ScheduledTaskInvokedReason::kReady); RunUserTask(); // No more member accesses here: |this| could be deleted at this point. }
diff --git a/build/android/pylib/local/device/local_device_instrumentation_test_run.py b/build/android/pylib/local/device/local_device_instrumentation_test_run.py index 8638ce942..f40a502 100644 --- a/build/android/pylib/local/device/local_device_instrumentation_test_run.py +++ b/build/android/pylib/local/device/local_device_instrumentation_test_run.py
@@ -104,6 +104,7 @@ FEATURE_ANNOTATION = 'Feature' RENDER_TEST_FEATURE_ANNOTATION = 'RenderTest' WPR_ARCHIVE_FILE_PATH_ANNOTATION = 'WPRArchiveDirectory' +WPR_ARCHIVE_NAME_ANNOTATION = 'WPRArchiveDirectory$ArchiveName' WPR_RECORD_REPLAY_TEST_FEATURE_ANNOTATION = 'WPRRecordReplayTest' _DEVICE_GOLD_DIR = 'skia_gold' @@ -663,10 +664,12 @@ wpr_archive_path, os.path.exists(wpr_archive_path))) + file_name = _GetWPRArchiveFileName( + test) or self._GetUniqueTestName(test) + '.wprgo' + # Some linux version does not like # in the name. Replaces it with __. - archive_path = os.path.join( - wpr_archive_path, - _ReplaceUncommonChars(self._GetUniqueTestName(test)) + '.wprgo') + archive_path = os.path.join(wpr_archive_path, + _ReplaceUncommonChars(file_name)) if not os.path.exists(_WPR_GO_LINUX_X86_64_PATH): # If we got to this stage, then we should have @@ -1372,6 +1375,13 @@ {}).get('value', ()) +def _GetWPRArchiveFileName(test): + """Retrieves the WPRArchiveDirectory.ArchiveName annotation.""" + value = test['annotations'].get(WPR_ARCHIVE_NAME_ANNOTATION, + {}).get('value', None) + return value[0] if value else None + + def _ReplaceUncommonChars(original): """Replaces uncommon characters with __.""" if not original:
diff --git a/build/config/android/rules.gni b/build/config/android/rules.gni index 02e814c9..d858e6b 100644 --- a/build/config/android/rules.gni +++ b/build/config/android/rules.gni
@@ -2604,6 +2604,8 @@ resources_config_paths += invoker.resources_config_paths } } + } else { + not_needed(invoker, [ "resources_config_paths" ]) } if (!_is_bundle_module) {
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1 index 3ec6479d..8ece1b2 100644 --- a/build/fuchsia/linux.sdk.sha1 +++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@ -6.20211012.0.1 +6.20211012.1.1
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1 index 3ec6479d..1290fe0 100644 --- a/build/fuchsia/mac.sdk.sha1 +++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@ -6.20211012.0.1 +6.20211012.2.1
diff --git a/build/rust/rust_source_set.gni b/build/rust/rust_source_set.gni index 5887a62..146eb7e 100644 --- a/build/rust/rust_source_set.gni +++ b/build/rust/rust_source_set.gni
@@ -149,7 +149,7 @@ "rustflags not supported by rust_source_set") _deps_for_rust_targets = [] if (defined(invoker.mutually_dependent_target)) { - _deps_for_rust_targets += [ invoker.mutually_depependent_peer ] + _deps_for_rust_targets += [ invoker.mutually_dependent_target ] } _deps = [] if (defined(invoker.deps)) { @@ -191,7 +191,7 @@ # binary by the C++ linker. ] if (defined(invoker.mutually_dependent_target)) { - visibility = invoker.mutually_dependent_target + visibility = [ invoker.mutually_dependent_target ] } }
diff --git a/build/rust/std/remap_alloc.cc b/build/rust/std/remap_alloc.cc index 799cf8b0..ab85638 100644 --- a/build/rust/std/remap_alloc.cc +++ b/build/rust/std/remap_alloc.cc
@@ -43,6 +43,11 @@ // redirect these symbols to that crate instead. The advantage of the latter // is that it would work equally well for those cases where rustc is doing // the final linking. +// +// They're weak symbols, because this file will sometimes end up in targets +// which are linked by rustc, and thus we would otherwise get duplicate +// definitions. The following definitions will therefore only end up being +// used in targets which are linked by our C++ toolchain. extern "C" { @@ -51,23 +56,24 @@ void* __rdl_realloc(void*, size_t, size_t, size_t); void* __rdl_alloc_zeroed(size_t, size_t); -void* __rust_alloc(size_t a, size_t b) { +void* __attribute__((weak)) __rust_alloc(size_t a, size_t b) { return __rdl_alloc(a, b); } -void __rust_dealloc(void* a) { +void __attribute__((weak)) __rust_dealloc(void* a) { __rdl_dealloc(a); } -void* __rust_realloc(void* a, size_t b, size_t c, size_t d) { +void* __attribute__((weak)) +__rust_realloc(void* a, size_t b, size_t c, size_t d) { return __rdl_realloc(a, b, c, d); } -void* __rust_alloc_zeroed(size_t a, size_t b) { +void* __attribute__((weak)) __rust_alloc_zeroed(size_t a, size_t b) { return __rdl_alloc_zeroed(a, b); } -void __rust_alloc_error_handler(size_t a, size_t b) { +void __attribute__((weak)) __rust_alloc_error_handler(size_t a, size_t b) { IMMEDIATE_CRASH(); }
diff --git a/build/rust/tests/BUILD.gn b/build/rust/tests/BUILD.gn index 4ccd89b2a..f111229 100644 --- a/build/rust/tests/BUILD.gn +++ b/build/rust/tests/BUILD.gn
@@ -11,12 +11,15 @@ if (toolchain_has_rust) { deps = [ "test_cpp_including_rust", + "test_mixed_source_set", "test_rust_source_set", ] if (build_rust_unit_tests) { deps += [ "test_cpp_including_rust:test_cpp_including_rust_unittests", + "test_mixed_source_set:test_mixed_source_set_rs_unittests", "test_rust_source_set:test_rust_source_set_unittests", + "test_rust_unittests", ] } if (rustc_can_link) {
diff --git a/build/rust/tests/test_cpp_including_rust/BUILD.gn b/build/rust/tests/test_cpp_including_rust/BUILD.gn index afe5ff4..43e8ef1 100644 --- a/build/rust/tests/test_cpp_including_rust/BUILD.gn +++ b/build/rust/tests/test_cpp_including_rust/BUILD.gn
@@ -8,6 +8,7 @@ executable("test_cpp_including_rust") { sources = [ "main.cc" ] deps = [ + "//build/rust/tests/test_mixed_source_set", "//build/rust/tests/test_rust_source_set:test_rust_source_set_cpp_bindings", ] } @@ -18,6 +19,7 @@ "//base", "//base/allocator:buildflags", "//base/test:run_all_unittests", + "//build/rust/tests/test_mixed_source_set", "//build/rust/tests/test_rust_source_set:test_rust_source_set_cpp_bindings", "//testing/gmock", "//testing/gtest",
diff --git a/build/rust/tests/test_cpp_including_rust/main.cc b/build/rust/tests/test_cpp_including_rust/main.cc index c1de55a..2718a8e 100644 --- a/build/rust/tests/test_cpp_including_rust/main.cc +++ b/build/rust/tests/test_cpp_including_rust/main.cc
@@ -2,10 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "build/rust/tests/test_mixed_source_set/test_mixed_source_set.h" + // Defined in Rust. extern "C" void say_hello_from_cpp(); int main(int argc, char* argv[]) { say_hello_from_cpp(); + say_hello_via_callbacks(); return 0; }
diff --git a/build/rust/tests/test_cpp_including_rust/unittests.cc b/build/rust/tests/test_cpp_including_rust/unittests.cc index a9bca8d..b100e536 100644 --- a/build/rust/tests/test_cpp_including_rust/unittests.cc +++ b/build/rust/tests/test_cpp_including_rust/unittests.cc
@@ -28,3 +28,8 @@ base::IsManagedByPartitionAlloc(cpp_allocated_int.get())); deallocate_via_rust(rust_allocated_ptr); } + +extern "C" int32_t add_two_ints_via_rust_then_cpp(int32_t x, int32_t y); +TEST(RustTest, CppCallingIntoRustAndBack_BasicFFI) { + EXPECT_EQ(10, add_two_ints_via_rust_then_cpp(6, 4)); +}
diff --git a/build/rust/tests/test_mixed_source_set/BUILD.gn b/build/rust/tests/test_mixed_source_set/BUILD.gn new file mode 100644 index 0000000..45840940 --- /dev/null +++ b/build/rust/tests/test_mixed_source_set/BUILD.gn
@@ -0,0 +1,18 @@ +# Copyright 2021 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/rust/rust_source_set.gni") + +rust_source_set("test_mixed_source_set_rs") { + sources = [ "src/lib.rs" ] + mutually_dependent_target = ":test_mixed_source_set" +} + +source_set("test_mixed_source_set") { + sources = [ + "test_mixed_source_set.cc", + "test_mixed_source_set.h", + ] + deps = [ ":test_mixed_source_set_rs_cpp_bindings" ] +}
diff --git a/build/rust/tests/test_mixed_source_set/src/lib.rs b/build/rust/tests/test_mixed_source_set/src/lib.rs new file mode 100644 index 0000000..a06e141 --- /dev/null +++ b/build/rust/tests/test_mixed_source_set/src/lib.rs
@@ -0,0 +1,33 @@ +// Copyright 2021 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. + +extern "C" { + fn cpp_callback(); + fn cpp_addition(a: u32, b: u32) -> u32; +} + +#[no_mangle] +pub extern "C" fn rust_code() { + say_hello_from_a_cpp_callback_from_rust() +} + +pub fn say_hello_from_a_cpp_callback_from_rust() { + unsafe { cpp_callback() }; // we'll have cxx to remove the need + // for unsafe in future for these simple cases +} + +#[no_mangle] +pub extern "C" fn add_two_ints_via_rust_then_cpp(a: u32, b: u32) -> u32 { + add_two_ints_using_cpp(a, b) +} + +pub fn add_two_ints_using_cpp(a: u32, b: u32) -> u32 { + unsafe { cpp_addition(a, b) } +} + +#[test] +fn test_callback_to_cpp() { + say_hello_from_a_cpp_callback_from_rust(); + assert_eq!(add_two_ints_via_rust_then_cpp(4u32, 4u32), 8u32); +}
diff --git a/build/rust/tests/test_mixed_source_set/test_mixed_source_set.cc b/build/rust/tests/test_mixed_source_set/test_mixed_source_set.cc new file mode 100644 index 0000000..6e2a5f5 --- /dev/null +++ b/build/rust/tests/test_mixed_source_set/test_mixed_source_set.cc
@@ -0,0 +1,21 @@ +// Copyright 2021 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 "test_mixed_source_set.h" +#include <stdint.h> +#include <iostream> + +extern "C" void rust_code(); + +void say_hello_via_callbacks() { + rust_code(); +} + +extern "C" void cpp_callback() { + std::cout << "Hello from C++ callback from Rust" << std::endl; +} + +extern "C" uint32_t cpp_addition(uint32_t a, uint32_t b) { + return a + b; +}
diff --git a/build/rust/tests/test_mixed_source_set/test_mixed_source_set.h b/build/rust/tests/test_mixed_source_set/test_mixed_source_set.h new file mode 100644 index 0000000..189e564 --- /dev/null +++ b/build/rust/tests/test_mixed_source_set/test_mixed_source_set.h
@@ -0,0 +1,10 @@ +// Copyright 2021 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 BUILD_RUST_TESTS_TEST_MIXED_SOURCE_SET_TEST_MIXED_SOURCE_SET_H_ +#define BUILD_RUST_TESTS_TEST_MIXED_SOURCE_SET_TEST_MIXED_SOURCE_SET_H_ + +void say_hello_via_callbacks(); + +#endif // BUILD_RUST_TESTS_TEST_MIXED_SOURCE_SET_TEST_MIXED_SOURCE_SET_H_
diff --git a/build/rust/tests/test_rust_exe/BUILD.gn b/build/rust/tests/test_rust_exe/BUILD.gn index 0ce2e4a..28d81fa 100644 --- a/build/rust/tests/test_rust_exe/BUILD.gn +++ b/build/rust/tests/test_rust_exe/BUILD.gn
@@ -4,7 +4,10 @@ executable("test_rust_exe") { crate_root = "main.rs" - deps = [ "//build/rust/tests/test_rust_source_set" ] + deps = [ + "//build/rust/tests/test_mixed_source_set:test_mixed_source_set_rs", + "//build/rust/tests/test_rust_source_set", + ] rustflags = [ "--edition", "2018",
diff --git a/build/rust/tests/test_rust_exe/main.rs b/build/rust/tests/test_rust_exe/main.rs index c107205..8514d832 100644 --- a/build/rust/tests/test_rust_exe/main.rs +++ b/build/rust/tests/test_rust_exe/main.rs
@@ -2,8 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +use test_mixed_source_set_rs::say_hello_from_a_cpp_callback_from_rust; use test_rust_source_set::say_hello; fn main() { say_hello(); + say_hello_from_a_cpp_callback_from_rust(); }
diff --git a/build/rust/tests/test_rust_unittests/BUILD.gn b/build/rust/tests/test_rust_unittests/BUILD.gn new file mode 100644 index 0000000..fa6e7e5 --- /dev/null +++ b/build/rust/tests/test_rust_unittests/BUILD.gn
@@ -0,0 +1,15 @@ +# Copyright 2021 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. + +executable("test_rust_unittests") { + crate_root = "main.rs" + deps = [ "//build/rust/tests/test_mixed_source_set:test_mixed_source_set_rs" ] + rustflags = [ + "--edition", + "2018", + "--cfg", + "test", + "--test", + ] +}
diff --git a/build/rust/tests/test_rust_unittests/main.rs b/build/rust/tests/test_rust_unittests/main.rs new file mode 100644 index 0000000..f004fbd --- /dev/null +++ b/build/rust/tests/test_rust_unittests/main.rs
@@ -0,0 +1,10 @@ +// Copyright 2021 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. + +use test_mixed_source_set_rs::add_two_ints_using_cpp; + +#[test] +fn test_call_into_mixed_source_set() { + assert_eq!(add_two_ints_using_cpp(5, 7), 12) +}
diff --git a/chrome/android/chrome_public_apk_tmpl.gni b/chrome/android/chrome_public_apk_tmpl.gni index 5ed1e35..8f483b1 100644 --- a/chrome/android/chrome_public_apk_tmpl.gni +++ b/chrome/android/chrome_public_apk_tmpl.gni
@@ -185,7 +185,7 @@ strip_resource_names = !is_java_debug # Shortens resource file names in apk eg: res/drawable/button.xml -> res/a.xml - short_resource_paths = true + short_resource_paths = !is_java_debug # Removes unused resources from the apk. Only enabled on official builds # since it adds a slow step and serializes the build graph causing fewer
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSurfaceMediator.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSurfaceMediator.java index e5a7180d..801f8206 100644 --- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSurfaceMediator.java +++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSurfaceMediator.java
@@ -169,8 +169,9 @@ headerList.get(index).set(SectionHeaderProperties.OPTIONS_INDICATOR_VISIBILITY_KEY, ViewVisibility.VISIBLE); } - - bindStream(newStream); + if (!mSettingUpStreams) { + bindStream(newStream); + } } @Override @@ -299,6 +300,9 @@ private final HashMap<Integer, Stream> mTabToStreamMap = new HashMap<>(); private Stream mCurrentStream; + // Whether we're currently adding the streams. If this is true, streams should not be bound yet. + // This avoids automatically binding the first stream when it's added. + private boolean mSettingUpStreams; /** * @param coordinator The {@link FeedSurfaceCoordinator} that interacts with this class. @@ -459,6 +463,8 @@ */ private void initializePropertiesForStream() { if (mHasHeader) { + assert !mSettingUpStreams; + mSettingUpStreams = true; mSectionHeaderModel.set(SectionHeaderListProperties.ON_TAB_SELECTED_CALLBACK_KEY, new FeedSurfaceHeaderSelectedCallback()); @@ -488,6 +494,7 @@ if (mTabToStreamMap.size() <= mRestoreTabId) mRestoreTabId = 0; mSectionHeaderModel.set( SectionHeaderListProperties.CURRENT_TAB_INDEX_KEY, mRestoreTabId); + mSettingUpStreams = false; } else { // Show feed if there is no header that would allow user to hide feed. // This is currently only relevant for the two panes start surface. @@ -499,8 +506,7 @@ mSectionHeaderModel.set(SectionHeaderListProperties.CURRENT_TAB_INDEX_KEY, 0); } - if (mCoordinator.isActive() - && mSectionHeaderModel.get(SectionHeaderListProperties.IS_SECTION_ENABLED_KEY)) { + if (mSectionHeaderModel.get(SectionHeaderListProperties.IS_SECTION_ENABLED_KEY)) { bindStream(mTabToStreamMap.get( mSectionHeaderModel.get(SectionHeaderListProperties.CURRENT_TAB_INDEX_KEY))); } else { @@ -600,6 +606,11 @@ if (mCurrentStream != null) { unbindStream(/* shouldPlaceSpacer = */ true); } + // Don't bind before the coordinator is active, or when the feed should not show. + if (!mCoordinator.isActive() + || !mSectionHeaderModel.get(SectionHeaderListProperties.IS_SECTION_ENABLED_KEY)) { + return; + } mCurrentStream = stream; mCurrentStream.addOnContentChangedListener(mStreamContentChangedListener); @@ -669,8 +680,6 @@ private void rebindStream() { // If a stream is already bound, then do nothing. if (mCurrentStream != null) return; - // If feed shouldn't be shown, do nothing. - if (!mSectionHeaderModel.get(SectionHeaderListProperties.IS_SECTION_ENABLED_KEY)) return; // Find the stream that should be bound and bind it. If no stream matches, then we haven't // fully set up yet. This will be taken care of by setup. Stream stream = mTabToStreamMap.get(
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedRootUiCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedRootUiCoordinator.java index da43239..1cfb672 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedRootUiCoordinator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedRootUiCoordinator.java
@@ -117,6 +117,7 @@ import org.chromium.components.browser_ui.widget.TouchEventObserver; import org.chromium.components.browser_ui.widget.scrim.ScrimCoordinator; import org.chromium.components.messages.MessageDispatcherProvider; +import org.chromium.content_public.browser.WebContents; import org.chromium.ui.base.ActivityWindowAndroid; import org.chromium.ui.base.DeviceFormFactor; import org.chromium.ui.base.IntentRequestTracker; @@ -632,9 +633,19 @@ ChromeFeatureList.DARKEN_WEBSITES_CHECKBOX_IN_THEMES_SETTING)) { // TODO(crbug.com/1252965): Investigate locking feature engagement system during // "second run promos" to avoid !didTriggerPromo check. - WebContentsDarkModeMessageController.attemptToSendMessage(mActivity, - Profile.fromWebContents(mActivityTabProvider.get().getWebContents()), - new SettingsLauncherImpl(), mMessageDispatcher); + Tab tab; + WebContents webContents; + + Profile profile; + if ((tab = mActivityTabProvider.get()) != null + && (webContents = tab.getWebContents()) != null) { + profile = Profile.fromWebContents(webContents); + } else { + profile = Profile.getLastUsedRegularProfile(); + } + + WebContentsDarkModeMessageController.attemptToSendMessage( + mActivity, profile, new SettingsLauncherImpl(), mMessageDispatcher); } if (FeedFeatures.isWebFeedUIEnabled()) {
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/feed/FeedSurfaceMediatorTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/feed/FeedSurfaceMediatorTest.java index 12c02385..0121ec9 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/feed/FeedSurfaceMediatorTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/feed/FeedSurfaceMediatorTest.java
@@ -7,7 +7,6 @@ import static junit.framework.Assert.assertEquals; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.anyLong; import static org.mockito.Mockito.eq; @@ -32,6 +31,7 @@ import org.mockito.junit.MockitoRule; import org.robolectric.Robolectric; import org.robolectric.annotation.Config; +import org.robolectric.shadows.ShadowLog; import org.chromium.base.supplier.ObservableSupplierImpl; import org.chromium.base.test.BaseRobolectricTestRunner; @@ -101,7 +101,9 @@ @Mock private TemplateUrlService mUrlService; @Mock - private FeedStream mStream; + private FeedStream mForYouStream; + @Mock + private FeedStream mFollowingStream; @Mock private FeedLaunchReliabilityLogger mLaunchReliabilityLogger; @Mock @@ -116,6 +118,9 @@ @Before public void setUp() { + // Print logs to stdout. + ShadowLog.stream = System.out; + mActivity = Robolectric.buildActivity(Activity.class).get(); mocker.mock(FeedServiceBridgeJni.TEST_HOOKS, mFeedServiceBridgeJniMock); mocker.mock(WebFeedBridge.getTestHooksForTesting(), mWebFeedBridgeJniMock); @@ -125,9 +130,11 @@ when(mIdentityService.getSigninManager(any(Profile.class))).thenReturn(mSigninManager); when(mSigninManager.getIdentityManager()).thenReturn(mIdentityManager); when(mIdentityManager.hasPrimaryAccount(anyInt())).thenReturn(true); + when(mFeedSurfaceCoordinator.isActive()).thenReturn(true); when(mFeedSurfaceCoordinator.getRecyclerView()).thenReturn(new RecyclerView(mActivity)); - when(mFeedSurfaceCoordinator.getStream()).thenReturn(mStream); - when(mFeedSurfaceCoordinator.createFeedStream(anyBoolean())).thenReturn(mStream); + when(mFeedSurfaceCoordinator.getStream()).thenReturn(mForYouStream); + when(mFeedSurfaceCoordinator.createFeedStream(eq(false))).thenReturn(mFollowingStream); + when(mFeedSurfaceCoordinator.createFeedStream(eq(true))).thenReturn(mForYouStream); when(mFeedSurfaceCoordinator.getLaunchReliabilityLogger()) .thenReturn(mLaunchReliabilityLogger); when(mFeedSurfaceCoordinator.getHybridListRenderer()).thenReturn(mHybridListRenderer); @@ -135,7 +142,8 @@ .thenReturn(mFeedSurfaceLifecycleManager); ObservableSupplierImpl<Boolean> hasUnreadContent = new ObservableSupplierImpl<>(); hasUnreadContent.set(false); - when(mStream.hasUnreadContent()).thenReturn(hasUnreadContent); + when(mForYouStream.hasUnreadContent()).thenReturn(hasUnreadContent); + when(mFollowingStream.hasUnreadContent()).thenReturn(hasUnreadContent); FeedSurfaceMediator.setPrefForTest(mPrefChangeRegistrar, mPrefService); FeedFeatures.setFakePrefsForTest(mPrefService); @@ -198,30 +206,37 @@ @Test public void updateContent_openingTabIdFollowing() { + when(mPrefService.getBoolean(Pref.ARTICLES_LIST_VISIBLE)).thenReturn(true); PropertyModel sectionHeaderModel = SectionHeaderListProperties.create(); mFeedSurfaceMediator = createMediator(FeedSurfaceCoordinator.StreamTabId.FOLLOWING, sectionHeaderModel); mFeedSurfaceMediator.updateContent(); + verify(mForYouStream, never()).bind(any(), any(), any(), any(), any(), any(), anyInt()); + verify(mFollowingStream, times(1)).bind(any(), any(), any(), any(), any(), any(), anyInt()); assertEquals(FeedSurfaceCoordinator.StreamTabId.FOLLOWING, sectionHeaderModel.get(SectionHeaderListProperties.CURRENT_TAB_INDEX_KEY)); } @Test public void updateContent_openingTabIdForYou() { + when(mPrefService.getBoolean(Pref.ARTICLES_LIST_VISIBLE)).thenReturn(true); PropertyModel sectionHeaderModel = SectionHeaderListProperties.create(); mFeedSurfaceMediator = createMediator(FeedSurfaceCoordinator.StreamTabId.FOR_YOU, sectionHeaderModel); mFeedSurfaceMediator.updateContent(); + verify(mForYouStream, times(1)).bind(any(), any(), any(), any(), any(), any(), anyInt()); + verify(mFollowingStream, never()).bind(any(), any(), any(), any(), any(), any(), anyInt()); assertEquals(FeedSurfaceCoordinator.StreamTabId.FOR_YOU, sectionHeaderModel.get(SectionHeaderListProperties.CURRENT_TAB_INDEX_KEY)); } @Test public void testOnSurfaceClosed_launchInProgress() { + when(mPrefService.getBoolean(Pref.ARTICLES_LIST_VISIBLE)).thenReturn(true); mFeedSurfaceMediator = createMediator(); - mFeedSurfaceMediator.bindStream(mStream); + mFeedSurfaceMediator.updateContent(); when(mLaunchReliabilityLogger.isLaunchInProgress()).thenReturn(true); mFeedSurfaceMediator.onSurfaceClosed(); @@ -232,8 +247,9 @@ @Test public void testOnSurfaceClosed_noLaunchInProgress() { + when(mPrefService.getBoolean(Pref.ARTICLES_LIST_VISIBLE)).thenReturn(true); mFeedSurfaceMediator = createMediator(); - mFeedSurfaceMediator.bindStream(mStream); + mFeedSurfaceMediator.updateContent(); when(mLaunchReliabilityLogger.isLaunchInProgress()).thenReturn(false); mFeedSurfaceMediator.onSurfaceClosed(); @@ -388,11 +404,11 @@ .add(SectionHeaderProperties.createSectionHeader("Following")); mFeedSurfaceMediator = createMediator(FeedSurfaceCoordinator.StreamTabId.FOLLOWING, model); - when(mStream.getOptionsView()).thenReturn(mView); + when(mForYouStream.getOptionsView()).thenReturn(mView); mFeedSurfaceMediator.setStreamForTesting( - FeedSurfaceCoordinator.StreamTabId.FOLLOWING, mStream); + FeedSurfaceCoordinator.StreamTabId.FOLLOWING, mForYouStream); mFeedSurfaceMediator.setStreamForTesting( - FeedSurfaceCoordinator.StreamTabId.FOR_YOU, mStream); + FeedSurfaceCoordinator.StreamTabId.FOR_YOU, mForYouStream); OnSectionHeaderSelectedListener listener = mFeedSurfaceMediator.getOrCreateSectionHeaderListenerForTesting(); @@ -417,9 +433,9 @@ mFeedSurfaceMediator = createMediator(FeedSurfaceCoordinator.StreamTabId.FOLLOWING, model); mFeedSurfaceMediator.setStreamForTesting( - FeedSurfaceCoordinator.StreamTabId.FOLLOWING, mStream); + FeedSurfaceCoordinator.StreamTabId.FOLLOWING, mForYouStream); mFeedSurfaceMediator.setStreamForTesting( - FeedSurfaceCoordinator.StreamTabId.FOR_YOU, mStream); + FeedSurfaceCoordinator.StreamTabId.FOR_YOU, mForYouStream); OnSectionHeaderSelectedListener listener = mFeedSurfaceMediator.getOrCreateSectionHeaderListenerForTesting(); @@ -444,11 +460,11 @@ .add(SectionHeaderProperties.createSectionHeader("Following")); mFeedSurfaceMediator = createMediator(FeedSurfaceCoordinator.StreamTabId.FOLLOWING, model); - when(mStream.getOptionsView()).thenReturn(mView); + when(mForYouStream.getOptionsView()).thenReturn(mView); mFeedSurfaceMediator.setStreamForTesting( - FeedSurfaceCoordinator.StreamTabId.FOLLOWING, mStream); + FeedSurfaceCoordinator.StreamTabId.FOLLOWING, mForYouStream); mFeedSurfaceMediator.setStreamForTesting( - FeedSurfaceCoordinator.StreamTabId.FOR_YOU, mStream); + FeedSurfaceCoordinator.StreamTabId.FOR_YOU, mForYouStream); OnSectionHeaderSelectedListener listener = mFeedSurfaceMediator.getOrCreateSectionHeaderListenerForTesting(); @@ -472,9 +488,9 @@ mFeedSurfaceMediator = createMediator(FeedSurfaceCoordinator.StreamTabId.FOLLOWING, model); mFeedSurfaceMediator.setStreamForTesting( - FeedSurfaceCoordinator.StreamTabId.FOLLOWING, mStream); + FeedSurfaceCoordinator.StreamTabId.FOLLOWING, mForYouStream); mFeedSurfaceMediator.setStreamForTesting( - FeedSurfaceCoordinator.StreamTabId.FOR_YOU, mStream); + FeedSurfaceCoordinator.StreamTabId.FOR_YOU, mForYouStream); OnSectionHeaderSelectedListener listener = mFeedSurfaceMediator.getOrCreateSectionHeaderListenerForTesting(); @@ -494,11 +510,11 @@ .add(SectionHeaderProperties.createSectionHeader("Following")); mFeedSurfaceMediator = createMediator(FeedSurfaceCoordinator.StreamTabId.FOLLOWING, model); - when(mStream.getOptionsView()).thenReturn(mView); + when(mForYouStream.getOptionsView()).thenReturn(mView); mFeedSurfaceMediator.setStreamForTesting( - FeedSurfaceCoordinator.StreamTabId.FOLLOWING, mStream); + FeedSurfaceCoordinator.StreamTabId.FOLLOWING, mForYouStream); mFeedSurfaceMediator.setStreamForTesting( - FeedSurfaceCoordinator.StreamTabId.FOR_YOU, mStream); + FeedSurfaceCoordinator.StreamTabId.FOR_YOU, mForYouStream); OnSectionHeaderSelectedListener listener = mFeedSurfaceMediator.getOrCreateSectionHeaderListenerForTesting(); @@ -520,9 +536,9 @@ mFeedSurfaceMediator = createMediator(FeedSurfaceCoordinator.StreamTabId.FOLLOWING, model); mFeedSurfaceMediator.setStreamForTesting( - FeedSurfaceCoordinator.StreamTabId.FOLLOWING, mStream); + FeedSurfaceCoordinator.StreamTabId.FOLLOWING, mForYouStream); mFeedSurfaceMediator.setStreamForTesting( - FeedSurfaceCoordinator.StreamTabId.FOR_YOU, mStream); + FeedSurfaceCoordinator.StreamTabId.FOR_YOU, mForYouStream); OnSectionHeaderSelectedListener listener = mFeedSurfaceMediator.getOrCreateSectionHeaderListenerForTesting();
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index 24cca08..25ffdd30 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd
@@ -5146,6 +5146,12 @@ <message name="IDS_WEB_APP_DISABLE_WINDOW_CONTROLS_OVERLAY_TOOLTIP"> Show title bar </message> + <message name="IDS_WEB_APP_WINDOW_CONTROLS_OVERLAY_ENABLED_ALERT" desc="Status change notification that the title bar is hidden after window controls overlay is enabled"> + Title bar is now hidden + </message> + <message name="IDS_WEB_APP_WINDOW_CONTROLS_OVERLAY_DISABLED_ALERT" desc="Status change notification that the title bar is showing after window controls overlay is disabled"> + Title bar is now showing + </message> <!-- Components --> <message name="IDS_COMPONENTS_TITLE" desc="Title for the chrome://components page."> @@ -7233,6 +7239,9 @@ <message name="IDS_TAB_CXMENU_CLOSETABSTORIGHT" desc="The label of the 'Close Tabs to the Right' Tab context menu item."> Close tabs to the right </message> + <message name="IDS_TAB_CXMENU_CLOSETABSTOLEFT" desc="The label of the 'Close Tabs to the Left' Tab context menu item."> + Close tabs to the left + </message> <message name="IDS_TAB_CXMENU_FOCUS_THIS_TAB" desc="The label of the 'Focus this tab' Tab context menu item."> Focus this tab </message> @@ -7313,6 +7322,9 @@ <message name="IDS_TAB_CXMENU_CLOSETABSTORIGHT" desc="In Title Case: The label of the 'Close Tabs to the Right' Tab context menu item."> Close Tabs to the Right </message> + <message name="IDS_TAB_CXMENU_CLOSETABSTOLEFT" desc="In Title Case: The label of the 'Close Tabs to the Left' Tab context menu item."> + Close Tabs to the Left + </message> <message name="IDS_TAB_CXMENU_FOCUS_THIS_TAB" desc="In Title Case: The label of the 'Focus This Tab' Tab context menu item."> Focus This Tab </message>
diff --git a/chrome/app/generated_resources_grd/IDS_TAB_CXMENU_CLOSETABSTOLEFT.png.sha1 b/chrome/app/generated_resources_grd/IDS_TAB_CXMENU_CLOSETABSTOLEFT.png.sha1 new file mode 100644 index 0000000..4954573 --- /dev/null +++ b/chrome/app/generated_resources_grd/IDS_TAB_CXMENU_CLOSETABSTOLEFT.png.sha1
@@ -0,0 +1 @@ +cc11fe8891b6c2bb71a98ef553ef6057c20aa256 \ No newline at end of file
diff --git a/chrome/app/global_media_controls_strings.grdp b/chrome/app/global_media_controls_strings.grdp index 52751fd..2871c4ed 100644 --- a/chrome/app/global_media_controls_strings.grdp +++ b/chrome/app/global_media_controls_strings.grdp
@@ -1,15 +1,9 @@ <?xml version="1.0" encoding="utf-8"?> <!-- Global Media Controls-specific strings (included from generated_resources.grd). --> <grit-part> - <message name="IDS_GLOBAL_MEDIA_CONTROLS_BACK_TO_TAB" desc="A11y text for the Global Media Controls container describing how clicking it takes you back to the tab."> - Back to tab - </message> <message name="IDS_GLOBAL_MEDIA_CONTROLS_ICON_TOOLTIP_TEXT" desc="Tooltip for the Global Media Controls icon, which appears in the toolbar. The tooltip appears on mouseover of the icon."> Control your music, videos, and more </message> - <message name="IDS_GLOBAL_MEDIA_CONTROLS_DISMISS_ICON_TOOLTIP_TEXT" desc="Tooltip for the dismiss button within the Global Media Controls dialog. The tooltip appears on mouseover of the icon."> - Dismiss - </message> <message name="IDS_GLOBAL_MEDIA_CONTROLS_DEVICES_BUTTON_LABEL" desc="Label for a button that opens a menu for picking an audio or cast device to play from."> Select a device </message>
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index 2c7581e..3ce275f 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -2444,7 +2444,6 @@ "//chrome/browser/ui/webui/chromeos/crostini_installer:mojo_bindings", "//chrome/browser/ui/webui/chromeos/crostini_upgrader:mojo_bindings", "//chrome/browser/ui/webui/chromeos/emoji:mojo_bindings", - "//chrome/browser/ui/webui/chromeos/enterprise_casting:mojo_bindings", "//chrome/browser/ui/webui/chromeos/launcher_internals:mojo_bindings", "//chrome/browser/ui/webui/chromeos/parent_access:mojo_bindings", "//chrome/browser/ui/webui/chromeos/vm:mojo_bindings", @@ -4413,6 +4412,7 @@ "//chrome/browser/share/proto:proto", "//chrome/browser/ui/color:color_headers", "//chrome/browser/ui/webui/tab_strip:mojo_bindings", + "//chrome/browser/ui/webui/enterprise_casting:mojo_bindings", "//chrome/browser/web_applications", "//chrome/browser/web_applications/app_service", "//chrome/common/apps/platform_apps", @@ -5025,6 +5025,8 @@ "lacros/client_cert_store_lacros.h", "lacros/crosapi_pref_observer.cc", "lacros/crosapi_pref_observer.h", + "lacros/device_settings_lacros.cc", + "lacros/device_settings_lacros.h", "lacros/download_controller_client_lacros.cc", "lacros/download_controller_client_lacros.h", "lacros/drivefs_cache.cc",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 84b04cba..2adf132 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -4201,6 +4201,15 @@ kOsCrOS, FEATURE_VALUE_TYPE( features::kExperimentalAccessibilitySwitchAccessSetupGuide)}, + {"enable-experimental-accessibility-switch-access-multistep-automation", + flag_descriptions:: + kExperimentalAccessibilitySwitchAccessMultistepAutomationName, + flag_descriptions:: + kExperimentalAccessibilitySwitchAccessMultistepAutomationDescription, + kOsCrOS, + SINGLE_VALUE_TYPE( + ::switches:: + kEnableExperimentalAccessibilitySwitchAccessMultistepAutomation)}, {"enable-experimental-kernel-vm-support", flag_descriptions::kKernelnextVMsName, flag_descriptions::kKernelnextVMsDescription, kOsCrOS, @@ -7461,6 +7470,11 @@ #endif // BUILDFLAG(IS_CHROMEOS_ASH) #if BUILDFLAG(IS_CHROMEOS_ASH) + {"enable-phone-hub-call-notification", + flag_descriptions::kPhoneHubCallNotificationName, + flag_descriptions::kPhoneHubCallNotificationDescription, kOsCrOS, + FEATURE_VALUE_TYPE(ash::features::kPhoneHubCallNotification)}, + {"enable-phone-hub-camera-roll", flag_descriptions::kPhoneHubCameraRollName, flag_descriptions::kPhoneHubCameraRollDescription, kOsCrOS, FEATURE_VALUE_TYPE(ash::features::kPhoneHubCameraRoll)},
diff --git a/chrome/browser/android/explore_sites/explore_sites_fetcher_unittest.cc b/chrome/browser/android/explore_sites/explore_sites_fetcher_unittest.cc index 92392033..455e2fd 100644 --- a/chrome/browser/android/explore_sites/explore_sites_fetcher_unittest.cc +++ b/chrome/browser/android/explore_sites/explore_sites_fetcher_unittest.cc
@@ -366,9 +366,8 @@ net::HttpRequestHeaders headers = last_resource_request.headers; std::string header_text; - bool success; - success = headers.GetHeader("X-Goog-Chrome-Experiment-Tag", &header_text); + headers.GetHeader("X-Goog-Chrome-Experiment-Tag", &header_text); EXPECT_EQ(std::string(kExperimentData), header_text); }
diff --git a/chrome/browser/android/oom_intervention/oom_intervention_config.cc b/chrome/browser/android/oom_intervention/oom_intervention_config.cc index 2390fe9..d678c96 100644 --- a/chrome/browser/android/oom_intervention/oom_intervention_config.cc +++ b/chrome/browser/android/oom_intervention/oom_intervention_config.cc
@@ -132,11 +132,8 @@ use_components_callback_ = base::GetFieldTrialParamByFeatureAsBool( features::kOomIntervention, kUseComponentCallbacks, true); - OomInterventionBrowserMonitorStatus status = - OomInterventionBrowserMonitorStatus::kEnabledWithValidConfig; if (!GetSwapFreeThreshold(&swapfree_threshold_)) { is_swap_monitor_enabled_ = false; - status = OomInterventionBrowserMonitorStatus::kEnabledWithNoSwap; } // If no threshold is specified, set blink_workload_threshold to 10% of the // RAM size.
diff --git a/chrome/browser/app_controller_mac.mm b/chrome/browser/app_controller_mac.mm index 97749b5..5d98086c 100644 --- a/chrome/browser/app_controller_mac.mm +++ b/chrome/browser/app_controller_mac.mm
@@ -302,7 +302,6 @@ // TODO(davidben): To limit those cases, consider preferentially // deminiaturizing a window on the current space. NSWindow* frontmost_window = nil; - NSWindow* frontmost_window_all_spaces = nil; NSWindow* frontmost_miniaturized_window = nil; bool all_miniaturized = true; for (NSWindow* win in [[NSApp orderedWindows] reverseObjectEnumerator]) { @@ -312,7 +311,6 @@ frontmost_miniaturized_window = win; } else if ([win isVisible]) { all_miniaturized = false; - frontmost_window_all_spaces = win; if ([win isOnActiveSpace]) { // Raise the old |frontmost_window| (if any). The topmost |win| will be // raised with makeKeyAndOrderFront: below.
diff --git a/chrome/browser/ash/app_restore/app_restore_arc_task_handler.cc b/chrome/browser/ash/app_restore/app_restore_arc_task_handler.cc index c297d35..5d9d49a 100644 --- a/chrome/browser/ash/app_restore/app_restore_arc_task_handler.cc +++ b/chrome/browser/ash/app_restore/app_restore_arc_task_handler.cc
@@ -115,6 +115,8 @@ if (handler) handler->OnArcPlayStoreEnabledChanged(enabled); } + + GetAppRestoreArcInfo()->NotifyPlayStoreEnabledChanged(enabled); } void AppRestoreArcTaskHandler::OnShelfReady() {
diff --git a/chrome/browser/ash/app_restore/full_restore_app_launch_handler_browsertest.cc b/chrome/browser/ash/app_restore/full_restore_app_launch_handler_browsertest.cc index e3f755f..49aade5 100644 --- a/chrome/browser/ash/app_restore/full_restore_app_launch_handler_browsertest.cc +++ b/chrome/browser/ash/app_restore/full_restore_app_launch_handler_browsertest.cc
@@ -1418,6 +1418,14 @@ return &test_full_restore_info_observer_; } + const std::map<int32_t, std::string>& task_id_to_app_id() { + auto* arc_save_handler = + ::full_restore::FullRestoreSaveHandler::GetInstance() + ->arc_save_handler_.get(); + DCHECK(arc_save_handler); + return arc_save_handler->task_id_to_app_id_; + } + protected: app_restore::ArcAppLaunchHandler* arc_app_launch_handler_ = nullptr; @@ -1928,6 +1936,89 @@ StopInstance(); } +// Test ARC apps restore data is removed, when Play Store is disabled. +IN_PROC_BROWSER_TEST_F(FullRestoreAppLaunchHandlerArcAppBrowserTest, + DisablePlayStore) { + SetProfile(); + InstallTestApps(kTestAppPackage, true); + + const std::string app_id1 = GetTestApp1Id(kTestAppPackage); + const std::string app_id2 = GetTestApp2Id(kTestAppPackage); + int32_t session_id1 = + ::full_restore::FullRestoreSaveHandler::GetInstance()->GetArcSessionId(); + int32_t session_id2 = + ::full_restore::FullRestoreSaveHandler::GetInstance()->GetArcSessionId(); + ::full_restore::FullRestoreInfo::GetInstance()->AddObserver( + test_full_restore_info_observer()); + + SaveAppLaunchInfo(app_id1, session_id1); + SaveAppLaunchInfo(app_id2, session_id2); + + // Simulate creating kTaskId1. + int32_t kTaskId1 = 100; + CreateTask(app_id1, kTaskId1, session_id1); + + // Create the window for the app1 and store its bounds. + views::Widget* widget1 = CreateExoWindow("org.chromium.arc.100"); + aura::Window* window1 = widget1->GetNativeWindow(); + + // Create the window for the app2 and store its bounds. + int32_t kTaskId2 = 101; + views::Widget* widget2 = CreateExoWindow("org.chromium.arc.101"); + aura::Window* window2 = widget2->GetNativeWindow(); + + // Simulate creating kTaskId2. + CreateTask(app_id2, kTaskId2, session_id2); + VerifyObserver(window1, /*launch_count=*/1, /*init_count=*/0); + VerifyObserver(window2, /*launch_count=*/1, /*init_count=*/0); + + VerifyWindowProperty(window1, kTaskId1, /*restore_window_id*/ 0, + /*hidden=*/false); + VerifyWindowProperty(window2, kTaskId2, /*restore_window_id*/ 0, + /*hidden=*/false); + + WaitForAppLaunchInfoSaved(); + + int32_t activation_index1 = 11; + int32_t activation_index2 = 12; + SaveWindowInfo(window1, activation_index1, + chromeos::WindowStateType::kMaximized); + SaveWindowInfo(window2, activation_index2, + chromeos::WindowStateType::kMinimized); + + WaitForAppLaunchInfoSaved(); + + // Verify ARC app launch info is saved in `restore_data`. + const auto* restore_data = + ::full_restore::FullRestoreSaveHandler::GetInstance()->GetRestoreData( + profile()->GetPath()); + ASSERT_TRUE(restore_data); + ASSERT_FALSE(restore_data->app_id_to_launch_list().empty()); + ASSERT_FALSE(task_id_to_app_id().empty()); + + // Simulate Play Store is disabled. + app_restore::AppRestoreArcTaskHandler::GetForProfile(profile()) + ->OnArcPlayStoreEnabledChanged(/*enabled=*/false); + widget1->CloseNow(); + + // Verify ARC app launch info is removed from `restore_data`. + ASSERT_TRUE(restore_data->app_id_to_launch_list().empty()); + ASSERT_TRUE(task_id_to_app_id().empty()); + + widget2->CloseNow(); + + // Simulate Play Store is enabled and `app_id1` is launched. + int32_t session_id3 = + ::full_restore::FullRestoreSaveHandler::GetInstance()->GetArcSessionId(); + int32_t kTaskId3 = 201; + SaveAppLaunchInfo(app_id1, session_id3); + CreateTask(app_id1, kTaskId3, session_id3); + ASSERT_FALSE(restore_data->app_id_to_launch_list().empty()); + ASSERT_TRUE(base::Contains(restore_data->app_id_to_launch_list(), app_id1)); + + StopInstance(); +} + // Test restoration when the ARC window is created before OnTaskCreated is // called. IN_PROC_BROWSER_TEST_F(FullRestoreAppLaunchHandlerArcAppBrowserTest,
diff --git a/chrome/browser/ash/crosapi/BUILD.gn b/chrome/browser/ash/crosapi/BUILD.gn index b827416..ad18063 100644 --- a/chrome/browser/ash/crosapi/BUILD.gn +++ b/chrome/browser/ash/crosapi/BUILD.gn
@@ -43,6 +43,8 @@ "crosapi_manager.h", "device_attributes_ash.cc", "device_attributes_ash.h", + "device_settings_ash.cc", + "device_settings_ash.h", "download_controller_ash.cc", "download_controller_ash.h", "drive_integration_service_ash.cc",
diff --git a/chrome/browser/ash/crosapi/browser_util.cc b/chrome/browser/ash/crosapi/browser_util.cc index 1b78279..739bb2b 100644 --- a/chrome/browser/ash/crosapi/browser_util.cc +++ b/chrome/browser/ash/crosapi/browser_util.cc
@@ -58,6 +58,7 @@ #include "chromeos/crosapi/mojom/content_protection.mojom.h" #include "chromeos/crosapi/mojom/crosapi.mojom.h" #include "chromeos/crosapi/mojom/device_attributes.mojom.h" +#include "chromeos/crosapi/mojom/device_settings_service.mojom.h" #include "chromeos/crosapi/mojom/download_controller.mojom.h" #include "chromeos/crosapi/mojom/drive_integration_service.mojom.h" #include "chromeos/crosapi/mojom/feedback.mojom.h" @@ -262,72 +263,6 @@ return result; } -// Returns the device policy data needed for Lacros. -mojom::DeviceSettingsPtr GetDeviceSettings() { - mojom::DeviceSettingsPtr result = mojom::DeviceSettings::New(); - - result->attestation_for_content_protection_enabled = MojoOptionalBool::kUnset; - if (ash::CrosSettings::IsInitialized()) { - // It's expected that the CrosSettings values are trusted. The only - // theoretical exception is when device ownership is taken on consumer - // device. Then there's no settings to be passed to Lacros anyway. - auto trusted_result = - ash::CrosSettings::Get()->PrepareTrustedValues(base::DoNothing()); - if (trusted_result == ash::CrosSettingsProvider::TRUSTED) { - const auto* cros_settings = ash::CrosSettings::Get(); - bool attestation_enabled = false; - if (cros_settings->GetBoolean( - ash::kAttestationForContentProtectionEnabled, - &attestation_enabled)) { - result->attestation_for_content_protection_enabled = - attestation_enabled ? MojoOptionalBool::kTrue - : MojoOptionalBool::kFalse; - } - - const base::ListValue* usb_detachable_allow_list; - if (cros_settings->GetList(ash::kUsbDetachableAllowlist, - &usb_detachable_allow_list)) { - mojom::UsbDetachableAllowlistPtr allow_list = - mojom::UsbDetachableAllowlist::New(); - for (const auto& entry : usb_detachable_allow_list->GetList()) { - mojom::UsbDeviceIdPtr usb_device_id = mojom::UsbDeviceId::New(); - absl::optional<int> vid = - entry.FindIntKey(ash::kUsbDetachableAllowlistKeyVid); - if (vid) { - usb_device_id->has_vendor_id = true; - usb_device_id->vendor_id = vid.value(); - } - absl::optional<int> pid = - entry.FindIntKey(ash::kUsbDetachableAllowlistKeyPid); - if (pid) { - usb_device_id->has_product_id = true; - usb_device_id->product_id = pid.value(); - } - allow_list->usb_device_ids.push_back(std::move(usb_device_id)); - } - result->usb_detachable_allow_list = std::move(allow_list); - } - } else { - LOG(WARNING) << "Unexpected crossettings trusted values status: " - << trusted_result; - } - } - - result->device_system_wide_tracing_enabled = MojoOptionalBool::kUnset; - auto* local_state = g_browser_process->local_state(); - if (local_state) { - auto* pref = local_state->FindPreference( - ash::prefs::kDeviceSystemWideTracingEnabled); - if (pref && pref->IsManaged()) { - result->device_system_wide_tracing_enabled = - pref->GetValue()->GetBool() ? MojoOptionalBool::kTrue - : MojoOptionalBool::kFalse; - } - } - - return result; -} - struct InterfaceVersionEntry { base::Token uuid; uint32_t version; @@ -355,6 +290,7 @@ MakeInterfaceVersionEntry<crosapi::mojom::ContentProtection>(), MakeInterfaceVersionEntry<crosapi::mojom::Crosapi>(), MakeInterfaceVersionEntry<crosapi::mojom::DeviceAttributes>(), + MakeInterfaceVersionEntry<crosapi::mojom::DeviceSettingsService>(), MakeInterfaceVersionEntry<crosapi::mojom::DownloadController>(), MakeInterfaceVersionEntry<crosapi::mojom::DriveIntegrationService>(), MakeInterfaceVersionEntry<crosapi::mojom::Feedback>(), @@ -458,7 +394,7 @@ } static_assert( - crosapi::mojom::Crosapi::Version_ == 54, + crosapi::mojom::Crosapi::Version_ == 55, "if you add a new crosapi, please add it to kInterfaceVersionEntries"); static_assert(!HasDuplicatedUuid(), "Each Crosapi Mojom interface should have unique UUID."); @@ -1094,6 +1030,72 @@ } } +// Returns the device policy data needed for Lacros. +mojom::DeviceSettingsPtr GetDeviceSettings() { + mojom::DeviceSettingsPtr result = mojom::DeviceSettings::New(); + + result->attestation_for_content_protection_enabled = MojoOptionalBool::kUnset; + if (ash::CrosSettings::IsInitialized()) { + // It's expected that the CrosSettings values are trusted. The only + // theoretical exception is when device ownership is taken on consumer + // device. Then there's no settings to be passed to Lacros anyway. + auto trusted_result = + ash::CrosSettings::Get()->PrepareTrustedValues(base::DoNothing()); + if (trusted_result == ash::CrosSettingsProvider::TRUSTED) { + const auto* cros_settings = ash::CrosSettings::Get(); + bool attestation_enabled = false; + if (cros_settings->GetBoolean( + ash::kAttestationForContentProtectionEnabled, + &attestation_enabled)) { + result->attestation_for_content_protection_enabled = + attestation_enabled ? MojoOptionalBool::kTrue + : MojoOptionalBool::kFalse; + } + + const base::ListValue* usb_detachable_allow_list; + if (cros_settings->GetList(ash::kUsbDetachableAllowlist, + &usb_detachable_allow_list)) { + mojom::UsbDetachableAllowlistPtr allow_list = + mojom::UsbDetachableAllowlist::New(); + for (const auto& entry : usb_detachable_allow_list->GetList()) { + mojom::UsbDeviceIdPtr usb_device_id = mojom::UsbDeviceId::New(); + absl::optional<int> vid = + entry.FindIntKey(ash::kUsbDetachableAllowlistKeyVid); + if (vid) { + usb_device_id->has_vendor_id = true; + usb_device_id->vendor_id = vid.value(); + } + absl::optional<int> pid = + entry.FindIntKey(ash::kUsbDetachableAllowlistKeyPid); + if (pid) { + usb_device_id->has_product_id = true; + usb_device_id->product_id = pid.value(); + } + allow_list->usb_device_ids.push_back(std::move(usb_device_id)); + } + result->usb_detachable_allow_list = std::move(allow_list); + } + } else { + LOG(WARNING) << "Unexpected crossettings trusted values status: " + << trusted_result; + } + } + + result->device_system_wide_tracing_enabled = MojoOptionalBool::kUnset; + auto* local_state = g_browser_process->local_state(); + if (local_state) { + auto* pref = local_state->FindPreference( + ash::prefs::kDeviceSystemWideTracingEnabled); + if (pref && pref->IsManaged()) { + result->device_system_wide_tracing_enabled = + pref->GetValue()->GetBool() ? MojoOptionalBool::kTrue + : MojoOptionalBool::kFalse; + } + } + + return result; +} + LacrosLaunchSwitch GetLaunchSwitchForTesting() { return GetLaunchSwitch(); }
diff --git a/chrome/browser/ash/crosapi/browser_util.h b/chrome/browser/ash/crosapi/browser_util.h index 6e9f2d4c..9d82b4c 100644 --- a/chrome/browser/ash/crosapi/browser_util.h +++ b/chrome/browser/ash/crosapi/browser_util.h
@@ -283,6 +283,9 @@ version_info::Channel GetLacrosSelectionUpdateChannel( LacrosSelection selection); +// Returns the device settings needed for Lacros. +mojom::DeviceSettingsPtr GetDeviceSettings(); + // Exposed for testing. Returns the lacros integration suggested by the policy // lacros-availability, modified by Finch flags and user flags as appropriate. LacrosLaunchSwitch GetLaunchSwitchForTesting();
diff --git a/chrome/browser/ash/crosapi/browser_util_unittest.cc b/chrome/browser/ash/crosapi/browser_util_unittest.cc index 81c6aa0..cef0dc5 100644 --- a/chrome/browser/ash/crosapi/browser_util_unittest.cc +++ b/chrome/browser/ash/crosapi/browser_util_unittest.cc
@@ -13,6 +13,7 @@ #include "base/values.h" #include "chrome/browser/ash/login/users/fake_chrome_user_manager.h" #include "chrome/browser/ash/profiles/profile_helper.h" +#include "chrome/browser/ash/settings/scoped_testing_cros_settings.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/policy/profile_policy_connector.h" #include "chrome/browser/profiles/profile_manager.h" @@ -23,6 +24,7 @@ #include "chrome/test/base/testing_profile.h" #include "chromeos/crosapi/mojom/crosapi.mojom.h" #include "chromeos/crosapi/mojom/keystore_service.mojom.h" +#include "chromeos/settings/cros_settings_names.h" #include "components/account_id/account_id.h" #include "components/policy/policy_constants.h" #include "components/user_manager/scoped_user_manager.h" @@ -700,4 +702,50 @@ cmdline->RemoveSwitch(browser_util::kLacrosStabilitySwitch); } +TEST_F(BrowserUtilTest, EmptyDeviceSettings) { + auto settings = browser_util::GetDeviceSettings(); + EXPECT_EQ(settings->attestation_for_content_protection_enabled, + crosapi::mojom::DeviceSettings::OptionalBool::kUnset); + EXPECT_EQ(settings->device_system_wide_tracing_enabled, + crosapi::mojom::DeviceSettings::OptionalBool::kUnset); +} + +TEST_F(BrowserUtilTest, DeviceSettingsWithData) { + testing_profile_.ScopedCrosSettingsTestHelper() + ->ReplaceDeviceSettingsProviderWithStub(); + testing_profile_.ScopedCrosSettingsTestHelper()->SetTrustedStatus( + ash::CrosSettingsProvider::TRUSTED); + base::RunLoop().RunUntilIdle(); + testing_profile_.ScopedCrosSettingsTestHelper() + ->GetStubbedProvider() + ->SetBoolean(chromeos::kAttestationForContentProtectionEnabled, true); + + base::Value allowlist(base::Value::Type::LIST); + base::Value ids(base::Value::Type::DICTIONARY); + ids.SetIntKey(ash::kUsbDetachableAllowlistKeyVid, 2); + ids.SetIntKey(ash::kUsbDetachableAllowlistKeyPid, 3); + allowlist.Append(std::move(ids)); + + testing_profile_.ScopedCrosSettingsTestHelper()->GetStubbedProvider()->Set( + chromeos::kUsbDetachableAllowlist, std::move(allowlist)); + + auto settings = browser_util::GetDeviceSettings(); + testing_profile_.ScopedCrosSettingsTestHelper() + ->RestoreRealDeviceSettingsProvider(); + + EXPECT_EQ(settings->attestation_for_content_protection_enabled, + crosapi::mojom::DeviceSettings::OptionalBool::kTrue); + EXPECT_EQ(settings->usb_detachable_allow_list->usb_device_ids.size(), 1); + EXPECT_EQ( + settings->usb_detachable_allow_list->usb_device_ids[0]->has_vendor_id, + true); + EXPECT_EQ(settings->usb_detachable_allow_list->usb_device_ids[0]->vendor_id, + 2); + EXPECT_EQ( + settings->usb_detachable_allow_list->usb_device_ids[0]->has_product_id, + true); + EXPECT_EQ(settings->usb_detachable_allow_list->usb_device_ids[0]->product_id, + 3); +} + } // namespace crosapi
diff --git a/chrome/browser/ash/crosapi/crosapi_ash.cc b/chrome/browser/ash/crosapi/crosapi_ash.cc index daa94f1733..e8983b84 100644 --- a/chrome/browser/ash/crosapi/crosapi_ash.cc +++ b/chrome/browser/ash/crosapi/crosapi_ash.cc
@@ -29,6 +29,7 @@ #include "chrome/browser/ash/crosapi/clipboard_history_ash.h" #include "chrome/browser/ash/crosapi/content_protection_ash.h" #include "chrome/browser/ash/crosapi/device_attributes_ash.h" +#include "chrome/browser/ash/crosapi/device_settings_ash.h" #include "chrome/browser/ash/crosapi/download_controller_ash.h" #include "chrome/browser/ash/crosapi/drive_integration_service_ash.h" #include "chrome/browser/ash/crosapi/feedback_ash.h" @@ -124,6 +125,7 @@ clipboard_history_ash_(std::make_unique<ClipboardHistoryAsh>()), content_protection_ash_(std::make_unique<ContentProtectionAsh>()), device_attributes_ash_(std::make_unique<DeviceAttributesAsh>()), + device_settings_ash_(std::make_unique<DeviceSettingsAsh>()), download_controller_ash_(std::make_unique<DownloadControllerAsh>()), drive_integration_service_ash_( std::make_unique<DriveIntegrationServiceAsh>()), @@ -421,6 +423,11 @@ device_attributes_ash_->BindReceiver(std::move(receiver)); } +void CrosapiAsh::BindDeviceSettingsService( + mojo::PendingReceiver<mojom::DeviceSettingsService> receiver) { + device_settings_ash_->BindReceiver(std::move(receiver)); +} + void CrosapiAsh::BindDownloadController( mojo::PendingReceiver<mojom::DownloadController> receiver) { download_controller_ash_->BindReceiver(std::move(receiver));
diff --git a/chrome/browser/ash/crosapi/crosapi_ash.h b/chrome/browser/ash/crosapi/crosapi_ash.h index 22add6e..fa5e725 100644 --- a/chrome/browser/ash/crosapi/crosapi_ash.h +++ b/chrome/browser/ash/crosapi/crosapi_ash.h
@@ -32,6 +32,7 @@ class ClipboardHistoryAsh; class ContentProtectionAsh; class DeviceAttributesAsh; +class DeviceSettingsAsh; class DownloadControllerAsh; class DriveIntegrationServiceAsh; class FeedbackAsh; @@ -114,6 +115,8 @@ mojo::PendingReceiver<mojom::ContentProtection> receiver) override; void BindDeviceAttributes( mojo::PendingReceiver<mojom::DeviceAttributes> receiver) override; + void BindDeviceSettingsService( + mojo::PendingReceiver<mojom::DeviceSettingsService> receiver) override; void BindHoldingSpaceService( mojo::PendingReceiver<mojom::HoldingSpaceService> receiver) override; void BindDownloadController( @@ -260,6 +263,7 @@ std::unique_ptr<ClipboardHistoryAsh> clipboard_history_ash_; std::unique_ptr<ContentProtectionAsh> content_protection_ash_; std::unique_ptr<DeviceAttributesAsh> device_attributes_ash_; + std::unique_ptr<DeviceSettingsAsh> device_settings_ash_; std::unique_ptr<DownloadControllerAsh> download_controller_ash_; std::unique_ptr<DriveIntegrationServiceAsh> drive_integration_service_ash_; std::unique_ptr<FeedbackAsh> feedback_ash_;
diff --git a/chrome/browser/ash/crosapi/device_settings_ash.cc b/chrome/browser/ash/crosapi/device_settings_ash.cc new file mode 100644 index 0000000..bc8ad9b --- /dev/null +++ b/chrome/browser/ash/crosapi/device_settings_ash.cc
@@ -0,0 +1,40 @@ +// Copyright 2021 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/ash/crosapi/device_settings_ash.h" + +#include <utility> + +#include "chrome/browser/ash/crosapi/browser_util.h" +#include "mojo/public/cpp/bindings/remote.h" + +namespace crosapi { + +DeviceSettingsAsh::DeviceSettingsAsh() { + if (ash::DeviceSettingsService::IsInitialized()) + ash::DeviceSettingsService::Get()->AddObserver(this); +} + +DeviceSettingsAsh::~DeviceSettingsAsh() { + if (ash::DeviceSettingsService::IsInitialized()) + ash::DeviceSettingsService::Get()->RemoveObserver(this); +} + +void DeviceSettingsAsh::BindReceiver( + mojo::PendingReceiver<mojom::DeviceSettingsService> receiver) { + receivers_.Add(this, std::move(receiver)); +} + +void DeviceSettingsAsh::DeviceSettingsUpdated() { + for (auto& observer : observers_) + observer->UpdateDeviceSettings(browser_util::GetDeviceSettings()); +} + +void DeviceSettingsAsh::AddDeviceSettingsObserver( + mojo::PendingRemote<mojom::DeviceSettingsObserver> observer) { + mojo::Remote<mojom::DeviceSettingsObserver> remote(std::move(observer)); + observers_.Add(std::move(remote)); +} + +} // namespace crosapi
diff --git a/chrome/browser/ash/crosapi/device_settings_ash.h b/chrome/browser/ash/crosapi/device_settings_ash.h new file mode 100644 index 0000000..bf4bff0 --- /dev/null +++ b/chrome/browser/ash/crosapi/device_settings_ash.h
@@ -0,0 +1,46 @@ +// Copyright 2021 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_ASH_CROSAPI_DEVICE_SETTINGS_ASH_H_ +#define CHROME_BROWSER_ASH_CROSAPI_DEVICE_SETTINGS_ASH_H_ + +#include "chrome/browser/ash/settings/device_settings_service.h" +#include "chromeos/crosapi/mojom/device_settings_service.mojom.h" +#include "mojo/public/cpp/bindings/pending_receiver.h" +#include "mojo/public/cpp/bindings/pending_remote.h" +#include "mojo/public/cpp/bindings/receiver_set.h" +#include "mojo/public/cpp/bindings/remote_set.h" + +namespace crosapi { + +// Implements the crosapi device settings interface. Lives in ash-chrome. +// Allows lacros-chrome to access device settings that live in ash. +class DeviceSettingsAsh : public mojom::DeviceSettingsService, + public ash::DeviceSettingsService::Observer { + public: + DeviceSettingsAsh(); + DeviceSettingsAsh(const DeviceSettingsAsh&) = delete; + DeviceSettingsAsh& operator=(const DeviceSettingsAsh&) = delete; + ~DeviceSettingsAsh() override; + + void BindReceiver( + mojo::PendingReceiver<mojom::DeviceSettingsService> receiver); + + // ash::DeviceSettingsService::Observer + void DeviceSettingsUpdated() override; + + // crosapi::mojom::DeviceSettingsService: + void AddDeviceSettingsObserver( + mojo::PendingRemote<mojom::DeviceSettingsObserver> observer) override; + + private: + mojo::ReceiverSet<mojom::DeviceSettingsService> receivers_; + + // Support any number of device settings observers. + mojo::RemoteSet<mojom::DeviceSettingsObserver> observers_; +}; + +} // namespace crosapi + +#endif // CHROME_BROWSER_ASH_CROSAPI_DEVICE_SETTINGS_ASH_H_
diff --git a/chrome/browser/ash/login/enrollment/enrollment_local_policy_server_browsertest.cc b/chrome/browser/ash/login/enrollment/enrollment_local_policy_server_browsertest.cc index ecfc28b..c11ff0d 100644 --- a/chrome/browser/ash/login/enrollment/enrollment_local_policy_server_browsertest.cc +++ b/chrome/browser/ash/login/enrollment/enrollment_local_policy_server_browsertest.cc
@@ -9,7 +9,6 @@ #include "base/bind.h" #include "base/check.h" #include "base/test/gtest_util.h" -#include "base/test/metrics/histogram_tester.h" #include "base/values.h" #include "build/build_config.h" #include "chrome/browser/ash/app_mode/kiosk_app_manager.h" @@ -1022,37 +1021,31 @@ INSTANTIATE_TEST_SUITE_P(All, OobeGuestButtonPolicy, ::testing::Bool()); IN_PROC_BROWSER_TEST_F(EnrollmentLocalPolicyServerBase, SwitchToViews) { - base::HistogramTester histogram_tester; TriggerEnrollmentAndSignInSuccessfully(); enrollment_ui_.WaitForStep(test::ui::kEnrollmentStepSuccess); ConfirmAndWaitLoginScreen(); EXPECT_TRUE(LoginScreenTestApi::IsOobeDialogVisible()); - histogram_tester.ExpectTotalCount("OOBE.WebUIToViewsSwitch.Duration", 1); } IN_PROC_BROWSER_TEST_F(EnrollmentLocalPolicyServerBase, SwitchToViewsLocalUsers) { AddPublicUser("test_user"); - base::HistogramTester histogram_tester; TriggerEnrollmentAndSignInSuccessfully(); enrollment_ui_.WaitForStep(test::ui::kEnrollmentStepSuccess); ConfirmAndWaitLoginScreen(); EXPECT_FALSE(LoginScreenTestApi::IsOobeDialogVisible()); EXPECT_EQ(LoginScreenTestApi::GetUsersCount(), 1); - histogram_tester.ExpectTotalCount("OOBE.WebUIToViewsSwitch.Duration", 1); } IN_PROC_BROWSER_TEST_F(EnrollmentLocalPolicyServerBase, SwitchToViewsLocales) { auto initial_label = LoginScreenTestApi::GetShutDownButtonLabel(); SetLoginScreenLocale("ru-RU"); - base::HistogramTester histogram_tester; TriggerEnrollmentAndSignInSuccessfully(); enrollment_ui_.WaitForStep(test::ui::kEnrollmentStepSuccess); ConfirmAndWaitLoginScreen(); EXPECT_TRUE(LoginScreenTestApi::IsOobeDialogVisible()); EXPECT_NE(LoginScreenTestApi::GetShutDownButtonLabel(), initial_label); - histogram_tester.ExpectTotalCount("OOBE.WebUIToViewsSwitch.Duration", 1); } class KioskEnrollmentTest : public EnrollmentLocalPolicyServerBase {
diff --git a/chrome/browser/ash/login/ui/login_display_host_webui.cc b/chrome/browser/ash/login/ui/login_display_host_webui.cc index 3c086fc2..d3c01d4 100644 --- a/chrome/browser/ash/login/ui/login_display_host_webui.cc +++ b/chrome/browser/ash/login/ui/login_display_host_webui.cc
@@ -26,9 +26,6 @@ #include "base/metrics/histogram_functions.h" #include "base/strings/string_split.h" #include "base/strings/utf_string_conversions.h" -#include "base/task/single_thread_task_runner_forward.h" -#include "base/threading/thread_restrictions.h" -#include "base/threading/thread_task_runner_handle.h" #include "base/time/time.h" #include "base/timer/elapsed_timer.h" #include "base/trace_event/trace_event.h" @@ -1286,38 +1283,10 @@ TriggerShowLoginWizardFinish(locale, std::move(data)); } -class WebUIToViewsSwitchMetricsReporter - : public session_manager::SessionManagerObserver { - public: - WebUIToViewsSwitchMetricsReporter() { - session_observation_.Observe(session_manager::SessionManager::Get()); - } - - // session_manager::SessionManagerObserver: - void OnLoginOrLockScreenVisible() override { - if (LoginDisplayHost::default_host()->GetOobeUI()) { - DCHECK_EQ(OobeUI::kGaiaSigninDisplay, - LoginDisplayHost::default_host()->GetOobeUI()->display_type()); - } - base::UmaHistogramTimes("OOBE.WebUIToViewsSwitch.Duration", - timer_.Elapsed()); - base::SequencedTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, this); - } - - private: - base::ScopedObservation<session_manager::SessionManager, - session_manager::SessionManagerObserver> - session_observation_{this}; - base::ElapsedTimer timer_; -}; - void SwitchWebUItoMojo() { DCHECK_EQ(LoginDisplayHost::default_host()->GetOobeUI()->display_type(), OobeUI::kOobeDisplay); - // The object deletes itself. - new WebUIToViewsSwitchMetricsReporter(); - // This replaces WebUI host with the Mojo (views) host. ShowLoginWizard(OobeScreen::SCREEN_UNKNOWN); }
diff --git a/chrome/browser/ash/net/network_portal_detector_impl.cc b/chrome/browser/ash/net/network_portal_detector_impl.cc index a677e67..f620929 100644 --- a/chrome/browser/ash/net/network_portal_detector_impl.cc +++ b/chrome/browser/ash/net/network_portal_detector_impl.cc
@@ -362,7 +362,6 @@ attempt_timeout_.Cancel(); CaptivePortalStatus status = CAPTIVE_PORTAL_STATUS_UNKNOWN; - bool no_response_since_portal = false; switch (result) { case captive_portal::RESULT_NO_RESPONSE: if (response_code == net::HTTP_PROXY_AUTHENTICATION_REQUIRED) { @@ -370,7 +369,6 @@ } else if (network && network->IsShillCaptivePortal()) { // Take into account shill's detection results. status = CAPTIVE_PORTAL_STATUS_PORTAL; - no_response_since_portal = true; } else { status = CAPTIVE_PORTAL_STATUS_OFFLINE; }
diff --git a/chrome/browser/ash/policy/remote_commands/device_command_reset_euicc_job.cc b/chrome/browser/ash/policy/remote_commands/device_command_reset_euicc_job.cc index e36d9102..408275d 100644 --- a/chrome/browser/ash/policy/remote_commands/device_command_reset_euicc_job.cc +++ b/chrome/browser/ash/policy/remote_commands/device_command_reset_euicc_job.cc
@@ -6,19 +6,35 @@ #include <utility> +#include "ash/public/cpp/notification_utils.h" +#include "ash/strings/grit/ash_strings.h" #include "base/bind.h" #include "base/memory/ptr_util.h" #include "base/syslog_logging.h" #include "base/threading/thread_task_runner_handle.h" +#include "chrome/browser/notifications/system_notification_helper.h" #include "chromeos/dbus/hermes/hermes_euicc_client.h" #include "chromeos/network/cellular_inhibitor.h" #include "chromeos/network/cellular_utils.h" #include "chromeos/network/network_handler.h" #include "components/policy/proto/device_management_backend.pb.h" #include "third_party/abseil-cpp/absl/types/optional.h" +#include "ui/base/l10n/l10n_util.h" +#include "ui/gfx/image/image.h" +#include "ui/message_center/public/cpp/notification.h" namespace policy { +namespace { + +constexpr char kNotifierESimPolicy[] = "policy.esim-policy"; + +} // namespace + +// static +const char DeviceCommandResetEuiccJob::kResetEuiccNotificationId[] = + "cros_reset_euicc"; + DeviceCommandResetEuiccJob::DeviceCommandResetEuiccJob() : DeviceCommandResetEuiccJob( chromeos::NetworkHandler::Get()->cellular_inhibitor()) {} @@ -50,8 +66,7 @@ return; } - // TODO(crbug.com/1231305) Trigger a notification if an eSIM network is - // active. + ShowResetEuiccNotification(); SYSLOG(INFO) << "Executing EUICC reset memory remote command"; cellular_inhibitor_->InhibitCellularScanning( chromeos::CellularInhibitor::InhibitReason::kResettingEuiccMemory, @@ -106,4 +121,24 @@ base::BindOnce(std::move(callback), /*result_payload=*/nullptr)); } +void DeviceCommandResetEuiccJob::ShowResetEuiccNotification() { + std::unique_ptr<message_center::Notification> notification = + ash::CreateSystemNotification( + message_center::NOTIFICATION_TYPE_SIMPLE, kResetEuiccNotificationId, + l10n_util::GetStringUTF16( + IDS_ASH_NETWORK_RESET_EUICC_NOTIFICATION_TITLE), + l10n_util::GetStringUTF16( + IDS_ASH_NETWORK_RESET_EUICC_NOTIFICATION_MESSAGE), + /*display_source=*/std::u16string(), /*origin_url=*/GURL(), + message_center::NotifierId( + message_center::NotifierType::SYSTEM_COMPONENT, + kNotifierESimPolicy), + message_center::RichNotificationData(), + base::MakeRefCounted<message_center::HandleNotificationClickDelegate>( + base::DoNothingAs<void()>()), + /*small_image=*/gfx::VectorIcon(), + message_center::SystemNotificationWarningLevel::NORMAL); + SystemNotificationHelper::GetInstance()->Display(*notification); +} + } // namespace policy
diff --git a/chrome/browser/ash/policy/remote_commands/device_command_reset_euicc_job.h b/chrome/browser/ash/policy/remote_commands/device_command_reset_euicc_job.h index 70abb81..6ff373b1 100644 --- a/chrome/browser/ash/policy/remote_commands/device_command_reset_euicc_job.h +++ b/chrome/browser/ash/policy/remote_commands/device_command_reset_euicc_job.h
@@ -36,6 +36,8 @@ static std::unique_ptr<DeviceCommandResetEuiccJob> CreateForTesting( chromeos::CellularInhibitor* cellular_inhbitor); + static const char kResetEuiccNotificationId[]; + // RemoteCommandJob: enterprise_management::RemoteCommand_Type GetType() const override; @@ -58,6 +60,7 @@ std::unique_ptr<chromeos::CellularInhibitor::InhibitLock> inhibit_lock, chromeos::HermesResponseStatus status); void RunResultCallback(CallbackWithResult callback); + void ShowResetEuiccNotification(); chromeos::CellularInhibitor* const cellular_inhibitor_; base::WeakPtrFactory<DeviceCommandResetEuiccJob> weak_ptr_factory_{this};
diff --git a/chrome/browser/ash/policy/remote_commands/device_command_reset_euicc_job_unittest.cc b/chrome/browser/ash/policy/remote_commands/device_command_reset_euicc_job_unittest.cc index fa8b54b5..63c726e 100644 --- a/chrome/browser/ash/policy/remote_commands/device_command_reset_euicc_job_unittest.cc +++ b/chrome/browser/ash/policy/remote_commands/device_command_reset_euicc_job_unittest.cc
@@ -4,7 +4,10 @@ #include "chrome/browser/ash/policy/remote_commands/device_command_reset_euicc_job.h" +#include "chrome/browser/notifications/notification_display_service_tester.h" +#include "chrome/browser/notifications/system_notification_helper.h" #include "chrome/test/base/chrome_ash_test_base.h" +#include "chrome/test/base/testing_browser_process.h" #include "chromeos/dbus/hermes/hermes_clients.h" #include "chromeos/dbus/hermes/hermes_euicc_client.h" #include "chromeos/dbus/hermes/hermes_manager_client.h" @@ -13,6 +16,7 @@ #include "chromeos/network/network_state_test_helper.h" #include "components/prefs/testing_pref_service.h" #include "testing/gtest/include/gtest/gtest.h" +#include "ui/message_center/public/cpp/notification.h" namespace policy { @@ -109,6 +113,10 @@ TEST_F(DeviceCommandResetEuiccJobTest, ResetEuicc) { base::RunLoop run_loop; + TestingBrowserProcess::GetGlobal()->SetSystemNotificationHelper( + std::make_unique<SystemNotificationHelper>()); + NotificationDisplayServiceTester tester(/*profile=*/nullptr); + std::unique_ptr<RemoteCommandJob> job = CreateResetEuiccJob(test_start_time_); EXPECT_TRUE( job->Run(base::Time::Now(), base::TimeTicks::Now(), @@ -117,10 +125,16 @@ RemoteCommandJob::Status::SUCCEEDED, /*expected_profile_count=*/0))); run_loop.Run(); + // Verify that the notification should be displayed. + EXPECT_TRUE(tester.GetNotification( + DeviceCommandResetEuiccJob::kResetEuiccNotificationId)); } TEST_F(DeviceCommandResetEuiccJobTest, ResetEuiccInhibitFailure) { chromeos::ShillManagerClient::Get()->GetTestInterface()->ClearDevices(); + TestingBrowserProcess::GetGlobal()->SetSystemNotificationHelper( + std::make_unique<SystemNotificationHelper>()); + NotificationDisplayServiceTester tester(/*profile=*/nullptr); base::RunLoop run_loop; std::unique_ptr<RemoteCommandJob> job = CreateResetEuiccJob(test_start_time_); EXPECT_TRUE( @@ -130,6 +144,9 @@ RemoteCommandJob::Status::FAILED, /*expected_profile_count=*/2))); run_loop.Run(); + // Verify that the notification should be displayed. + EXPECT_TRUE(tester.GetNotification( + DeviceCommandResetEuiccJob::kResetEuiccNotificationId)); } } // namespace policy
diff --git a/chrome/browser/ash/web_applications/personalization_app/chrome_personalization_app_ui_delegate.cc b/chrome/browser/ash/web_applications/personalization_app/chrome_personalization_app_ui_delegate.cc index 3e9bf0b7..6255045 100644 --- a/chrome/browser/ash/web_applications/personalization_app/chrome_personalization_app_ui_delegate.cc +++ b/chrome/browser/ash/web_applications/personalization_app/chrome_personalization_app_ui_delegate.cc
@@ -11,6 +11,7 @@ #include <string> #include <vector> +#include "ash/public/cpp/tablet_mode.h" #include "ash/public/cpp/wallpaper/online_wallpaper_params.h" #include "ash/public/cpp/wallpaper/wallpaper_controller.h" #include "ash/public/cpp/wallpaper/wallpaper_info.h" @@ -238,8 +239,13 @@ } } +void ChromePersonalizationAppUiDelegate::OnWallpaperPreviewEnded() { + ChromePersonalizationAppUiDelegate::OnWallpaperChanged(); +} + void ChromePersonalizationAppUiDelegate::SelectWallpaper( uint64_t image_asset_id, + bool preview_mode, SelectWallpaperCallback callback) { const auto& it = image_asset_id_map_.find(image_asset_id); @@ -259,8 +265,8 @@ ash::OnlineWallpaperParams( GetAccountId(), absl::make_optional(image_asset_id), GURL(it->second.image_url.spec()), it->second.collection_id, - ash::WallpaperLayout::WALLPAPER_LAYOUT_CENTER_CROPPED, - /*preview_mode=*/false, /*from_user=*/true, + ash::WallpaperLayout::WALLPAPER_LAYOUT_CENTER_CROPPED, preview_mode, + /*from_user=*/true, /*daily_refresh_enabled=*/false), base::BindOnce( &ChromePersonalizationAppUiDelegate::OnOnlineWallpaperSelected, @@ -269,6 +275,7 @@ void ChromePersonalizationAppUiDelegate::SelectLocalImage( const base::FilePath& path, + bool preview_mode, SelectLocalImageCallback callback) { if (local_images_.count(path) == 0) { mojo::ReportBadMessage("Invalid local image path selected"); @@ -280,8 +287,7 @@ WallpaperController::Get()->SetCustomWallpaper( GetAccountId(), path, - ash::WallpaperLayout::WALLPAPER_LAYOUT_CENTER_CROPPED, - /*preview_mode=*/false, + ash::WallpaperLayout::WALLPAPER_LAYOUT_CENTER_CROPPED, preview_mode, base::BindOnce(&ChromePersonalizationAppUiDelegate::OnLocalImageSelected, backend_weak_ptr_factory_.GetWeakPtr())); } @@ -317,6 +323,19 @@ backend_weak_ptr_factory_.GetWeakPtr())); } +void ChromePersonalizationAppUiDelegate::IsInTabletMode( + IsInTabletModeCallback callback) { + std::move(callback).Run(ash::TabletMode::IsInTabletMode()); +} + +void ChromePersonalizationAppUiDelegate::ConfirmPreviewWallpaper() { + WallpaperController::Get()->ConfirmPreviewWallpaper(); +} + +void ChromePersonalizationAppUiDelegate::CancelPreviewWallpaper() { + WallpaperController::Get()->CancelPreviewWallpaper(); +} + void ChromePersonalizationAppUiDelegate::OnFetchCollections( bool success, const std::vector<backdrop::Collection>& collections) {
diff --git a/chrome/browser/ash/web_applications/personalization_app/chrome_personalization_app_ui_delegate.h b/chrome/browser/ash/web_applications/personalization_app/chrome_personalization_app_ui_delegate.h index acf3a9d..cf11164 100644 --- a/chrome/browser/ash/web_applications/personalization_app/chrome_personalization_app_ui_delegate.h +++ b/chrome/browser/ash/web_applications/personalization_app/chrome_personalization_app_ui_delegate.h
@@ -91,11 +91,16 @@ // ash::WallpaperControllerObserver: void OnWallpaperChanged() override; + // ash::WallpaperControllerObserver: + void OnWallpaperPreviewEnded() override; + // chromeos::personalization_app::mojom::WallpaperProvider: void SelectWallpaper(uint64_t image_asset_id, + bool preview_mode, SelectWallpaperCallback callback) override; void SelectLocalImage(const base::FilePath& path, + bool preview_mode, SelectLocalImageCallback callback) override; void SetCustomWallpaperLayout(ash::WallpaperLayout layout) override; @@ -108,6 +113,12 @@ void UpdateDailyRefreshWallpaper( UpdateDailyRefreshWallpaperCallback callback) override; + void IsInTabletMode(IsInTabletModeCallback callback) override; + + void ConfirmPreviewWallpaper() override; + + void CancelPreviewWallpaper() override; + private: friend class ChromePersonalizationAppUiDelegateTest;
diff --git a/chrome/browser/ash/web_applications/personalization_app/chrome_personalization_app_ui_delegate_unittest.cc b/chrome/browser/ash/web_applications/personalization_app/chrome_personalization_app_ui_delegate_unittest.cc index 2e80d7d..d2d8341 100644 --- a/chrome/browser/ash/web_applications/personalization_app/chrome_personalization_app_ui_delegate_unittest.cc +++ b/chrome/browser/ash/web_applications/personalization_app/chrome_personalization_app_ui_delegate_unittest.cc
@@ -210,7 +210,7 @@ base::RunLoop loop; wallpaper_provider_remote()->get()->SelectWallpaper( - asset_id, + asset_id, /*preview_mode=*/false, base::BindLambdaForTesting([quit = loop.QuitClosure()](bool success) { EXPECT_TRUE(success); std::move(quit).Run(); @@ -229,6 +229,37 @@ test_wallpaper_controller()->wallpaper_info().value()); } +TEST_F(ChromePersonalizationAppUiDelegateTest, PreviewWallpaper) { + test_wallpaper_controller()->ClearCounts(); + + const uint64_t asset_id = 1; + + AddWallpaperImage(asset_id, /*image_info=*/{ + GURL("test_url"), + "collection_id", + }); + + base::RunLoop loop; + wallpaper_provider_remote()->get()->SelectWallpaper( + asset_id, /*preview_mode=*/true, + base::BindLambdaForTesting([quit = loop.QuitClosure()](bool success) { + EXPECT_TRUE(success); + std::move(quit).Run(); + })); + wallpaper_provider_remote()->FlushForTesting(); + loop.Run(); + + EXPECT_EQ(1, test_wallpaper_controller()->set_online_wallpaper_count()); + EXPECT_EQ( + ash::WallpaperInfo( + {AccountId::FromUserEmailGaiaId(kFakeTestEmail, kTestGaiaId), + absl::make_optional(asset_id), GURL("test_url"), "collection_id", + ash::WallpaperLayout::WALLPAPER_LAYOUT_CENTER_CROPPED, + /*preview_mode=*/true, /*from_user=*/true, + /*daily_refresh_enabled=*/false}), + test_wallpaper_controller()->wallpaper_info().value()); +} + TEST_F(ChromePersonalizationAppUiDelegateTest, ObserveWallpaperFiresWhenBound) { // This will create the data url referenced below in expectation. test_wallpaper_controller()->ShowWallpaperImage(
diff --git a/chrome/browser/browsing_data/counters/site_data_counting_helper.cc b/chrome/browser/browsing_data/counters/site_data_counting_helper.cc index 590a4bd..a1a26d7e 100644 --- a/chrome/browser/browsing_data/counters/site_data_counting_helper.cc +++ b/chrome/browser/browsing_data/counters/site_data_counting_helper.cc
@@ -10,7 +10,7 @@ #include "chrome/browser/profiles/profile.h" #include "components/browsing_data/content/browsing_data_helper.h" #include "components/content_settings/core/browser/host_content_settings_map.h" -#include "components/services/storage/public/cpp/buckets/bucket_info.h" +#include "components/services/storage/public/cpp/buckets/bucket_locator.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/dom_storage_context.h" @@ -157,11 +157,11 @@ } void SiteDataCountingHelper::GetQuotaBucketsCallback( - const std::set<storage::BucketInfo>& buckets, + const std::set<storage::BucketLocator>& buckets, blink::mojom::StorageType type) { DCHECK_CURRENTLY_ON(BrowserThread::IO); std::set<GURL> urls; - for (const storage::BucketInfo& bucket : buckets) + for (const storage::BucketLocator& bucket : buckets) urls.insert(bucket.storage_key.origin().GetURL()); content::GetUIThreadTaskRunner({})->PostTask( FROM_HERE,
diff --git a/chrome/browser/browsing_data/counters/site_data_counting_helper.h b/chrome/browser/browsing_data/counters/site_data_counting_helper.h index 3ee94de3..e968a4b 100644 --- a/chrome/browser/browsing_data/counters/site_data_counting_helper.h +++ b/chrome/browser/browsing_data/counters/site_data_counting_helper.h
@@ -25,7 +25,7 @@ namespace storage { class SpecialStoragePolicy; -struct BucketInfo; +struct BucketLocator; } // Helper class that counts the number of unique origins, that are affected by @@ -49,7 +49,7 @@ const scoped_refptr<storage::SpecialStoragePolicy>& special_storage_policy, const std::vector<content::StorageUsageInfo>& infos); - void GetQuotaBucketsCallback(const std::set<storage::BucketInfo>& buckets, + void GetQuotaBucketsCallback(const std::set<storage::BucketLocator>& buckets, blink::mojom::StorageType type); void SitesWithMediaLicensesCallback( const std::list<BrowsingDataMediaLicenseHelper::MediaLicenseInfo>&
diff --git a/chrome/browser/chrome_browser_interface_binders.cc b/chrome/browser/chrome_browser_interface_binders.cc index 98f9814f..ecc9ac2 100644 --- a/chrome/browser/chrome_browser_interface_binders.cc +++ b/chrome/browser/chrome_browser_interface_binders.cc
@@ -130,6 +130,8 @@ #include "chrome/browser/ui/webui/app_service_internals/app_service_internals_ui.h" #include "chrome/browser/ui/webui/downloads/downloads.mojom.h" #include "chrome/browser/ui/webui/downloads/downloads_ui.h" +#include "chrome/browser/ui/webui/enterprise_casting/enterprise_casting.mojom.h" +#include "chrome/browser/ui/webui/enterprise_casting/enterprise_casting_ui.h" #include "chrome/browser/ui/webui/realbox/realbox.mojom.h" #if !defined(OFFICIAL_BUILD) #include "chrome/browser/ui/webui/new_tab_page/foo/foo.mojom.h" // nogncheck crbug.com/1125897 @@ -204,8 +206,6 @@ #include "chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_ui.h" #include "chrome/browser/ui/webui/chromeos/emoji/emoji_picker.mojom.h" #include "chrome/browser/ui/webui/chromeos/emoji/emoji_ui.h" -#include "chrome/browser/ui/webui/chromeos/enterprise_casting/enterprise_casting.mojom.h" -#include "chrome/browser/ui/webui/chromeos/enterprise_casting/enterprise_casting_ui.h" #include "chrome/browser/ui/webui/chromeos/in_session_password_change/lock_screen_network_ui.h" #include "chrome/browser/ui/webui/chromeos/internet_config_dialog.h" #include "chrome/browser/ui/webui/chromeos/internet_detail_dialog.h" @@ -785,6 +785,10 @@ RegisterWebUIControllerInterfaceBinder< ::mojom::app_service_internals::AppServiceInternalsPageHandler, AppServiceInternalsUI>(map); + + RegisterWebUIControllerInterfaceBinder< + enterprise_casting::mojom::PageHandlerFactory, + EnterpriseCastingUI>(map); #endif // defined(OS_ANDROID) #if BUILDFLAG(ENABLE_WEBUI_TAB_STRIP) @@ -949,10 +953,6 @@ launcher_internals::mojom::PageHandlerFactory, chromeos::LauncherInternalsUI>(map); - RegisterWebUIControllerInterfaceBinder< - enterprise_casting::mojom::PageHandlerFactory, - chromeos::EnterpriseCastingUI>(map); - if (ash::features::IsBluetoothRevampEnabled()) { RegisterWebUIControllerInterfaceBinder< chromeos::bluetooth_config::mojom::CrosBluetoothConfig,
diff --git a/chrome/browser/content_creation/reactions/internal/android/java/res/layout/reaction_layout.xml b/chrome/browser/content_creation/reactions/internal/android/java/res/layout/reaction_layout.xml index efe7a772..e66f4864 100644 --- a/chrome/browser/content_creation/reactions/internal/android/java/res/layout/reaction_layout.xml +++ b/chrome/browser/content_creation/reactions/internal/android/java/res/layout/reaction_layout.xml
@@ -15,7 +15,7 @@ android:id="@+id/reaction_view" android:layout_width="match_parent" android:layout_height="match_parent" - android:padding="24dp" + android:padding="@dimen/reaction_padding" android:background="@drawable/border_inset"/> <org.chromium.ui.widget.ChromeImageButton
diff --git a/chrome/browser/content_creation/reactions/internal/android/java/res/values/dimens.xml b/chrome/browser/content_creation/reactions/internal/android/java/res/values/dimens.xml index b3493dc..667239d4 100644 --- a/chrome/browser/content_creation/reactions/internal/android/java/res/values/dimens.xml +++ b/chrome/browser/content_creation/reactions/internal/android/java/res/values/dimens.xml
@@ -8,6 +8,7 @@ <dimen name="button_size">24dp</dimen> <dimen name="border_inset">12dp</dimen> <dimen name="delete_icon_padding">3dp</dimen> + <dimen name="reaction_padding">24dp</dimen> <dimen name="rtl_auto_mirror_scale">1</dimen> <dimen name="toolbar_row_height">56dp</dimen> <dimen name="toolbar_total_height">112dp</dimen>
diff --git a/chrome/browser/content_creation/reactions/internal/android/java/src/org/chromium/chrome/browser/content_creation/reactions/scene/ReactionLayout.java b/chrome/browser/content_creation/reactions/internal/android/java/src/org/chromium/chrome/browser/content_creation/reactions/scene/ReactionLayout.java index 198a05a..be386a2 100644 --- a/chrome/browser/content_creation/reactions/internal/android/java/src/org/chromium/chrome/browser/content_creation/reactions/scene/ReactionLayout.java +++ b/chrome/browser/content_creation/reactions/internal/android/java/src/org/chromium/chrome/browser/content_creation/reactions/scene/ReactionLayout.java
@@ -8,6 +8,7 @@ import android.graphics.drawable.Drawable; import android.graphics.drawable.LayerDrawable; import android.util.AttributeSet; +import android.view.View; import android.widget.ImageView; import android.widget.RelativeLayout; @@ -16,13 +17,19 @@ import org.chromium.ui.widget.ChromeImageButton; class ReactionLayout extends RelativeLayout { + private final int mReactionPadding; + private ChromeImageButton mCopyButton; + private ChromeImageButton mDeleteButton; + private ChromeImageButton mAdjustButton; private Drawable mDrawable; private ImageView mReaction; private SceneEditorDelegate mSceneEditorDelegate; + private boolean mIsActive; public ReactionLayout(Context context, AttributeSet attrs) { super(context, attrs); + mReactionPadding = context.getResources().getDimensionPixelSize(R.dimen.reaction_padding); } /** @@ -33,9 +40,8 @@ void init(Drawable drawable, SceneEditorDelegate sceneEditorDelegate) { mDrawable = drawable; mSceneEditorDelegate = sceneEditorDelegate; - if (mReaction != null) { - mReaction.setImageDrawable(mDrawable); - } + mIsActive = true; + setUpReactionView(); } Drawable getReaction() { @@ -46,10 +52,32 @@ public void onFinishInflate() { super.onFinishInflate(); mReaction = findViewById(R.id.reaction_view); - if (mDrawable != null) { - mReaction.setImageDrawable(mDrawable); - } setUpCopyButton(); + mDeleteButton = findViewById(R.id.delete_button); + mAdjustButton = findViewById(R.id.adjust_button); + } + + void setActive(boolean isActive) { + if (mIsActive == isActive) return; + + mIsActive = isActive; + int visibility = mIsActive ? View.VISIBLE : View.GONE; + mCopyButton.setVisibility(visibility); + mDeleteButton.setVisibility(visibility); + mAdjustButton.setVisibility(visibility); + if (!mIsActive) { + mReaction.setBackground(null); + } else { + mReaction.setBackgroundResource(R.drawable.border_inset); + mReaction.setPadding( + mReactionPadding, mReactionPadding, mReactionPadding, mReactionPadding); + } + } + + private void setUpReactionView() { + mReaction.setImageDrawable(mDrawable); + mReaction.setOnClickListener( + view -> mSceneEditorDelegate.markActiveStatus(this, !mIsActive)); } private void setUpCopyButton() {
diff --git a/chrome/browser/content_creation/reactions/internal/android/java/src/org/chromium/chrome/browser/content_creation/reactions/scene/SceneCoordinator.java b/chrome/browser/content_creation/reactions/internal/android/java/src/org/chromium/chrome/browser/content_creation/reactions/scene/SceneCoordinator.java index 8d32bb3..73a00de 100644 --- a/chrome/browser/content_creation/reactions/internal/android/java/src/org/chromium/chrome/browser/content_creation/reactions/scene/SceneCoordinator.java +++ b/chrome/browser/content_creation/reactions/internal/android/java/src/org/chromium/chrome/browser/content_creation/reactions/scene/SceneCoordinator.java
@@ -28,6 +28,7 @@ private final Activity mActivity; private final Set<ReactionLayout> mReactionLayouts; + private ReactionLayout mActiveReaction; private RelativeLayout mSceneBackground; /** @@ -42,6 +43,8 @@ public void setSceneBackground(RelativeLayout sceneBackground) { mSceneBackground = sceneBackground; + mSceneBackground.setOnClickListener( + (view) -> { markActiveStatus(mActiveReaction, false); }); } public void addInitialReaction() { @@ -65,8 +68,14 @@ - res.getDimensionPixelSize(R.dimen.toolbar_total_height); lp.setMargins(leftPx, topPx, 0, 0); - mSceneBackground.addView(reactionLayout, lp); + addReaction(reactionLayout, lp); + } + + private void addReaction( + ReactionLayout reactionLayout, RelativeLayout.LayoutParams layoutParams) { + mSceneBackground.addView(reactionLayout, layoutParams); mReactionLayouts.add(reactionLayout); + markActiveStatus(reactionLayout, true); } // SceneEditorCallback implementation. @@ -89,10 +98,8 @@ int offsetPx = ViewUtils.dpToPx(mActivity, REACTION_OFFSET_DP); newLayoutParams.leftMargin = oldLayoutParams.leftMargin + offsetPx; newLayoutParams.topMargin = oldLayoutParams.topMargin + offsetPx; - newReactionLayout.setLayoutParams(newLayoutParams); - mSceneBackground.addView(newReactionLayout); - mReactionLayouts.add(newReactionLayout); + addReaction(newReactionLayout, newLayoutParams); } @Override @@ -103,6 +110,15 @@ @Override public void markActiveStatus(ReactionLayout reactionLayout, boolean isActive) { - // no-op for now + if (isActive) { + if (mActiveReaction != null) { + mActiveReaction.setActive(false); + } + reactionLayout.setActive(true); + mActiveReaction = reactionLayout; + } else if (mActiveReaction != null) { + mActiveReaction.setActive(false); + mActiveReaction = null; + } } }
diff --git a/chrome/browser/dev_ui/android/dev_ui_loader_throttle.cc b/chrome/browser/dev_ui/android/dev_ui_loader_throttle.cc index 02265a1..c8cd2f5 100644 --- a/chrome/browser/dev_ui/android/dev_ui_loader_throttle.cc +++ b/chrome/browser/dev_ui/android/dev_ui_loader_throttle.cc
@@ -64,8 +64,8 @@ host == chrome::kChromeUIWebApksHost || host == chrome::kChromeUIWebRtcLogsHost || host == content::kChromeUIAppCacheInternalsHost || + host == content::kChromeUIAttributionInternalsHost || host == content::kChromeUIBlobInternalsHost || - host == content::kChromeUIConversionInternalsHost || host == content::kChromeUIGpuHost || host == content::kChromeUIHistogramHost || host == content::kChromeUIIndexedDBInternalsHost ||
diff --git a/chrome/browser/devtools/devtools_window.cc b/chrome/browser/devtools/devtools_window.cc index ff31db1..699f1ef 100644 --- a/chrome/browser/devtools/devtools_window.cc +++ b/chrome/browser/devtools/devtools_window.cc
@@ -80,6 +80,11 @@ #include "ui/events/keycodes/keyboard_code_conversion.h" #include "ui/events/keycodes/keyboard_codes.h" +// This should be after all other #includes. +#if defined(_WINDOWS_) // Detect whether windows.h was included. +#include "base/win/windows_h_disallowed.h" +#endif // defined(_WINDOWS_) + using base::DictionaryValue; using blink::WebInputEvent; using content::BrowserThread;
diff --git a/chrome/browser/enterprise/connectors/device_trust/attestation/common/proto/device_trust_attestation_ca.proto b/chrome/browser/enterprise/connectors/device_trust/attestation/common/proto/device_trust_attestation_ca.proto index 8521c48d..3e679df 100644 --- a/chrome/browser/enterprise/connectors/device_trust/attestation/common/proto/device_trust_attestation_ca.proto +++ b/chrome/browser/enterprise/connectors/device_trust/attestation/common/proto/device_trust_attestation_ca.proto
@@ -124,9 +124,9 @@ // OS version (e.g. macOS 10.15.7) optional string os_version = 8; // IMEI - optional string imei = 9; + repeated string imei = 9; // MEID - optional string meid = 10; + repeated string meid = 10; // Hash of the EKPub certificate of the TPM on the device, if available. optional string tpm_hash = 11; // Is the disk encrypted
diff --git a/chrome/browser/enterprise/reporting/browser_report_generator_android.cc b/chrome/browser/enterprise/reporting/browser_report_generator_android.cc index 3d023e8..efea90a 100644 --- a/chrome/browser/enterprise/reporting/browser_report_generator_android.cc +++ b/chrome/browser/enterprise/reporting/browser_report_generator_android.cc
@@ -36,7 +36,7 @@ } std::vector<BrowserReportGenerator::ReportedProfileData> -BrowserReportGeneratorAndroid::GetReportedProfiles(ReportType report_type) { +BrowserReportGeneratorAndroid::GetReportedProfiles() { std::vector<BrowserReportGenerator::ReportedProfileData> reportedProfileData; ProfileManager* profile_manager = g_browser_process->profile_manager(); for (const auto* entry : profile_manager->GetProfileAttributesStorage() @@ -69,9 +69,4 @@ std::move(callback).Run(std::move(report)); } -void BrowserReportGeneratorAndroid::OnProfileInfoGenerated( - ReportType report_type) { - // Not used on Android because there is no throttling profiles. -} - } // namespace enterprise_reporting
diff --git a/chrome/browser/enterprise/reporting/browser_report_generator_android.h b/chrome/browser/enterprise/reporting/browser_report_generator_android.h index d609e618..bd653bc 100644 --- a/chrome/browser/enterprise/reporting/browser_report_generator_android.h +++ b/chrome/browser/enterprise/reporting/browser_report_generator_android.h
@@ -33,15 +33,14 @@ // BrowserReportGenerator::Delegate implementation std::string GetExecutablePath() override; version_info::Channel GetChannel() override; - std::vector<BrowserReportGenerator::ReportedProfileData> GetReportedProfiles( - ReportType report_type) override; + std::vector<BrowserReportGenerator::ReportedProfileData> GetReportedProfiles() + override; bool IsExtendedStableChannel() override; void GenerateBuildStateInfo( enterprise_management::BrowserReport* report) override; void GeneratePluginsIfNeeded( ReportCallback callback, std::unique_ptr<enterprise_management::BrowserReport> report) override; - void OnProfileInfoGenerated(ReportType report_type) override; }; } // namespace enterprise_reporting
diff --git a/chrome/browser/enterprise/reporting/browser_report_generator_desktop.cc b/chrome/browser/enterprise/reporting/browser_report_generator_desktop.cc index eeb46395..0d1c467e 100644 --- a/chrome/browser/enterprise/reporting/browser_report_generator_desktop.cc +++ b/chrome/browser/enterprise/reporting/browser_report_generator_desktop.cc
@@ -12,7 +12,6 @@ #include "build/build_config.h" #include "build/chromeos_buildflags.h" #include "chrome/browser/browser_process.h" -#include "chrome/browser/enterprise/reporting/extension_request/extension_request_report_throttler.h" #include "chrome/browser/profiles/profile_attributes_entry.h" #include "chrome/browser/profiles/profile_attributes_storage.h" #include "chrome/browser/profiles/profile_manager.h" @@ -51,19 +50,9 @@ } std::vector<BrowserReportGenerator::ReportedProfileData> -BrowserReportGeneratorDesktop::GetReportedProfiles(ReportType report_type) { +BrowserReportGeneratorDesktop::GetReportedProfiles() { std::vector<BrowserReportGenerator::ReportedProfileData> reportedProfileData; - bool is_extension_request_report = - (report_type == ReportType::kExtensionRequest); - - auto* throttler = ExtensionRequestReportThrottler::Get(); - if (is_extension_request_report && !throttler->IsEnabled()) - return reportedProfileData; - - base::flat_set<base::FilePath> extension_request_profile_paths = - throttler->GetProfiles(); - for (const auto* entry : g_browser_process->profile_manager() ->GetProfileAttributesStorage() .GetAllProfilesAttributes()) { @@ -76,10 +65,6 @@ #endif // BUILDFLAG(IS_CHROMEOS_ASH) base::FilePath profile_path = entry->GetPath(); - if (is_extension_request_report && - !extension_request_profile_paths.contains(profile_path)) { - continue; - } reportedProfileData.push_back( {profile_path.AsUTF8Unsafe(), base::UTF16ToUTF8(entry->GetName())}); @@ -116,14 +101,6 @@ #endif } -void BrowserReportGeneratorDesktop::OnProfileInfoGenerated( - ReportType report_type) { - auto* throttler = ExtensionRequestReportThrottler::Get(); - if (throttler->IsEnabled() && (report_type == ReportType::kExtensionRequest || - report_type == ReportType::kFull)) - throttler->ResetProfiles(); -} - void BrowserReportGeneratorDesktop::OnPluginsReady( ReportCallback callback, std::unique_ptr<em::BrowserReport> report,
diff --git a/chrome/browser/enterprise/reporting/browser_report_generator_desktop.h b/chrome/browser/enterprise/reporting/browser_report_generator_desktop.h index fcb68e53..1f4449b 100644 --- a/chrome/browser/enterprise/reporting/browser_report_generator_desktop.h +++ b/chrome/browser/enterprise/reporting/browser_report_generator_desktop.h
@@ -35,8 +35,8 @@ std::string GetExecutablePath() override; version_info::Channel GetChannel() override; - std::vector<BrowserReportGenerator::ReportedProfileData> GetReportedProfiles( - ReportType report_type) override; + std::vector<BrowserReportGenerator::ReportedProfileData> GetReportedProfiles() + override; bool IsExtendedStableChannel() override; // Adds the auto-updated version to the given report instance. void GenerateBuildStateInfo( @@ -44,7 +44,6 @@ void GeneratePluginsIfNeeded( ReportCallback callback, std::unique_ptr<enterprise_management::BrowserReport> report) override; - void OnProfileInfoGenerated(ReportType report_type) override; void OnPluginsReady( ReportCallback callback,
diff --git a/chrome/browser/enterprise/reporting/browser_report_generator_unittest.cc b/chrome/browser/enterprise/reporting/browser_report_generator_unittest.cc index 22738dd..5ace7d3 100644 --- a/chrome/browser/enterprise/reporting/browser_report_generator_unittest.cc +++ b/chrome/browser/enterprise/reporting/browser_report_generator_unittest.cc
@@ -27,7 +27,6 @@ #include "testing/gtest/include/gtest/gtest.h" #if !defined(OS_ANDROID) -#include "chrome/browser/enterprise/reporting/extension_request/extension_request_report_throttler_test.h" #include "chrome/browser/upgrade_detector/build_state.h" #endif // !defined(OS_ANDROID) @@ -203,13 +202,6 @@ } #if !defined(OS_ANDROID) - void InitializeExtensionRequest() { - throttler()->AddProfile( - profile_manager()->profiles_dir().AppendASCII(kProfileId)); - throttler()->AddProfile( - profile_manager()->profiles_dir().AppendASCII("deleted_profile")); - } - void InitializeUpdate() { auto* build_state = g_browser_process->GetBuildState(); build_state->SetUpdate(BuildState::UpdateType::kNormalUpdate, @@ -220,7 +212,6 @@ void GenerateAndVerify() { base::RunLoop run_loop; generator_.Generate( - ReportType::kFull, base::BindLambdaForTesting( [&run_loop](std::unique_ptr<em::BrowserReport> report) { EXPECT_TRUE(report.get()); @@ -237,38 +228,6 @@ run_loop.Run(); } -#if !defined(OS_ANDROID) - void GenerateExtensinRequestReportAndVerify( - const std::vector<std::string>& expected_request_profile_ids) { - base::RunLoop run_loop; - generator_.Generate( - ReportType::kExtensionRequest, - base::BindLambdaForTesting( - [&run_loop, &expected_request_profile_ids]( - std::unique_ptr<em::BrowserReport> report) { - EXPECT_TRUE(report.get()); - EXPECT_NE(std::string(), report->executable_path()); - EXPECT_FALSE(report->has_browser_version()); - EXPECT_FALSE(report->has_channel()); - EXPECT_FALSE(report->has_installed_browser_version()); - EXPECT_EQ(expected_request_profile_ids.size(), - static_cast<size_t>( - report->chrome_user_profile_infos_size())); - if (expected_request_profile_ids.size() > 0 && - report->chrome_user_profile_infos_size() > 0) { - EXPECT_EQ(expected_request_profile_ids[0], - report->chrome_user_profile_infos(0).id()); - } - EXPECT_EQ(0, report->plugins_size()); - run_loop.Quit(); - ExtensionRequestReportThrottler::Get()->Disable(); - })); - run_loop.Run(); - } - - ExtensionRequestReportThrottler* throttler() { return throttler_.Get(); } -#endif // !defined(OS_ANDROID) - TestingProfileManager* profile_manager() { return &profile_manager_; } private: @@ -277,9 +236,6 @@ TestingProfileManager profile_manager_; BrowserReportGenerator generator_; -#if !defined(OS_ANDROID) - ScopedExtensionRequestReportThrottler throttler_; -#endif // !defined(OS_ANDROID) }; TEST_F(BrowserReportGeneratorTest, GenerateBasicReport) { @@ -314,30 +270,4 @@ #endif // !defined(OS_ANDROID) && !BUILDFLAG(IS_CHROMEOS_ASH) && // BUILDFLAG(GOOGLE_CHROME_BRANDING) -#if !defined(OS_ANDROID) -TEST_F(BrowserReportGeneratorTest, ExtensionRequestOnly) { - InitializeUpdate(); - InitializeProfile(); - InitializeIrregularProfiles(); - InitializePlugin(); - InitializeExtensionRequest(); - GenerateExtensinRequestReportAndVerify({profile_manager() - ->profiles_dir() - .AppendASCII(kProfileId) - .AsUTF8Unsafe()}); -} - -// It's possible that the extension request report is delayed and by the time -// report is generated, the extension request report throttler is disabled. -TEST_F(BrowserReportGeneratorTest, ExtensionRequestOnlyWithoutThrottler) { - InitializeUpdate(); - InitializeProfile(); - InitializeIrregularProfiles(); - InitializePlugin(); - InitializeExtensionRequest(); - throttler()->Disable(); - GenerateExtensinRequestReportAndVerify({}); -} -#endif // !defined(OS_ANDROID) - } // namespace enterprise_reporting
diff --git a/chrome/browser/enterprise/reporting/profile_report_generator_unittest.cc b/chrome/browser/enterprise/reporting/profile_report_generator_unittest.cc index 8cdd742..83edc60 100644 --- a/chrome/browser/enterprise/reporting/profile_report_generator_unittest.cc +++ b/chrome/browser/enterprise/reporting/profile_report_generator_unittest.cc
@@ -119,7 +119,7 @@ const base::FilePath& path, const std::string& name) { std::unique_ptr<em::ChromeUserProfileInfo> report = - generator_.MaybeGenerate(path, name, ReportType::kFull); + generator_.MaybeGenerate(path, name); return report; } @@ -190,7 +190,7 @@ profile_manager()->profile_attributes_storage()->AddProfile( std::move(params)); std::unique_ptr<em::ChromeUserProfileInfo> response = - generator_.MaybeGenerate(profile_path, kIdleProfile, ReportType::kFull); + generator_.MaybeGenerate(profile_path, kIdleProfile); ASSERT_FALSE(response.get()); } @@ -319,80 +319,6 @@ report2->extension_requests(id).id()); } -TEST_F(ProfileReportGeneratorTest, ExtensionRequestOnlyReport) { - profile()->GetTestingPrefService()->SetManagedPref( - prefs::kCloudExtensionRequestEnabled, - std::make_unique<base::Value>(true)); - std::vector<std::string> ids = {kExtensionId}; - SetExtensionToPendingList(ids); - - IdentityTestEnvironmentProfileAdaptor identity_test_env_adaptor(profile()); - auto expected_info = - identity_test_env_adaptor.identity_test_env()->SetPrimaryAccount( - "test@mail.com", signin::ConsentLevel::kSync); - - auto report = generator_.MaybeGenerate(profile()->GetPath(), - profile()->GetProfileUserName(), - ReportType::kExtensionRequest); - - // Extension request and profile id are included. Profile name and sign in - // users info are included on CrOS only. - EXPECT_TRUE(report); - EXPECT_EQ(profile()->GetPath().AsUTF8Unsafe(), report->id()); -#if BUILDFLAG(IS_CHROMEOS_ASH) - EXPECT_EQ(profile()->GetProfileUserName(), report->name()); - EXPECT_TRUE(report->has_chrome_signed_in_user()); -#else - EXPECT_FALSE(report->has_name()); - EXPECT_FALSE(report->has_chrome_signed_in_user()); -#endif - ASSERT_EQ(1, report->extension_requests_size()); - EXPECT_EQ(kExtensionId, report->extension_requests(0).id()); - EXPECT_EQ(kFakeTime, report->extension_requests(0).request_timestamp()); - - // Policies and extensions info should not be added. - EXPECT_EQ(0, report->chrome_policies_size()); - EXPECT_EQ(0, report->extensions_size()); - EXPECT_EQ(0, report->policy_fetched_timestamps_size()); - EXPECT_TRUE(report->is_detail_available()); -} - -TEST_F(ProfileReportGeneratorTest, ExtensionRequestOnlyReportWithoutPolicy) { - profile()->GetTestingPrefService()->SetManagedPref( - prefs::kCloudExtensionRequestEnabled, - std::make_unique<base::Value>(false)); - IdentityTestEnvironmentProfileAdaptor identity_test_env_adaptor(profile()); - auto expected_info = - identity_test_env_adaptor.identity_test_env()->SetPrimaryAccount( - "test@mail.com", signin::ConsentLevel::kSync); - - auto report = generator_.MaybeGenerate(profile()->GetPath(), - profile()->GetProfileUserName(), - ReportType::kExtensionRequest); - EXPECT_TRUE(report); - EXPECT_EQ(0, report->extension_requests_size()); -} - -TEST_F(ProfileReportGeneratorTest, - ExtensionRequestOnlyReportWithoutAnyRequest) { - profile()->GetTestingPrefService()->SetManagedPref( - prefs::kCloudExtensionRequestEnabled, - std::make_unique<base::Value>(true)); - std::vector<std::string> ids; - SetExtensionToPendingList(ids); - - IdentityTestEnvironmentProfileAdaptor identity_test_env_adaptor(profile()); - auto expected_info = - identity_test_env_adaptor.identity_test_env()->SetPrimaryAccount( - "test@mail.com", signin::ConsentLevel::kSync); - - auto report = generator_.MaybeGenerate(profile()->GetPath(), - profile()->GetProfileUserName(), - ReportType::kExtensionRequest); - - EXPECT_TRUE(report); - EXPECT_EQ(0, report->extension_requests_size()); -} #endif // !defined(OS_ANDROID) } // namespace enterprise_reporting
diff --git a/chrome/browser/enterprise/reporting/report_generator_unittest.cc b/chrome/browser/enterprise/reporting/report_generator_unittest.cc index 8ecdd60..343cb4d8bc 100644 --- a/chrome/browser/enterprise/reporting/report_generator_unittest.cc +++ b/chrome/browser/enterprise/reporting/report_generator_unittest.cc
@@ -21,6 +21,7 @@ #include "chrome/test/base/testing_profile_manager.h" #include "components/account_id/account_id.h" #include "components/enterprise/browser/reporting/report_request_definition.h" +#include "components/enterprise/browser/reporting/report_type.h" #include "components/policy/core/common/cloud/cloud_policy_util.h" #include "content/public/common/webplugininfo.h" #include "content/public/test/browser_task_environment.h" @@ -463,30 +464,6 @@ profile_names, browser_report); } -TEST_F(ReportGeneratorTest, ExtensionRequestOnly) { - auto profile_names = CreateProfiles(/*number*/ 2, kActive); - CreatePlugin(); - - auto requests = GenerateRequests(ReportType::kExtensionRequest); - EXPECT_EQ(1u, requests.size()); - - auto* basic_request = requests[0].get(); - -#if !BUILDFLAG(IS_CHROMEOS_ASH) - EXPECT_FALSE(basic_request->has_computer_name()); - EXPECT_FALSE(basic_request->has_os_user_name()); - EXPECT_FALSE(basic_request->has_os_report()); - EXPECT_FALSE(basic_request->has_serial_number()); -#else - EXPECT_EQ(0, basic_request->android_app_infos_size()); -#endif // !BUILDFLAG(IS_CHROMEOS_ASH) - EXPECT_TRUE(basic_request->has_browser_report()); - - EXPECT_EQ(1, basic_request->partial_report_types_size()); - EXPECT_EQ(em::PartialReportType::EXTENSION_REQUEST, - basic_request->partial_report_types(0)); -} - #endif // defined(OS_ANDROID) #if BUILDFLAG(IS_CHROMEOS_ASH)
diff --git a/chrome/browser/enterprise/reporting/report_request_queue_generator_unittest.cc b/chrome/browser/enterprise/reporting/report_request_queue_generator_unittest.cc index 5105faa9..8db2c34a 100644 --- a/chrome/browser/enterprise/reporting/report_request_queue_generator_unittest.cc +++ b/chrome/browser/enterprise/reporting/report_request_queue_generator_unittest.cc
@@ -131,7 +131,6 @@ base::RunLoop run_loop; browser_report_generator_.Generate( - ReportType::kFull, base::BindLambdaForTesting( [&run_loop, &request](std::unique_ptr<em::BrowserReport> report) { request->set_allocated_browser_report(report.release()), @@ -146,7 +145,7 @@ const ReportRequest& request) { histogram_tester_ = std::make_unique<base::HistogramTester>(); std::queue<std::unique_ptr<ReportRequest>> requests = - report_request_queue_generator_.Generate(ReportType::kFull, request); + report_request_queue_generator_.Generate(request); std::vector<std::unique_ptr<ReportRequest>> result; while (!requests.empty()) { result.push_back(std::move(requests.front()));
diff --git a/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_browsertest.cc b/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_browsertest.cc index e73d07a3..93a37c3 100644 --- a/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_browsertest.cc +++ b/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_browsertest.cc
@@ -730,11 +730,9 @@ current_ruleset_count + expected_extensions_with_rulesets_count_change); size_t expected_enabled_rulesets_count = has_dynamic_ruleset ? 1 : 0; - size_t expected_manifest_rules_count = 0; size_t expected_manifest_enabled_rules_count = 0; for (const TestRulesetInfo& info : rulesets) { size_t rules_count = info.rules_value.GetList().size(); - expected_manifest_rules_count += rules_count; if (info.enabled) { expected_enabled_rulesets_count++;
diff --git a/chrome/browser/extensions/external_install_manager.cc b/chrome/browser/extensions/external_install_manager.cc index a09c9c5..4e791878 100644 --- a/chrome/browser/extensions/external_install_manager.cc +++ b/chrome/browser/extensions/external_install_manager.cc
@@ -10,9 +10,13 @@ #include "base/containers/contains.h" #include "base/metrics/histogram_macros.h" #include "chrome/app/chrome_command_ids.h" +#include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/extensions/extension_management.h" #include "chrome/browser/extensions/external_install_error.h" +#include "chrome/browser/profiles/profile.h" #include "components/version_info/version_info.h" +#include "content/public/browser/notification_details.h" +#include "content/public/browser/notification_source.h" #include "extensions/browser/extension_prefs.h" #include "extensions/common/extension.h" #include "extensions/common/feature_switch.h" @@ -66,6 +70,9 @@ DCHECK(browser_context_); extension_registry_observation_.Observe( ExtensionRegistry::Get(browser_context_)); + Profile* profile = Profile::FromBrowserContext(browser_context_); + registrar_.Add(this, extensions::NOTIFICATION_EXTENSION_REMOVED, + content::Source<Profile>(profile)); // Populate the set of unacknowledged external extensions now. We can't just // rely on IsUnacknowledgedExternalExtension() for cases like // OnExtensionLoaded(), since we need to examine the disable reasons, which @@ -260,9 +267,6 @@ content::BrowserContext* browser_context, const Extension* extension, extensions::UninstallReason reason) { - if (base::Contains(errors_, extension->id())) - RemoveExternalInstallError(extension->id()); - ExtensionManagement* settings = ExtensionManagementFactory::GetForBrowserContext(browser_context_); if (unacknowledged_ids_.erase(extension->id())) { @@ -289,4 +293,19 @@ !extension_prefs_->IsExternalExtensionAcknowledged(extension.id()); } +void ExternalInstallManager::Observe( + int type, + const content::NotificationSource& source, + const content::NotificationDetails& details) { + DCHECK_EQ(type, extensions::NOTIFICATION_EXTENSION_REMOVED); + // The error is invalidated if the extension has been loaded or removed. + // It's a shame we have to use the notification system (instead of the + // registry observer) for this, but the ExtensionUnloaded notification is + // not sent out if the extension is disabled (which it is here). + const std::string& extension_id = + content::Details<const Extension>(details).ptr()->id(); + if (base::Contains(errors_, extension_id)) + RemoveExternalInstallError(extension_id); +} + } // namespace extensions
diff --git a/chrome/browser/extensions/external_install_manager.h b/chrome/browser/extensions/external_install_manager.h index e0b56ef..5d98b6a 100644 --- a/chrome/browser/extensions/external_install_manager.h +++ b/chrome/browser/extensions/external_install_manager.h
@@ -10,12 +10,16 @@ #include "base/macros.h" #include "base/scoped_observation.h" +#include "content/public/browser/notification_observer.h" +#include "content/public/browser/notification_registrar.h" #include "extensions/browser/extension_registry.h" #include "extensions/browser/extension_registry_observer.h" #include "extensions/common/extension_id.h" namespace content { class BrowserContext; +class NotificationDetails; +class NotificationSource; } namespace extensions { @@ -23,7 +27,8 @@ class ExtensionPrefs; class ExternalInstallError; -class ExternalInstallManager : public ExtensionRegistryObserver { +class ExternalInstallManager : public ExtensionRegistryObserver, + public content::NotificationObserver { public: ExternalInstallManager(content::BrowserContext* browser_context, bool is_first_run); @@ -80,6 +85,11 @@ const Extension* extension, extensions::UninstallReason reason) override; + // content::NotificationObserver implementation. + void Observe(int type, + const content::NotificationSource& source, + const content::NotificationDetails& details) override; + // Adds a global error informing the user that an external extension was // installed. If |is_new_profile| is true, then this error is from the first // time our profile checked for new extensions. @@ -112,6 +122,8 @@ // The error that is currently showing an alert dialog/bubble. ExternalInstallError* currently_visible_install_alert_; + content::NotificationRegistrar registrar_; + base::ScopedObservation<ExtensionRegistry, ExtensionRegistryObserver> extension_registry_observation_{this}; };
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index 3531adb1..a68d111 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -1889,6 +1889,11 @@ "expiry_milestone": 98 }, { + "name": "enable-experimental-accessibility-switch-access-multistep-automation", + "owners": [ "akihiroota@google.com", "mschillaci@google.com" ], + "expiry_milestone": 98 + }, + { "name": "enable-experimental-accessibility-switch-access-setup-guide", "owners": ["ansatasi@google.com", "josiahk@google.com", "//ui/accessibility/OWNERS"], "expiry_milestone": 97 @@ -2386,6 +2391,11 @@ "expiry_milestone": 95 }, { + "name": "enable-phone-hub-call-notification", + "owners": [ "dhnishi", "andychou", "samchiu" ], + "expiry_milestone": 102 + }, + { "name": "enable-phone-hub-camera-roll", "owners": [ "mattwalliser", "jasonsun", "cros-cameraroll@google.com" ], "expiry_milestone": 97 @@ -3263,7 +3273,7 @@ { "name": "global-media-controls-modern-ui", "owners": [ "steimel", "media-dev" ], - "expiry_milestone": 95 + "expiry_milestone": 100 }, { "name": "global-media-controls-picture-in-picture", @@ -4994,12 +5004,12 @@ { "name" : "side-panel", "owners": [ "chrome-desktop-ui-sea@google.com", "pbos" ], - "expiry_milestone" : 96 + "expiry_milestone" : 101 }, { "name" : "side-panel-drag-and-drop", "owners": [ "chrome-desktop-ui-sea@google.com", "johntlee" ], - "expiry_milestone" : 96 + "expiry_milestone" : 101 }, { "name" : "side-search",
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index c3aea1d..240a3fbd 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -4657,6 +4657,13 @@ "Enable a setup guide to walk through the steps of initially configuring " "Switch Access."; +const char kExperimentalAccessibilitySwitchAccessMultistepAutomationName[] = + "Enable multistep automation for Switch Access."; +const char + kExperimentalAccessibilitySwitchAccessMultistepAutomationDescription[] = + "Enable multistep automation for Switch Access, which is a project for " + "the 2021 accessibility sprint."; + const char kMagnifierContinuousMouseFollowingModeSettingName[] = "Enable ability to choose continuous mouse following mode in Magnifier " "settings"; @@ -4936,6 +4943,11 @@ "If enabled, windows may be moved instead of scaled when resizing split " "view in tablet mode."; +const char kPhoneHubCallNotificationName[] = + "Incoming call notification in Phone Hub"; +const char kPhoneHubCallNotificationDescription[] = + "Enables the incoming/ongoing call feature in Phone Hub."; + const char kPhoneHubCameraRollName[] = "Camera Roll in Phone Hub"; const char kPhoneHubCameraRollDescription[] = "Enables the Camera Roll feature in Phone Hub, which allows users to "
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index d0af920..283d6b2 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -2668,6 +2668,11 @@ extern const char kExperimentalAccessibilitySwitchAccessSetupGuideName[]; extern const char kExperimentalAccessibilitySwitchAccessSetupGuideDescription[]; +extern const char + kExperimentalAccessibilitySwitchAccessMultistepAutomationName[]; +extern const char + kExperimentalAccessibilitySwitchAccessMultistepAutomationDescription[]; + extern const char kMagnifierContinuousMouseFollowingModeSettingName[]; extern const char kMagnifierContinuousMouseFollowingModeSettingDescription[]; @@ -2842,6 +2847,9 @@ extern const char kPerformantSplitViewResizing[]; extern const char kPerformantSplitViewResizingDescription[]; +extern const char kPhoneHubCallNotificationName[]; +extern const char kPhoneHubCallNotificationDescription[]; + extern const char kPhoneHubCameraRollName[]; extern const char kPhoneHubCameraRollDescription[];
diff --git a/chrome/browser/lacros/device_settings_lacros.cc b/chrome/browser/lacros/device_settings_lacros.cc new file mode 100644 index 0000000..08753563 --- /dev/null +++ b/chrome/browser/lacros/device_settings_lacros.cc
@@ -0,0 +1,44 @@ +// Copyright 2021 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/lacros/device_settings_lacros.h" + +#include <utility> + +#include "chromeos/crosapi/mojom/device_settings_service.mojom.h" +#include "chromeos/lacros/lacros_service.h" + +DeviceSettingsLacros::DeviceSettingsLacros() { + auto* lacros_service = chromeos::LacrosService::Get(); + device_settings_ = lacros_service->init_params()->device_settings.Clone(); + + // DeviceSettingsService is not available yet at the time when this is + // constructed. So, we post it as a task to be executed later. + base::ThreadTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::BindOnce(&DeviceSettingsLacros::Init, + weak_ptr_factory_.GetWeakPtr())); +} + +DeviceSettingsLacros::~DeviceSettingsLacros() = default; + +void DeviceSettingsLacros::Init() { + auto* lacros_service = chromeos::LacrosService::Get(); + if (!lacros_service->IsAvailable<crosapi::mojom::DeviceSettingsService>()) { + LOG(ERROR) << "DeviceSettingsService not available."; + return; + } + + lacros_service->GetRemote<crosapi::mojom::DeviceSettingsService>() + ->AddDeviceSettingsObserver( + receiver_.BindNewPipeAndPassRemoteWithVersion()); +} + +crosapi::mojom::DeviceSettings* DeviceSettingsLacros::GetDeviceSettings() { + return device_settings_.get(); +} + +void DeviceSettingsLacros::UpdateDeviceSettings( + crosapi::mojom::DeviceSettingsPtr device_settings) { + device_settings_ = std::move(device_settings); +}
diff --git a/chrome/browser/lacros/device_settings_lacros.h b/chrome/browser/lacros/device_settings_lacros.h new file mode 100644 index 0000000..cd09bb6 --- /dev/null +++ b/chrome/browser/lacros/device_settings_lacros.h
@@ -0,0 +1,37 @@ +// Copyright 2021 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_LACROS_DEVICE_SETTINGS_LACROS_H_ +#define CHROME_BROWSER_LACROS_DEVICE_SETTINGS_LACROS_H_ + +#include "base/memory/weak_ptr.h" +#include "chromeos/crosapi/mojom/device_settings_service.mojom.h" +#include "mojo/public/cpp/bindings/receiver.h" + +// The keeper of device settings needed for Lacros. Initializes with current +// value at startup and receives the updates from ash when the settings are +// changed. Lacros should use the device settings provided by this class when +// needs to use any device settings. +class DeviceSettingsLacros : public crosapi::mojom::DeviceSettingsObserver { + public: + DeviceSettingsLacros(); + DeviceSettingsLacros(const DeviceSettingsLacros&) = delete; + DeviceSettingsLacros& operator=(const DeviceSettingsLacros&) = delete; + ~DeviceSettingsLacros() override; + + crosapi::mojom::DeviceSettings* GetDeviceSettings(); + + // crosapi::mojom::DeviceSettingsObserver: + void UpdateDeviceSettings( + crosapi::mojom::DeviceSettingsPtr device_settings) override; + + private: + void Init(); + + crosapi::mojom::DeviceSettingsPtr device_settings_; + mojo::Receiver<crosapi::mojom::DeviceSettingsObserver> receiver_{this}; + base::WeakPtrFactory<DeviceSettingsLacros> weak_ptr_factory_{this}; +}; + +#endif // CHROME_BROWSER_LACROS_DEVICE_SETTINGS_LACROS_H_
diff --git a/chrome/browser/page_info/chrome_about_this_site_service_client.cc b/chrome/browser/page_info/chrome_about_this_site_service_client.cc index d78c39e..7475f5e 100644 --- a/chrome/browser/page_info/chrome_about_this_site_service_client.cc +++ b/chrome/browser/page_info/chrome_about_this_site_service_client.cc
@@ -23,7 +23,6 @@ ChromeAboutThisSiteServiceClient::CanApplyOptimization( const GURL& url, optimization_guide::OptimizationMetadata* optimization_metadata) { - // TODO(crbug.com/1250653): Call CanApplyOptimization method of - // `optimization_guide_decider_` after proto is added. - return optimization_guide::OptimizationGuideDecision::kUnknown; + return optimization_guide_decider_->CanApplyOptimization( + url, optimization_guide::proto::ABOUT_THIS_SITE, optimization_metadata); }
diff --git a/chrome/browser/password_manager/android/BUILD.gn b/chrome/browser/password_manager/android/BUILD.gn index 960a4a9..88d2aa7a 100644 --- a/chrome/browser/password_manager/android/BUILD.gn +++ b/chrome/browser/password_manager/android/BUILD.gn
@@ -93,11 +93,18 @@ "junit/src/org/chromium/chrome/browser/password_manager/settings/PasswordReauthenticationFragmentTest.java", "junit/src/org/chromium/chrome/browser/password_manager/settings/ReauthenticationManagerTest.java", ] + if (enable_chrome_android_internal) { + sources += [ "junit/src/org/chromium/chrome/browser/password_manager/PasswordStoreAndroidBackendBridgeTest.java" ] + } deps = [ ":java", + "//base:base_java", + "//base:base_java_test_support", "//base:base_junit_test_support", "//chrome/test/android:chrome_java_test_support", + "//components/sync/protocol:protocol_java", + "//third_party/android_deps:protobuf_lite_runtime_java", "//third_party/androidx:androidx_fragment_fragment_java", "//third_party/junit", ]
diff --git a/chrome/browser/password_manager/android/junit/src/org/chromium/chrome/browser/password_manager/PasswordStoreAndroidBackendBridgeTest.java b/chrome/browser/password_manager/android/junit/src/org/chromium/chrome/browser/password_manager/PasswordStoreAndroidBackendBridgeTest.java new file mode 100644 index 0000000..d05d860e --- /dev/null +++ b/chrome/browser/password_manager/android/junit/src/org/chromium/chrome/browser/password_manager/PasswordStoreAndroidBackendBridgeTest.java
@@ -0,0 +1,97 @@ +// Copyright 2021 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.password_manager; + +import static org.junit.Assert.assertNotNull; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.verify; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.annotation.Config; + +import org.chromium.base.Callback; +import org.chromium.base.test.BaseRobolectricTestRunner; +import org.chromium.base.test.util.Batch; +import org.chromium.base.test.util.JniMocker; +import org.chromium.components.sync.protocol.ListPasswordsResult; +import org.chromium.components.sync.protocol.PasswordSpecificsData; +import org.chromium.components.sync.protocol.PasswordWithLocalData; + +/** + * Tests that bridge calls as invoked by the password store reach the backend and return correctly. + */ +@RunWith(BaseRobolectricTestRunner.class) +@Config(manifest = Config.NONE) +@Batch(Batch.PER_CLASS) +public class PasswordStoreAndroidBackendBridgeTest { + private static final PasswordSpecificsData.Builder sTestProfile = + PasswordSpecificsData.newBuilder() + .setUsernameValue("Todd Tester") + .setUsernameElement("name") + .setPasswordElement("pwd") + .setOrigin("https://www.google.com/") + .setSignonRealm("https://accounts.google.com/signin") + .setPasswordValue("S3cr3t"); + private static final ListPasswordsResult.Builder sTestLogins = + ListPasswordsResult.newBuilder().addPasswordData( + PasswordWithLocalData.newBuilder().setPasswordSpecificsData(sTestProfile)); + private static final long sDummyNativePointer = 4; + + @Rule + public JniMocker mJniMocker = new JniMocker(); + + @Mock + private PasswordStoreAndroidBackendBridgeImpl.Natives mBridgeJniMock; + @Mock + private PasswordStoreAndroidBackend mBackendMock; + + private PasswordStoreAndroidBackendBridgeImpl mBackendBridge; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mJniMocker.mock(PasswordStoreAndroidBackendBridgeImplJni.TEST_HOOKS, mBridgeJniMock); + mBackendBridge = + new PasswordStoreAndroidBackendBridgeImpl(sDummyNativePointer, mBackendMock); + } + + @Test + public void testGetAllLoginsCallsBridgeOnSuccess() { + final int kTestTaskId = 1337; + + // Ensure the backend is called with a valid success callback. + mBackendBridge.getAllLogins(kTestTaskId); + ArgumentCaptor<Callback<byte[]>> successCallback = ArgumentCaptor.forClass(Callback.class); + verify(mBackendMock).getAllLogins(successCallback.capture(), any()); + assertNotNull(successCallback.getValue()); + + byte[] kExpectedList = sTestLogins.build().toByteArray(); + successCallback.getValue().onResult(kExpectedList); + verify(mBridgeJniMock) + .onCompleteWithLogins(sDummyNativePointer, kTestTaskId, kExpectedList); + } + + @Test + public void testGetAllLoginsCallsBridgeOnFailure() { + final int kTestTaskId = 42069; + + // Ensure the backend is called with a valid failure callback. + mBackendBridge.getAllLogins(kTestTaskId); + ArgumentCaptor<Callback<Exception>> failureCallback = + ArgumentCaptor.forClass(Callback.class); + verify(mBackendMock).getAllLogins(any(), failureCallback.capture()); + assertNotNull(failureCallback.getValue()); + + Exception kExpectedException = new Exception("Sample failure"); + failureCallback.getValue().onResult(kExpectedException); + verify(mBridgeJniMock).onError(sDummyNativePointer, kTestTaskId); + } +}
diff --git a/chrome/browser/performance_monitor/resource_coalition_mac_unittest.mm b/chrome/browser/performance_monitor/resource_coalition_mac_unittest.mm index f01f721..d3dfbe2 100644 --- a/chrome/browser/performance_monitor/resource_coalition_mac_unittest.mm +++ b/chrome/browser/performance_monitor/resource_coalition_mac_unittest.mm
@@ -9,6 +9,7 @@ #include <limits> #include <memory> +#include "base/compiler_specific.h" #include "base/containers/contains.h" #include "base/files/file_path.h" #include "base/logging.h" @@ -84,12 +85,13 @@ base::TimeTicks begin = base::TimeTicks::Now(); constexpr base::TimeDelta busy_time = base::Seconds(1); - double number = 1; + volatile double number = 1; while (base::TimeTicks::Now() < (begin + busy_time)) { for (int i = 0; i < 10000; ++i) { number *= base::RandDouble() / std::numeric_limits<double>::max() * 2; } } + ALLOW_UNUSED_LOCAL(number); auto sample = coalition.GetDataRate(); EXPECT_TRUE(sample.has_value());
diff --git a/chrome/browser/policy/chrome_browser_policy_connector.cc b/chrome/browser/policy/chrome_browser_policy_connector.cc index 78c8677..a76118a 100644 --- a/chrome/browser/policy/chrome_browser_policy_connector.cc +++ b/chrome/browser/policy/chrome_browser_policy_connector.cc
@@ -71,6 +71,7 @@ #endif #if BUILDFLAG(IS_CHROMEOS_LACROS) +#include "chrome/browser/lacros/device_settings_lacros.h" #include "components/policy/core/common/policy_loader_lacros.h" #endif @@ -125,6 +126,11 @@ bool ChromeBrowserPolicyConnector::IsMainUserManaged() const { return PolicyLoaderLacros::IsMainUserManaged(); } + +crosapi::mojom::DeviceSettings* +ChromeBrowserPolicyConnector::GetDeviceSettings() const { + return device_settings_->GetDeviceSettings(); +} #endif bool ChromeBrowserPolicyConnector::IsDeviceEnterpriseManaged() const { @@ -226,6 +232,10 @@ MaybeCreateCloudPolicyManager(&providers); #endif // !BUILDFLAG(IS_CHROMEOS_ASH) +#if BUILDFLAG(IS_CHROMEOS_LACROS) + device_settings_ = std::make_unique<DeviceSettingsLacros>(); +#endif // BUILDFLAG(IS_CHROMEOS_LACROS) + std::unique_ptr<CommandLinePolicyProvider> command_line_provider = CommandLinePolicyProvider::CreateIfAllowed( *base::CommandLine::ForCurrentProcess(), chrome::GetChannel());
diff --git a/chrome/browser/policy/chrome_browser_policy_connector.h b/chrome/browser/policy/chrome_browser_policy_connector.h index f659492..22d3a922 100644 --- a/chrome/browser/policy/chrome_browser_policy_connector.h +++ b/chrome/browser/policy/chrome_browser_policy_connector.h
@@ -23,6 +23,10 @@ #include "components/policy/core/browser/android/policy_cache_updater_android.h" #endif +#if BUILDFLAG(IS_CHROMEOS_LACROS) +#include "chrome/browser/lacros/device_settings_lacros.h" +#endif // BUILDFLAG(IS_CHROMEOS_LACROS) + class PrefService; namespace policy { @@ -110,6 +114,9 @@ // Checks if the main / primary user is managed or not. // TODO(crbug/1245077): Remove once Lacros handles all profiles the same way. bool IsMainUserManaged() const; + + // The device settings used in Lacros. + crosapi::mojom::DeviceSettings* GetDeviceSettings() const; #endif protected: @@ -167,6 +174,10 @@ // Owned by base class. ConfigurationPolicyProvider* command_line_provider_ = nullptr; +#if BUILDFLAG(IS_CHROMEOS_LACROS) + std::unique_ptr<DeviceSettingsLacros> device_settings_ = nullptr; +#endif + // Holds a callback to |ChromeBrowserCloudManagementController::Init| so that // its execution can be deferred until an enrollment token is available. base::OnceClosure deferred_init_callback_;
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc index d721794..4230f5a 100644 --- a/chrome/browser/prefs/browser_prefs.cc +++ b/chrome/browser/prefs/browser_prefs.cc
@@ -993,6 +993,8 @@ crosapi::browser_util::RegisterLocalStatePrefs(registry); chromeos::CupsPrintersManager::RegisterLocalStatePrefs(registry); ash::BrowserDataMigrator::RegisterLocalStatePrefs(registry); + chromeos::bluetooth_config::DeviceNameManagerImpl::RegisterLocalStatePrefs( + registry); ash::DemoModeDetector::RegisterPrefs(registry); ash::DemoModeResourcesRemover::RegisterLocalStatePrefs(registry); ash::DemoSession::RegisterLocalStatePrefs(registry); @@ -1320,7 +1322,6 @@ ash::ClientAppMetadataProviderService::RegisterProfilePrefs(registry); chromeos::CupsPrintersManager::RegisterProfilePrefs(registry); chromeos::device_sync::RegisterProfilePrefs(registry); - chromeos::bluetooth_config::DeviceNameManagerImpl::RegisterPrefs(registry); ash::FamilyUserChromeActivityMetrics::RegisterProfilePrefs(registry); ash::FamilyUserMetricsService::RegisterProfilePrefs(registry); ash::FamilyUserSessionMetrics::RegisterProfilePrefs(registry);
diff --git a/chrome/browser/printing/print_browsertest.cc b/chrome/browser/printing/print_browsertest.cc index a6cec98..b030a50 100644 --- a/chrome/browser/printing/print_browsertest.cc +++ b/chrome/browser/printing/print_browsertest.cc
@@ -1394,7 +1394,7 @@ const char kScript[] = R"( const button = document.getElementsByTagName('print-preview-app')[0] .$['previewArea'] - .$$('iframe') + .shadowRoot.querySelector('iframe') .contentDocument.querySelector('pdf-viewer-pp') .shadowRoot.querySelector('#zoom-toolbar') .$['zoom-out-button'];
diff --git a/chrome/browser/privacy_review/android/BUILD.gn b/chrome/browser/privacy_review/android/BUILD.gn index 9272f679..94eb86f 100644 --- a/chrome/browser/privacy_review/android/BUILD.gn +++ b/chrome/browser/privacy_review/android/BUILD.gn
@@ -15,11 +15,15 @@ android_resources("java_resources") { sources = [ + "java/res/drawable/privacy_review_illustration.xml", "java/res/layout/privacy_review_dialog.xml", + "java/res/layout/privacy_review_welcome.xml", "java/res/menu/privacy_review_toolbar_menu.xml", + "java/res/values/dimens.xml", ] deps = [ "//chrome/browser/ui/android/strings:ui_strings_grd", "//components/browser_ui/styles/android:java_resources", + "//components/browser_ui/widget/android:java_resources", ] }
diff --git a/chrome/browser/privacy_review/android/java/res/drawable/privacy_review_illustration.xml b/chrome/browser/privacy_review/android/java/res/drawable/privacy_review_illustration.xml new file mode 100644 index 0000000..c1792d3 --- /dev/null +++ b/chrome/browser/privacy_review/android/java/res/drawable/privacy_review_illustration.xml
@@ -0,0 +1,97 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright 2021 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. +--> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + tools:targetApi="21" + tools:ignore="VectorRaster" + android:width="258dp" + android:height="144dp" + android:viewportWidth="258" + android:viewportHeight="144"> + <path + android:pathData="M0,141.822H257.759" + android:strokeWidth="3.00427" + android:fillColor="#00000000" + android:strokeColor="#E8EAED"/> + <path + android:pathData="M185.577,54.163L175.521,45.238C174.426,44.266 174.329,42.598 175.3,41.503C176.271,40.408 177.94,40.311 179.035,41.283L189.09,50.208C190.185,51.179 190.282,52.848 189.311,53.943C188.34,55.037 186.671,55.134 185.577,54.163Z" + android:fillColor="#CF8D66"/> + <path + android:pathData="M204.549,136.463C217.49,136.463 227.98,125.973 227.98,113.032C227.98,100.092 217.49,89.601 204.549,89.601C191.609,89.601 181.118,100.092 181.118,113.032C181.118,125.973 191.609,136.463 204.549,136.463Z" + android:strokeWidth="7.00996" + android:fillColor="#00000000" + android:strokeColor="#DADCE0"/> + <path + android:pathData="M204.549,113.032L191.739,57.659H183.714" + android:strokeLineJoin="round" + android:strokeWidth="5.00711" + android:fillColor="#00000000" + android:strokeColor="#FBBC04" + android:strokeLineCap="round"/> + <path + android:pathData="M130.477,19.908L150.236,9.959L128.014,2.746C127.405,3.673 126.902,4.688 126.531,5.791C124.809,11.018 126.549,16.545 130.477,19.908Z" + android:fillColor="#3C4043"/> + <path + android:pathData="M140.163,63.054L160.971,79.74L147.729,104.698" + android:strokeLineJoin="round" + android:strokeWidth="20.0285" + android:fillColor="#00000000" + android:strokeColor="#174EA6"/> + <path + android:pathData="M129.674,113.032H68.024" + android:strokeWidth="5.00711" + android:fillColor="#00000000" + android:strokeColor="#DADCE0"/> + <path + android:pathData="M86.652,77.206H29.779V114.824H86.652V77.206Z" + android:fillColor="#5BB974"/> + <path + android:pathData="M119.821,136.463C132.762,136.463 143.252,125.973 143.252,113.032C143.252,100.092 132.762,89.601 119.821,89.601C106.881,89.601 96.39,100.092 96.39,113.032C96.39,125.973 106.881,136.463 119.821,136.463Z" + android:strokeWidth="7.00996" + android:fillColor="#00000000" + android:strokeColor="#DADCE0"/> + <path + android:pathData="M58.216,136.463C66.987,136.463 74.098,129.352 74.098,120.581C74.098,111.809 66.987,104.698 58.216,104.698C49.444,104.698 42.333,111.809 42.333,120.581C42.333,129.352 49.444,136.463 58.216,136.463Z" + android:strokeWidth="7.00996" + android:fillColor="#00000000" + android:strokeColor="#DADCE0"/> + <path + android:pathData="M147.367,113.032H119.822L144.515,72.191H194.811" + android:strokeLineJoin="round" + android:strokeWidth="5.00711" + android:fillColor="#00000000" + android:strokeColor="#FBBC04"/> + <path + android:pathData="M196.48,78.124L156.787,113.032" + android:strokeLineJoin="round" + android:strokeWidth="5.00711" + android:fillColor="#00000000" + android:strokeColor="#FBBC04"/> + <path + android:pathData="M152.346,112.344L157.14,111.514C157.14,111.514 157.043,115.61 160.353,117.005C162.198,117.782 164.838,117.941 166.816,117.923C168.405,117.906 169.765,119.027 170.038,120.572L170.126,121.102L151.816,121.022L152.346,112.344Z" + android:fillColor="#DADCE0"/> + <path + android:pathData="M153.591,14.108C157.486,14.108 160.645,10.95 160.645,7.054C160.645,3.158 157.486,0 153.591,0C149.695,0 146.537,3.158 146.537,7.054C146.537,10.95 149.695,14.108 153.591,14.108Z" + android:fillColor="#CF8D66"/> + <path + android:pathData="M146.546,20.235L175.918,46.059" + android:strokeLineJoin="round" + android:strokeWidth="16.0228" + android:fillColor="#00000000" + android:strokeColor="#5BB974"/> + <path + android:pathData="M131.316,53.907L143.261,114.895H158.367L147.04,55.867L131.316,53.907Z" + android:fillColor="#1967D2"/> + <path + android:pathData="M155.807,0.362C152.108,-0.856 148.126,1.148 146.899,4.847C146.166,7.072 146.607,9.402 147.879,11.177L160.309,4.926C159.647,2.843 158.04,1.095 155.807,0.362Z" + android:fillColor="#3C4043"/> + <path + android:pathData="M150.571,15.891C149.838,16.757 118.877,46.721 118.877,46.721C118.877,46.721 123.9,53.766 134.212,57.174C145.292,60.838 155.392,60.838 155.392,60.838L150.571,15.891Z" + android:fillColor="#5BB974"/> + <path + android:pathData="M71.344,72.191H45.079C40.806,72.191 37.336,68.73 37.336,64.449V38.192C37.336,33.919 40.797,30.45 45.079,30.45H71.344C75.617,30.45 79.087,33.91 79.087,38.192V64.457C79.087,68.73 75.617,72.191 71.344,72.191Z" + android:fillColor="#D2E3FC"/> +</vector>
diff --git a/chrome/browser/privacy_review/android/java/res/layout/privacy_review_dialog.xml b/chrome/browser/privacy_review/android/java/res/layout/privacy_review_dialog.xml index 5433f090..1861ccf 100644 --- a/chrome/browser/privacy_review/android/java/res/layout/privacy_review_dialog.xml +++ b/chrome/browser/privacy_review/android/java/res/layout/privacy_review_dialog.xml
@@ -12,13 +12,18 @@ <com.google.android.material.appbar.AppBarLayout android:id="@+id/app_bar_layout" android:layout_width="match_parent" - android:layout_height="wrap_content" - android:fitsSystemWindows="true" - app:liftOnScroll="true"> + android:layout_height="wrap_content"> <com.google.android.material.appbar.MaterialToolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="@dimen/toolbar_height_no_shadow"/> </com.google.android.material.appbar.AppBarLayout> + + <FrameLayout + android:id="@+id/dialog_content" + android:layout_width="match_parent" + android:layout_height="match_parent" + app:layout_behavior="@string/appbar_scrolling_view_behavior"> + </FrameLayout> </androidx.coordinatorlayout.widget.CoordinatorLayout>
diff --git a/chrome/browser/privacy_review/android/java/res/layout/privacy_review_welcome.xml b/chrome/browser/privacy_review/android/java/res/layout/privacy_review_welcome.xml new file mode 100644 index 0000000..8e25a08 --- /dev/null +++ b/chrome/browser/privacy_review/android/java/res/layout/privacy_review_welcome.xml
@@ -0,0 +1,72 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright 2021 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. --> + +<LinearLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical"> + + <ScrollView + android:id="@+id/scroll_view" + android:layout_width="match_parent" + android:layout_height="wrap_content"> + + <LinearLayout + android:id="@+id/welcome_main_layout" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:animateLayoutChanges="true" + android:gravity="center_horizontal" + android:orientation="vertical"> + + <ImageView + android:id="@+id/image" + android:layout_marginTop="32dp" + android:layout_marginBottom="32dp" + android:layout_height="@dimen/privacy_review_illustration_height" + android:layout_width="@dimen/privacy_review_illustration_width" + android:src="@drawable/privacy_review_illustration" + android:importantForAccessibility="no" /> + + <TextView + android:id="@+id/welcome_title" + android:layout_margin="16dp" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/privacy_review_welcome_title" + style="@style/TextAppearance.Headline.Primary" /> + + <TextView + android:id="@+id/welcome_description" + android:layout_margin="16dp" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text="@string/privacy_review_welcome_description" + style="@style/TextAppearance.TextLarge.Secondary" /> + + </LinearLayout> + + </ScrollView> + + <LinearLayout + android:orientation="vertical" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:gravity="bottom|center"> + + <org.chromium.ui.widget.ButtonCompat + android:id="@+id/start_button" + android:focusable="true" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginBottom="16dp" + android:layout_marginLeft="16dp" + android:layout_marginRight="16dp" + android:text="@string/privacy_review_start_button" + style="@style/FilledButton.Flat" /> + </LinearLayout> + +</LinearLayout>
diff --git a/chrome/browser/privacy_review/android/java/res/values/dimens.xml b/chrome/browser/privacy_review/android/java/res/values/dimens.xml new file mode 100644 index 0000000..34dd5ab --- /dev/null +++ b/chrome/browser/privacy_review/android/java/res/values/dimens.xml
@@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright 2021 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. --> + +<resources> + <dimen name="privacy_review_illustration_height">120dp</dimen> + <dimen name="privacy_review_illustration_width">215dp</dimen> +</resources>
diff --git a/chrome/browser/privacy_review/android/java/src/org/chromium/chrome/browser/privacy_review/PrivacyReviewDialog.java b/chrome/browser/privacy_review/android/java/src/org/chromium/chrome/browser/privacy_review/PrivacyReviewDialog.java index d0c7459..b741d37c 100644 --- a/chrome/browser/privacy_review/android/java/src/org/chromium/chrome/browser/privacy_review/PrivacyReviewDialog.java +++ b/chrome/browser/privacy_review/android/java/src/org/chromium/chrome/browser/privacy_review/PrivacyReviewDialog.java
@@ -4,18 +4,19 @@ package org.chromium.chrome.browser.privacy_review; +import android.app.Dialog; import android.content.Context; import android.view.LayoutInflater; import android.view.MenuItem; import android.view.View; +import android.widget.FrameLayout; -import androidx.appcompat.app.AlertDialog; import androidx.appcompat.widget.Toolbar; /** * UI for the Privacy Review dialog in Privacy and security settings. */ -public class PrivacyReviewDialog extends AlertDialog { +public class PrivacyReviewDialog extends Dialog { public PrivacyReviewDialog(Context context) { super(context, R.style.ThemeOverlay_BrowserUI_Fullscreen); View view = LayoutInflater.from(context).inflate(R.layout.privacy_review_dialog, null); @@ -24,7 +25,10 @@ toolbar.inflateMenu(R.menu.privacy_review_toolbar_menu); toolbar.setOnMenuItemClickListener(this::onMenuItemClick); - setView(view); + FrameLayout content = view.findViewById(R.id.dialog_content); + LayoutInflater.from(context).inflate(R.layout.privacy_review_welcome, content); + + setContentView(view); } private boolean onMenuItemClick(MenuItem menuItem) {
diff --git a/chrome/browser/profiles/profile_impl.cc b/chrome/browser/profiles/profile_impl.cc index 7c563a81b..35b58c18 100644 --- a/chrome/browser/profiles/profile_impl.cc +++ b/chrome/browser/profiles/profile_impl.cc
@@ -601,9 +601,10 @@ user_policy_provider_->Init(schema_registry_service_->registry()); policy_provider = user_policy_provider_.get(); user_cloud_policy_manager = nullptr; - } else -#endif // BUILDFLAG(IS_CHROMEOS_LACROS) + } else { +#else { +#endif // BUILDFLAG(IS_CHROMEOS_LACROS) user_cloud_policy_manager_ = CreateUserCloudPolicyManager( GetPath(), GetPolicySchemaRegistryService()->registry(), force_immediate_policy_load, io_task_runner_); @@ -876,13 +877,17 @@ // Destroy all OTR profiles and their profile services first. std::vector<Profile*> raw_otr_profiles; +#if BUILDFLAG(ENABLE_EXTENSIONS) bool primary_otr_available = false; +#endif // Get a list of existing OTR profiles since |off_the_record_profile_| might // be modified after the call to |DestroyProfileNow|. for (auto& otr_profile : otr_profiles_) { raw_otr_profiles.push_back(otr_profile.second.get()); +#if BUILDFLAG(ENABLE_EXTENSIONS) primary_otr_available |= (otr_profile.first == OTRProfileID::PrimaryID()); +#endif } for (Profile* otr_profile : raw_otr_profiles)
diff --git a/chrome/browser/resources/BUILD.gn b/chrome/browser/resources/BUILD.gn index 312b52e..4d890ed 100644 --- a/chrome/browser/resources/BUILD.gn +++ b/chrome/browser/resources/BUILD.gn
@@ -30,6 +30,7 @@ "commander:resources", "download_shelf:resources", "downloads:resources", + "enterprise_casting:resources", "federated_learning:resources", "feedback_webui:resources", "gaia_auth_host:resources", @@ -59,7 +60,6 @@ "chromeos/accessibility:build", "chromeos/audio:resources", "chromeos/emoji_picker:resources", - "chromeos/enterprise_casting:resources", "chromeos/launcher_internals:resources", "chromeos/login:conditional_resources", "chromeos/login:unconditional_resources",
diff --git a/chrome/browser/resources/chromeos/enterprise_casting/tsconfig_base.json b/chrome/browser/resources/chromeos/enterprise_casting/tsconfig_base.json deleted file mode 100644 index 5502828..0000000 --- a/chrome/browser/resources/chromeos/enterprise_casting/tsconfig_base.json +++ /dev/null
@@ -1,6 +0,0 @@ -{ - "extends": "../../../../../tools/typescript/tsconfig_base.json", - "compilerOptions": { - "allowJs": true - } -}
diff --git a/chrome/browser/resources/chromeos/enterprise_casting/BUILD.gn b/chrome/browser/resources/enterprise_casting/BUILD.gn similarity index 87% rename from chrome/browser/resources/chromeos/enterprise_casting/BUILD.gn rename to chrome/browser/resources/enterprise_casting/BUILD.gn index 6454fc2..86e4be3 100644 --- a/chrome/browser/resources/chromeos/enterprise_casting/BUILD.gn +++ b/chrome/browser/resources/enterprise_casting/BUILD.gn
@@ -7,7 +7,7 @@ import("//tools/typescript/ts_library.gni") import("//ui/webui/resources/tools/generate_grd.gni") -assert(is_chromeos, "enterprise_casting is Chrome OS only.") +assert(!is_android, "enterprise_casting is not for android.") resources_grd_file = "$target_gen_dir/resources.grd" @@ -21,8 +21,10 @@ } copy("copy_mojo") { - deps = [ "//chrome/browser/ui/webui/chromeos/enterprise_casting:mojo_bindings_webui_js" ] - mojom_folder = "$root_gen_dir/mojom-webui/chrome/browser/ui/webui/chromeos/enterprise_casting/" + deps = + [ "//chrome/browser/ui/webui/enterprise_casting:mojo_bindings_webui_js" ] + mojom_folder = + "$root_gen_dir/mojom-webui/chrome/browser/ui/webui/enterprise_casting/" sources = [ "$mojom_folder/enterprise_casting.mojom-webui.js" ] outputs = [ "$target_gen_dir/{{source_file_part}}" ] }
diff --git a/chrome/browser/resources/chromeos/enterprise_casting/OWNERS b/chrome/browser/resources/enterprise_casting/OWNERS similarity index 100% rename from chrome/browser/resources/chromeos/enterprise_casting/OWNERS rename to chrome/browser/resources/enterprise_casting/OWNERS
diff --git a/chrome/browser/resources/chromeos/enterprise_casting/browser_proxy.ts b/chrome/browser/resources/enterprise_casting/browser_proxy.ts similarity index 100% rename from chrome/browser/resources/chromeos/enterprise_casting/browser_proxy.ts rename to chrome/browser/resources/enterprise_casting/browser_proxy.ts
diff --git a/chrome/browser/resources/chromeos/enterprise_casting/enterprise_casting.html b/chrome/browser/resources/enterprise_casting/enterprise_casting.html similarity index 100% rename from chrome/browser/resources/chromeos/enterprise_casting/enterprise_casting.html rename to chrome/browser/resources/enterprise_casting/enterprise_casting.html
diff --git a/chrome/browser/resources/chromeos/enterprise_casting/enterprise_casting.ts b/chrome/browser/resources/enterprise_casting/enterprise_casting.ts similarity index 100% rename from chrome/browser/resources/chromeos/enterprise_casting/enterprise_casting.ts rename to chrome/browser/resources/enterprise_casting/enterprise_casting.ts
diff --git a/chrome/browser/resources/chromeos/enterprise_casting/index.html b/chrome/browser/resources/enterprise_casting/index.html similarity index 100% rename from chrome/browser/resources/chromeos/enterprise_casting/index.html rename to chrome/browser/resources/enterprise_casting/index.html
diff --git a/chrome/browser/resources/enterprise_casting/tsconfig_base.json b/chrome/browser/resources/enterprise_casting/tsconfig_base.json new file mode 100644 index 0000000..99a81eca --- /dev/null +++ b/chrome/browser/resources/enterprise_casting/tsconfig_base.json
@@ -0,0 +1,6 @@ +{ + "extends": "../../../../tools/typescript/tsconfig_base.json", + "compilerOptions": { + "allowJs": true + } +}
diff --git a/chrome/browser/resources/print_preview/data/document_info.ts b/chrome/browser/resources/print_preview/data/document_info.ts index 754b83a..ece9937 100644 --- a/chrome/browser/resources/print_preview/data/document_info.ts +++ b/chrome/browser/resources/print_preview/data/document_info.ts
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import {WebUIListenerBehavior} from 'chrome://resources/js/web_ui_listener_behavior.m.js'; -import {mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {WebUIListenerMixin} from 'chrome://resources/js/web_ui_listener_mixin.js'; +import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {Coordinate2d} from './coordinate2d.js'; import {CustomMarginsOrientation, Margins} from './margins.js'; @@ -34,9 +34,7 @@ printableAreaHeight: number, }; -const PrintPreviewDocumentInfoElementBase = - mixinBehaviors([WebUIListenerBehavior], PolymerElement) as - {new (): PolymerElement & WebUIListenerBehavior}; +const PrintPreviewDocumentInfoElementBase = WebUIListenerMixin(PolymerElement); export class PrintPreviewDocumentInfoElement extends PrintPreviewDocumentInfoElementBase {
diff --git a/chrome/browser/resources/print_preview/data/user_manager.ts b/chrome/browser/resources/print_preview/data/user_manager.ts index b9f461c..fd8e412d 100644 --- a/chrome/browser/resources/print_preview/data/user_manager.ts +++ b/chrome/browser/resources/print_preview/data/user_manager.ts
@@ -4,8 +4,8 @@ import {assert} from 'chrome://resources/js/assert.m.js'; import {EventTracker} from 'chrome://resources/js/event_tracker.m.js'; -import {WebUIListenerBehavior} from 'chrome://resources/js/web_ui_listener_behavior.m.js'; -import {mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {WebUIListenerMixin} from 'chrome://resources/js/web_ui_listener_mixin.js'; +import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {CloudPrintInterface, CloudPrintInterfaceErrorEventDetail, CloudPrintInterfaceEventType} from '../cloud_print_interface.js'; import {CloudPrintInterfaceImpl} from '../cloud_print_interface_impl.js'; @@ -18,11 +18,8 @@ users?: string[], }; -const PrintPreviewUserManagerElementBase = - mixinBehaviors([WebUIListenerBehavior], PolymerElement) as - {new (): PolymerElement & WebUIListenerBehavior}; +const PrintPreviewUserManagerElementBase = WebUIListenerMixin(PolymerElement); -/** @polymer */ class PrintPreviewUserManagerElement extends PrintPreviewUserManagerElementBase { static get is() {
diff --git a/chrome/browser/resources/print_preview/ui/advanced_settings_dialog.ts b/chrome/browser/resources/print_preview/ui/advanced_settings_dialog.ts index ed2b40fc..a673b41 100644 --- a/chrome/browser/resources/print_preview/ui/advanced_settings_dialog.ts +++ b/chrome/browser/resources/print_preview/ui/advanced_settings_dialog.ts
@@ -12,15 +12,15 @@ import '../strings.m.js'; import {CrDialogElement} from 'chrome://resources/cr_elements/cr_dialog/cr_dialog.m.js'; -import {I18nBehavior} from 'chrome://resources/js/i18n_behavior.m.js'; +import {I18nMixin} from 'chrome://resources/js/i18n_mixin.js'; import {removeHighlights} from 'chrome://resources/js/search_highlight_utils.js'; -import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {Destination} from '../data/destination.js'; import {MetricsContext, PrintSettingsUiBucket} from '../metrics.js'; import {PrintPreviewSearchBoxElement} from './print_preview_search_box.js'; -import {SettingsMixin, SettingsMixinInterface} from './settings_mixin.js'; +import {SettingsMixin} from './settings_mixin.js'; export interface PrintPreviewAdvancedSettingsDialogElement { $: { @@ -30,8 +30,7 @@ } const PrintPreviewAdvancedSettingsDialogElementBase = - mixinBehaviors([I18nBehavior], SettingsMixin(PolymerElement)) as - {new (): PolymerElement & SettingsMixinInterface & I18nBehavior}; + I18nMixin(SettingsMixin(PolymerElement)); export class PrintPreviewAdvancedSettingsDialogElement extends PrintPreviewAdvancedSettingsDialogElementBase {
diff --git a/chrome/browser/resources/print_preview/ui/app.ts b/chrome/browser/resources/print_preview/ui/app.ts index d763dd3f..b778b47 100644 --- a/chrome/browser/resources/print_preview/ui/app.ts +++ b/chrome/browser/resources/print_preview/ui/app.ts
@@ -14,8 +14,8 @@ import {FocusOutlineManager} from 'chrome://resources/js/cr/ui/focus_outline_manager.m.js'; import {EventTracker} from 'chrome://resources/js/event_tracker.m.js'; import {hasKeyModifiers} from 'chrome://resources/js/util.m.js'; -import {WebUIListenerBehavior} from 'chrome://resources/js/web_ui_listener_behavior.m.js'; -import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {WebUIListenerMixin} from 'chrome://resources/js/web_ui_listener_mixin.js'; +import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {CloudPrintInterface, CloudPrintInterfaceErrorEventDetail, CloudPrintInterfaceEventType} from '../cloud_print_interface.js'; import {CloudPrintInterfaceImpl} from '../cloud_print_interface_impl.js'; @@ -37,7 +37,7 @@ import {DestinationState} from './destination_settings.js'; import {PreviewAreaState, PrintPreviewPreviewAreaElement} from './preview_area.js'; -import {SettingsMixin, SettingsMixinInterface} from './settings_mixin.js'; +import {SettingsMixin} from './settings_mixin.js'; import {PrintPreviewSidebarElement} from './sidebar.js'; export interface PrintPreviewAppElement { @@ -51,8 +51,7 @@ } const PrintPreviewAppElementBase = - mixinBehaviors([WebUIListenerBehavior], SettingsMixin(PolymerElement)) as - {new (): PolymerElement & WebUIListenerBehavior & SettingsMixinInterface}; + WebUIListenerMixin(SettingsMixin(PolymerElement)); export class PrintPreviewAppElement extends PrintPreviewAppElementBase { static get is() {
diff --git a/chrome/browser/resources/print_preview/ui/destination_dialog_cros.ts b/chrome/browser/resources/print_preview/ui/destination_dialog_cros.ts index 7d33607..177d96d 100644 --- a/chrome/browser/resources/print_preview/ui/destination_dialog_cros.ts +++ b/chrome/browser/resources/print_preview/ui/destination_dialog_cros.ts
@@ -28,7 +28,7 @@ import {EventTracker} from 'chrome://resources/js/event_tracker.m.js'; import {ListPropertyUpdateBehavior} from 'chrome://resources/js/list_property_update_behavior.m.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; -import {WebUIListenerBehavior} from 'chrome://resources/js/web_ui_listener_behavior.m.js'; +import {WebUIListenerMixin, WebUIListenerMixinInterface} from 'chrome://resources/js/web_ui_listener_mixin.js'; import {beforeNextRender, html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {Destination, GooglePromotedDestinationId} from '../data/destination.js'; @@ -57,10 +57,9 @@ const PrintPreviewDestinationDialogCrosElementBase = mixinBehaviors( - [ListPropertyUpdateBehavior, WebUIListenerBehavior], PolymerElement) as - { - new (): - PolymerElement & WebUIListenerBehavior & ListPropertyUpdateBehavior + [ListPropertyUpdateBehavior], WebUIListenerMixin(PolymerElement)) as { + new (): PolymerElement & WebUIListenerMixinInterface & + ListPropertyUpdateBehavior }; export class PrintPreviewDestinationDialogCrosElement extends
diff --git a/chrome/browser/resources/print_preview/ui/destination_dropdown_cros.ts b/chrome/browser/resources/print_preview/ui/destination_dropdown_cros.ts index efb5d34..9d5de91 100644 --- a/chrome/browser/resources/print_preview/ui/destination_dropdown_cros.ts +++ b/chrome/browser/resources/print_preview/ui/destination_dropdown_cros.ts
@@ -10,8 +10,8 @@ import './print_preview_vars_css.js'; -import {I18nBehavior} from 'chrome://resources/js/i18n_behavior.m.js'; -import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {I18nMixin} from 'chrome://resources/js/i18n_mixin.js'; +import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {Destination, DestinationOrigin} from '../data/destination.js'; import {ERROR_STRING_KEY_MAP, getPrinterStatusIcon, PrinterStatusReason} from '../data/printer_status_cros.js'; @@ -24,8 +24,7 @@ } const PrintPreviewDestinationDropdownCrosElementBase = - mixinBehaviors([I18nBehavior], PolymerElement) as - {new (): PolymerElement & I18nBehavior}; + I18nMixin(PolymerElement); export class PrintPreviewDestinationDropdownCrosElement extends PrintPreviewDestinationDropdownCrosElementBase {
diff --git a/chrome/browser/resources/print_preview/ui/destination_list_item.ts b/chrome/browser/resources/print_preview/ui/destination_list_item.ts index 28887161..d23a752 100644 --- a/chrome/browser/resources/print_preview/ui/destination_list_item.ts +++ b/chrome/browser/resources/print_preview/ui/destination_list_item.ts
@@ -11,10 +11,10 @@ import '../strings.m.js'; import {assert} from 'chrome://resources/js/assert.m.js'; -import {I18nBehavior} from 'chrome://resources/js/i18n_behavior.m.js'; +import {I18nMixin} from 'chrome://resources/js/i18n_mixin.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; import {removeHighlights} from 'chrome://resources/js/search_highlight_utils.js'; -import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {Destination, DestinationOrigin} from '../data/destination.js'; // <if expr="chromeos or lacros"> @@ -31,9 +31,7 @@ } // </if> -const PrintPreviewDestinationListItemElementBase = - mixinBehaviors([I18nBehavior], PolymerElement) as - {new (): I18nBehavior & PolymerElement}; +const PrintPreviewDestinationListItemElementBase = I18nMixin(PolymerElement); export class PrintPreviewDestinationListItemElement extends PrintPreviewDestinationListItemElementBase {
diff --git a/chrome/browser/resources/print_preview/ui/destination_select.ts b/chrome/browser/resources/print_preview/ui/destination_select.ts index 9552aa9b..1743576 100644 --- a/chrome/browser/resources/print_preview/ui/destination_select.ts +++ b/chrome/browser/resources/print_preview/ui/destination_select.ts
@@ -19,19 +19,18 @@ import './throbber_css.js'; import '../strings.m.js'; -import {I18nBehavior} from 'chrome://resources/js/i18n_behavior.m.js'; +import {I18nMixin} from 'chrome://resources/js/i18n_mixin.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; import {IronMeta} from 'chrome://resources/polymer/v3_0/iron-meta/iron-meta.js'; -import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {Destination, DestinationOrigin, GooglePromotedDestinationId, PDF_DESTINATION_KEY, RecentDestination} from '../data/destination.js'; import {getSelectDropdownBackground} from '../print_preview_utils.js'; -import {SelectMixin, SelectMixinInterface} from './select_mixin.js'; +import {SelectMixin} from './select_mixin.js'; const PrintPreviewDestinationSelectElementBase = - mixinBehaviors([I18nBehavior], SelectMixin(PolymerElement)) as - {new (): PolymerElement & I18nBehavior & SelectMixinInterface}; + I18nMixin(SelectMixin(PolymerElement)); export class PrintPreviewDestinationSelectElement extends PrintPreviewDestinationSelectElementBase {
diff --git a/chrome/browser/resources/print_preview/ui/destination_select_cros.ts b/chrome/browser/resources/print_preview/ui/destination_select_cros.ts index b5c87df..699aead 100644 --- a/chrome/browser/resources/print_preview/ui/destination_select_cros.ts +++ b/chrome/browser/resources/print_preview/ui/destination_select_cros.ts
@@ -15,17 +15,16 @@ import '../strings.m.js'; import {assert} from 'chrome://resources/js/assert.m.js'; -import {I18nBehavior} from 'chrome://resources/js/i18n_behavior.m.js'; -import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {I18nMixin} from 'chrome://resources/js/i18n_mixin.js'; +import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {CloudOrigins, Destination, DestinationOrigin, GooglePromotedDestinationId, PDF_DESTINATION_KEY, RecentDestination, SAVE_TO_DRIVE_CROS_DESTINATION_KEY} from '../data/destination.js'; import {ERROR_STRING_KEY_MAP, getPrinterStatusIcon, PrinterStatusReason} from '../data/printer_status_cros.js'; -import {SelectMixin, SelectMixinInterface} from './select_mixin.js'; +import {SelectMixin} from './select_mixin.js'; const PrintPreviewDestinationSelectCrosElementBase = - mixinBehaviors([I18nBehavior], SelectMixin(PolymerElement)) as - {new (): I18nBehavior & SelectMixinInterface & PolymerElement}; + I18nMixin(SelectMixin(PolymerElement)); export class PrintPreviewDestinationSelectCrosElement extends PrintPreviewDestinationSelectCrosElementBase {
diff --git a/chrome/browser/resources/print_preview/ui/destination_settings.ts b/chrome/browser/resources/print_preview/ui/destination_settings.ts index 05b559f..bacd860 100644 --- a/chrome/browser/resources/print_preview/ui/destination_settings.ts +++ b/chrome/browser/resources/print_preview/ui/destination_settings.ts
@@ -27,10 +27,10 @@ import {CrLazyRenderElement} from 'chrome://resources/cr_elements/cr_lazy_render/cr_lazy_render.m.js'; import {assert} from 'chrome://resources/js/assert.m.js'; import {EventTracker} from 'chrome://resources/js/event_tracker.m.js'; -import {I18nBehavior} from 'chrome://resources/js/i18n_behavior.m.js'; +import {I18nMixin} from 'chrome://resources/js/i18n_mixin.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; -import {WebUIListenerBehavior} from 'chrome://resources/js/web_ui_listener_behavior.m.js'; -import {beforeNextRender, html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {WebUIListenerMixin} from 'chrome://resources/js/web_ui_listener_mixin.js'; +import {beforeNextRender, html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {CloudPrintInterfaceImpl} from '../cloud_print_interface_impl.js'; import {CloudOrigins, createDestinationKey, createRecentDestinationKey, Destination, DestinationOrigin, GooglePromotedDestinationId, makeRecentDestination, RecentDestination} from '../data/destination.js'; @@ -53,7 +53,7 @@ // <if expr="chromeos or lacros"> import {PrintPreviewDestinationSelectCrosElement} from './destination_select_cros.js'; // </if> -import {SettingsMixin, SettingsMixinInterface} from './settings_mixin.js'; +import {SettingsMixin} from './settings_mixin.js'; export enum DestinationState { INIT = 0, @@ -93,12 +93,7 @@ } const PrintPreviewDestinationSettingsElementBase = - mixinBehaviors( - [I18nBehavior, WebUIListenerBehavior], SettingsMixin(PolymerElement)) as - { - new (): PolymerElement & I18nBehavior & WebUIListenerBehavior & - SettingsMixinInterface - }; + I18nMixin(WebUIListenerMixin(SettingsMixin(PolymerElement))); export class PrintPreviewDestinationSettingsElement extends PrintPreviewDestinationSettingsElementBase {
diff --git a/chrome/browser/resources/print_preview/ui/input_mixin.ts b/chrome/browser/resources/print_preview/ui/input_mixin.ts index d9b9c6f..da904d6 100644 --- a/chrome/browser/resources/print_preview/ui/input_mixin.ts +++ b/chrome/browser/resources/print_preview/ui/input_mixin.ts
@@ -111,7 +111,7 @@ return InputMixin; }); -export interface InputMixinInterface { +interface InputMixinInterface { /** * @return The cr-input or input element the behavior should use. Should be * overridden by elements using this behavior.
diff --git a/chrome/browser/resources/print_preview/ui/margin_control.ts b/chrome/browser/resources/print_preview/ui/margin_control.ts index 4c6ef5d..ed40d9ee 100644 --- a/chrome/browser/resources/print_preview/ui/margin_control.ts +++ b/chrome/browser/resources/print_preview/ui/margin_control.ts
@@ -7,9 +7,9 @@ import '../strings.m.js'; import {assert} from 'chrome://resources/js/assert.m.js'; -import {I18nBehavior} from 'chrome://resources/js/i18n_behavior.m.js'; -import {WebUIListenerBehavior} from 'chrome://resources/js/web_ui_listener_behavior.m.js'; -import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {I18nMixin} from 'chrome://resources/js/i18n_mixin.js'; +import {WebUIListenerMixin} from 'chrome://resources/js/web_ui_listener_mixin.js'; +import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {Coordinate2d} from '../data/coordinate2d.js'; import {CustomMarginsOrientation} from '../data/margins.js'; @@ -17,7 +17,7 @@ import {Size} from '../data/size.js'; import {observerDepsDefined} from '../print_preview_utils.js'; -import {InputMixin, InputMixinInterface} from './input_mixin.js'; +import {InputMixin} from './input_mixin.js'; /** * Radius of the margin control in pixels. Padding of control + 1 for border. @@ -32,11 +32,7 @@ } const PrintPreviewMarginControlElementBase = - mixinBehaviors( - [I18nBehavior, WebUIListenerBehavior], InputMixin(PolymerElement)) as { - new (): PolymerElement & I18nBehavior & WebUIListenerBehavior & - InputMixinInterface - }; + I18nMixin(WebUIListenerMixin(InputMixin(PolymerElement))); export class PrintPreviewMarginControlElement extends PrintPreviewMarginControlElementBase {
diff --git a/chrome/browser/resources/print_preview/ui/margin_control_container.ts b/chrome/browser/resources/print_preview/ui/margin_control_container.ts index c8780ce..fc71a45 100644 --- a/chrome/browser/resources/print_preview/ui/margin_control_container.ts +++ b/chrome/browser/resources/print_preview/ui/margin_control_container.ts
@@ -15,7 +15,7 @@ import {State} from '../data/state.js'; import {PrintPreviewMarginControlElement} from './margin_control.js'; -import {SettingsMixin, SettingsMixinInterface} from './settings_mixin.js'; +import {SettingsMixin} from './settings_mixin.js'; export const MARGIN_KEY_MAP: Map<CustomMarginsOrientation, string> = new Map([ [CustomMarginsOrientation.TOP, 'marginTop'],
diff --git a/chrome/browser/resources/print_preview/ui/more_settings.ts b/chrome/browser/resources/print_preview/ui/more_settings.ts index 9ec3e9e..a2a2f43c 100644 --- a/chrome/browser/resources/print_preview/ui/more_settings.ts +++ b/chrome/browser/resources/print_preview/ui/more_settings.ts
@@ -9,7 +9,7 @@ import {CrExpandButtonElement} from 'chrome://resources/cr_elements/cr_expand_button/cr_expand_button.m.js'; import {assert} from 'chrome://resources/js/assert.m.js'; -import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {MetricsContext, PrintSettingsUiBucket} from '../metrics.js';
diff --git a/chrome/browser/resources/print_preview/ui/number_settings_section.ts b/chrome/browser/resources/print_preview/ui/number_settings_section.ts index a7051c66..af4057e 100644 --- a/chrome/browser/resources/print_preview/ui/number_settings_section.ts +++ b/chrome/browser/resources/print_preview/ui/number_settings_section.ts
@@ -8,10 +8,10 @@ import './settings_section.js'; import {CrInputElement} from 'chrome://resources/cr_elements/cr_input/cr_input.m.js'; -import {WebUIListenerBehavior} from 'chrome://resources/js/web_ui_listener_behavior.m.js'; -import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {WebUIListenerMixin} from 'chrome://resources/js/web_ui_listener_mixin.js'; +import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; -import {InputMixin, InputMixinInterface} from './input_mixin.js'; +import {InputMixin} from './input_mixin.js'; export interface PrintPreviewNumberSettingsSectionElement { $: { @@ -20,8 +20,7 @@ } const PrintPreviewNumberSettingsSectionElementBase = - mixinBehaviors([WebUIListenerBehavior], InputMixin(PolymerElement)) as - {new (): PolymerElement & WebUIListenerBehavior & InputMixinInterface}; + WebUIListenerMixin(InputMixin(PolymerElement)); export class PrintPreviewNumberSettingsSectionElement extends PrintPreviewNumberSettingsSectionElementBase {
diff --git a/chrome/browser/resources/print_preview/ui/pages_settings.ts b/chrome/browser/resources/print_preview/ui/pages_settings.ts index ae6982b..5e82cbd 100644 --- a/chrome/browser/resources/print_preview/ui/pages_settings.ts +++ b/chrome/browser/resources/print_preview/ui/pages_settings.ts
@@ -12,14 +12,14 @@ import {CrInputElement} from 'chrome://resources/cr_elements/cr_input/cr_input.m.js'; import {assert} from 'chrome://resources/js/assert.m.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; -import {WebUIListenerBehavior} from 'chrome://resources/js/web_ui_listener_behavior.m.js'; -import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {WebUIListenerMixin} from 'chrome://resources/js/web_ui_listener_mixin.js'; +import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {areRangesEqual, Range} from '../print_preview_utils.js'; -import {InputMixin, InputMixinInterface} from './input_mixin.js'; -import {SelectMixin, SelectMixinInterface} from './select_mixin.js'; -import {SettingsMixin, SettingsMixinInterface} from './settings_mixin.js'; +import {InputMixin} from './input_mixin.js'; +import {SelectMixin} from './select_mixin.js'; +import {SettingsMixin} from './settings_mixin.js'; enum PagesInputErrorState { NO_ERROR = 0, @@ -56,12 +56,7 @@ } const PrintPreviewPagesSettingsElementBase = - mixinBehaviors( - [WebUIListenerBehavior], - InputMixin(SettingsMixin(SelectMixin(PolymerElement)))) as { - new (): PolymerElement & WebUIListenerBehavior & InputMixinInterface & - SettingsMixinInterface & SelectMixinInterface - }; + WebUIListenerMixin(InputMixin(SettingsMixin(SelectMixin(PolymerElement)))); export class PrintPreviewPagesSettingsElement extends PrintPreviewPagesSettingsElementBase {
diff --git a/chrome/browser/resources/print_preview/ui/pin_settings.ts b/chrome/browser/resources/print_preview/ui/pin_settings.ts index 257e5efd..b1a83e70 100644 --- a/chrome/browser/resources/print_preview/ui/pin_settings.ts +++ b/chrome/browser/resources/print_preview/ui/pin_settings.ts
@@ -10,14 +10,14 @@ import {CrCheckboxElement} from 'chrome://resources/cr_elements/cr_checkbox/cr_checkbox.m.js'; import {CrInputElement} from 'chrome://resources/cr_elements/cr_input/cr_input.m.js'; -import {I18nMixin, I18nMixinInterface} from 'chrome://resources/js/i18n_mixin.js'; -import {WebUIListenerBehavior} from 'chrome://resources/js/web_ui_listener_behavior.m.js'; -import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {I18nMixin} from 'chrome://resources/js/i18n_mixin.js'; +import {WebUIListenerMixin} from 'chrome://resources/js/web_ui_listener_mixin.js'; +import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {State} from '../data/state.js'; -import {InputMixin, InputMixinInterface} from './input_mixin.js'; -import {SettingsMixin, SettingsMixinInterface} from './settings_mixin.js'; +import {InputMixin} from './input_mixin.js'; +import {SettingsMixin} from './settings_mixin.js'; interface PrintPreviewPinSettingsElement { $: { @@ -27,12 +27,7 @@ } const PrintPreviewPinSettingsElementBase = - mixinBehaviors( - [WebUIListenerBehavior], - InputMixin(SettingsMixin(I18nMixin(PolymerElement)))) as { - new (): PolymerElement & I18nMixinInterface & WebUIListenerBehavior & - InputMixinInterface & SettingsMixinInterface - }; + WebUIListenerMixin(InputMixin(SettingsMixin(I18nMixin(PolymerElement)))); class PrintPreviewPinSettingsElement extends PrintPreviewPinSettingsElementBase {
diff --git a/chrome/browser/resources/print_preview/ui/preview_area.ts b/chrome/browser/resources/print_preview/ui/preview_area.ts index 64186dd..96de86f 100644 --- a/chrome/browser/resources/print_preview/ui/preview_area.ts +++ b/chrome/browser/resources/print_preview/ui/preview_area.ts
@@ -9,12 +9,12 @@ import {assert} from 'chrome://resources/js/assert.m.js'; import {isMac} from 'chrome://resources/js/cr.m.js'; -import {I18nBehavior} from 'chrome://resources/js/i18n_behavior.m.js'; +import {I18nMixin} from 'chrome://resources/js/i18n_mixin.js'; import {hasKeyModifiers} from 'chrome://resources/js/util.m.js'; -import {WebUIListenerBehavior} from 'chrome://resources/js/web_ui_listener_behavior.m.js'; -import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {WebUIListenerMixin} from 'chrome://resources/js/web_ui_listener_mixin.js'; +import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; -import {DarkModeMixin, DarkModeMixinInterface} from '../dark_mode_mixin.js'; +import {DarkModeMixin} from '../dark_mode_mixin.js'; import {Coordinate2d} from '../data/coordinate2d.js'; import {Destination} from '../data/destination.js'; import {getPrinterTypeForDestination} from '../data/destination_match.js'; @@ -31,7 +31,7 @@ import {MARGIN_KEY_MAP, MarginObject, PrintPreviewMarginControlContainerElement} from './margin_control_container.js'; import {PluginProxy, PluginProxyImpl} from './plugin_proxy.js'; -import {SettingsMixin, SettingsMixinInterface} from './settings_mixin.js'; +import {SettingsMixin} from './settings_mixin.js'; type PreviewTicket = Ticket&{ headerFooterEnabled: boolean; @@ -54,12 +54,7 @@ } const PrintPreviewPreviewAreaElementBase = - mixinBehaviors( - [WebUIListenerBehavior, I18nBehavior], - SettingsMixin(DarkModeMixin(PolymerElement))) as { - new (): PolymerElement & WebUIListenerBehavior & I18nBehavior & - SettingsMixinInterface & DarkModeMixinInterface - }; + WebUIListenerMixin(I18nMixin(SettingsMixin(DarkModeMixin(PolymerElement)))); export class PrintPreviewPreviewAreaElement extends PrintPreviewPreviewAreaElementBase {
diff --git a/chrome/browser/resources/print_preview/ui/print_preview_search_box.ts b/chrome/browser/resources/print_preview/ui/print_preview_search_box.ts index bd28c08..b4c574a0 100644 --- a/chrome/browser/resources/print_preview/ui/print_preview_search_box.ts +++ b/chrome/browser/resources/print_preview/ui/print_preview_search_box.ts
@@ -11,7 +11,7 @@ import {CrInputElement} from 'chrome://resources/cr_elements/cr_input/cr_input.m.js'; import {CrSearchFieldBehavior} from 'chrome://resources/cr_elements/cr_search_field/cr_search_field_behavior.js'; import {stripDiacritics} from 'chrome://resources/js/search_highlight_utils.js'; -import {WebUIListenerBehavior} from 'chrome://resources/js/web_ui_listener_behavior.m.js'; +import {WebUIListenerMixin, WebUIListenerMixinInterface} from 'chrome://resources/js/web_ui_listener_mixin.js'; import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; declare global { @@ -30,8 +30,10 @@ const PrintPreviewSearchBoxElementBase = mixinBehaviors( - [CrSearchFieldBehavior, WebUIListenerBehavior], PolymerElement) as - {new (): PolymerElement & WebUIListenerBehavior & CrSearchFieldBehavior}; + [CrSearchFieldBehavior], WebUIListenerMixin(PolymerElement)) as { + new (): + PolymerElement & WebUIListenerMixinInterface & CrSearchFieldBehavior + }; export class PrintPreviewSearchBoxElement extends PrintPreviewSearchBoxElementBase {
diff --git a/chrome/browser/resources/print_preview/ui/provisional_destination_resolver.ts b/chrome/browser/resources/print_preview/ui/provisional_destination_resolver.ts index 9200c3af..36efcea 100644 --- a/chrome/browser/resources/print_preview/ui/provisional_destination_resolver.ts +++ b/chrome/browser/resources/print_preview/ui/provisional_destination_resolver.ts
@@ -13,9 +13,9 @@ import {CrDialogElement} from 'chrome://resources/cr_elements/cr_dialog/cr_dialog.m.js'; import {assert} from 'chrome://resources/js/assert.m.js'; -import {I18nBehavior} from 'chrome://resources/js/i18n_behavior.m.js'; +import {I18nMixin} from 'chrome://resources/js/i18n_mixin.js'; import {PromiseResolver} from 'chrome://resources/js/promise_resolver.m.js'; -import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {Destination} from '../data/destination.js'; import {DestinationStore} from '../data/destination_store.js'; @@ -47,8 +47,7 @@ } const PrintPreviewProvisionalDestinationResolverElementBase = - mixinBehaviors([I18nBehavior], PolymerElement) as - {new (): PolymerElement & I18nBehavior}; + I18nMixin(PolymerElement); export class PrintPreviewProvisionalDestinationResolverElement extends PrintPreviewProvisionalDestinationResolverElementBase {
diff --git a/chrome/browser/resources/print_preview/ui/select_mixin.ts b/chrome/browser/resources/print_preview/ui/select_mixin.ts index 0ada172..0c2a6df 100644 --- a/chrome/browser/resources/print_preview/ui/select_mixin.ts +++ b/chrome/browser/resources/print_preview/ui/select_mixin.ts
@@ -58,7 +58,7 @@ return SelectMixin; }); -export interface SelectMixinInterface { +interface SelectMixinInterface { selectedValue: string; /**
diff --git a/chrome/browser/resources/print_preview/ui/sidebar.ts b/chrome/browser/resources/print_preview/ui/sidebar.ts index 2056d6d..712b57f 100644 --- a/chrome/browser/resources/print_preview/ui/sidebar.ts +++ b/chrome/browser/resources/print_preview/ui/sidebar.ts
@@ -33,7 +33,7 @@ import {CrContainerShadowBehavior} from 'chrome://resources/cr_elements/cr_container_shadow_behavior.m.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; -import {WebUIListenerBehavior} from 'chrome://resources/js/web_ui_listener_behavior.m.js'; +import {WebUIListenerMixin, WebUIListenerMixinInterface} from 'chrome://resources/js/web_ui_listener_mixin.js'; import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {DarkModeMixin, DarkModeMixinInterface} from '../dark_mode_mixin.js'; @@ -59,11 +59,10 @@ mixinBehaviors( [ CrContainerShadowBehavior, - WebUIListenerBehavior, ], - SettingsMixin(DarkModeMixin(PolymerElement))) as { - new (): PolymerElement & WebUIListenerBehavior & DarkModeMixinInterface & - SettingsMixinInterface + WebUIListenerMixin(SettingsMixin(DarkModeMixin(PolymerElement)))) as { + new (): PolymerElement & WebUIListenerMixinInterface & + DarkModeMixinInterface & SettingsMixinInterface }; export class PrintPreviewSidebarElement extends PrintPreviewSidebarElementBase {
diff --git a/chrome/browser/safe_browsing/chrome_password_protection_service.cc b/chrome/browser/safe_browsing/chrome_password_protection_service.cc index fa36955..5e67260 100644 --- a/chrome/browser/safe_browsing/chrome_password_protection_service.cc +++ b/chrome/browser/safe_browsing/chrome_password_protection_service.cc
@@ -1615,6 +1615,11 @@ identity_manager->GetPrimaryAccountInfo(signin::ConsentLevel::kSync)); } +ChromeUserPopulation::UserPopulation +ChromePasswordProtectionService::GetUserPopulationPref() const { + return ::safe_browsing::GetUserPopulationPref(profile_->GetPrefs()); +} + ChromePasswordProtectionService::ChromePasswordProtectionService( Profile* profile, scoped_refptr<SafeBrowsingUIManager> ui_manager,
diff --git a/chrome/browser/safe_browsing/chrome_password_protection_service.h b/chrome/browser/safe_browsing/chrome_password_protection_service.h index caf7a0b..07d39fd 100644 --- a/chrome/browser/safe_browsing/chrome_password_protection_service.h +++ b/chrome/browser/safe_browsing/chrome_password_protection_service.h
@@ -26,6 +26,7 @@ #include "components/safe_browsing/buildflags.h" #include "components/safe_browsing/content/browser/password_protection/password_protection_service.h" #include "components/safe_browsing/content/browser/triggers/trigger_manager.h" +#include "components/safe_browsing/content/browser/user_population.h" #include "components/sessions/core/session_id.h" #include "components/sync/protocol/gaia_password_reuse.pb.h" #include "components/sync/protocol/user_event_specifics.pb.h" @@ -292,6 +293,9 @@ // Gets |account_info_| based on |profile_|. AccountInfo GetAccountInfo() const override; + // Gets the UserPopulation value for this profile. + ChromeUserPopulation::UserPopulation GetUserPopulationPref() const override; + // KeyedService: // Called before the actual deletion of the object. void Shutdown() override;
diff --git a/chrome/browser/share/OWNERS b/chrome/browser/share/OWNERS index 07431be0..8d2032ce 100644 --- a/chrome/browser/share/OWNERS +++ b/chrome/browser/share/OWNERS
@@ -5,3 +5,5 @@ sebsg@chromium.org skare@chromium.org sophey@chromium.org + +per-file *.gni=file://components/paint_preview/OWNERS
diff --git a/chrome/browser/supervised_user/supervised_user_navigation_throttle_browsertest.cc b/chrome/browser/supervised_user/supervised_user_navigation_throttle_browsertest.cc index 7289964..1208a15a 100644 --- a/chrome/browser/supervised_user/supervised_user_navigation_throttle_browsertest.cc +++ b/chrome/browser/supervised_user/supervised_user_navigation_throttle_browsertest.cc
@@ -16,6 +16,7 @@ #include "base/strings/utf_string_conversions.h" #include "base/test/scoped_feature_list.h" #include "base/values.h" +#include "build/build_config.h" #include "chrome/browser/ash/login/test/logged_in_user_mixin.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_key.h" @@ -221,8 +222,14 @@ } // Tests that prerendering fails in supervised user mode. +#if defined(OS_CHROMEOS) +// TODO(crbug.com/1259146): Flaky on ChromeOS. +#define MAYBE_DisallowPrerendering DISABLED_DisallowPrerendering +#else +#define MAYBE_DisallowPrerendering DisallowPrerendering +#endif IN_PROC_BROWSER_TEST_F(SupervisedUserNavigationThrottleTest, - DisallowPrerendering) { + MAYBE_DisallowPrerendering) { base::HistogramTester histogram_tester; const GURL initial_url = embedded_test_server()->GetURL("/simple.html"); const GURL allowed_url =
diff --git a/chrome/browser/sync/test/integration/two_client_send_tab_to_self_sync_test.cc b/chrome/browser/sync/test/integration/two_client_send_tab_to_self_sync_test.cc index 65f3a90..67a1bba 100644 --- a/chrome/browser/sync/test/integration/two_client_send_tab_to_self_sync_test.cc +++ b/chrome/browser/sync/test/integration/two_client_send_tab_to_self_sync_test.cc
@@ -122,21 +122,6 @@ EXPECT_TRUE(send_tab_to_self::IsUserSyncTypeActive(GetProfile(0))); } -IN_PROC_BROWSER_TEST_F(TwoClientSendTabToSelfSyncTest, HasValidTargetDevice) { - ASSERT_TRUE(SetupSync()); - - static_cast<send_tab_to_self::SendTabToSelfBridge*>( - SendTabToSelfSyncServiceFactory::GetForProfile(GetProfile(0)) - ->GetSendTabToSelfModel()) - ->SetLocalDeviceNameForTest("device1"); - static_cast<send_tab_to_self::SendTabToSelfBridge*>( - SendTabToSelfSyncServiceFactory::GetForProfile(GetProfile(1)) - ->GetSendTabToSelfModel()) - ->SetLocalDeviceNameForTest("device2"); - - EXPECT_TRUE(send_tab_to_self::HasValidTargetDevice(GetProfile(0))); -} - IN_PROC_BROWSER_TEST_F(TwoClientSendTabToSelfSyncTest, SendTabToSelfReceivingEnabled) { ASSERT_TRUE(SetupSync()); @@ -191,7 +176,7 @@ } IN_PROC_BROWSER_TEST_F(TwoClientSendTabToSelfSyncTest, - SendTabToSelfTargetDeviceMap) { + SendTabToSelfTargetDeviceInfoList) { ASSERT_TRUE(SetupSync()); DeviceInfoSyncServiceFactory::GetForProfile(GetProfile(0)) @@ -209,6 +194,11 @@ // Explicitly set the two profiles to have different client names to simulate // them being on different devices. Otherwise their device infos will get // deduped. + // TODO(crbug.com/1257573): This is rather misleading. The "device1"/"device2" + // strings below are never sent to the server, they just ensure the local + // device name is different from the other entry. The same string could even + // be used in both calls. The most robust test would be: update the device + // info name and wait for the right value of GetTargetDeviceInfoSortedList(). static_cast<send_tab_to_self::SendTabToSelfBridge*>( SendTabToSelfSyncServiceFactory::GetForProfile(GetProfile(0)) ->GetSendTabToSelfModel()) @@ -218,17 +208,27 @@ ->GetSendTabToSelfModel()) ->SetLocalDeviceNameForTest("device2"); - std::vector<send_tab_to_self::TargetDeviceInfo> profile1_target_device_map = + // Emulate a device info update to force the target device list to refresh. + DeviceInfoSyncServiceFactory::GetForProfile(GetProfile(1)) + ->GetDeviceInfoTracker() + ->ForcePulseForTest(); + DeviceInfoSyncServiceFactory::GetForProfile(GetProfile(0)) + ->GetDeviceInfoTracker() + ->ForcePulseForTest(); + + std::vector<send_tab_to_self::TargetDeviceInfo> profile1_target_devices = SendTabToSelfSyncServiceFactory::GetForProfile(GetProfile(0)) ->GetSendTabToSelfModel() ->GetTargetDeviceInfoSortedList(); - std::vector<send_tab_to_self::TargetDeviceInfo> profile2_target_device_map = + std::vector<send_tab_to_self::TargetDeviceInfo> profile2_target_devices = SendTabToSelfSyncServiceFactory::GetForProfile(GetProfile(1)) ->GetSendTabToSelfModel() ->GetTargetDeviceInfoSortedList(); - EXPECT_EQ(1u, profile1_target_device_map.size()); - EXPECT_EQ(1u, profile2_target_device_map.size()); + EXPECT_EQ(1u, profile1_target_devices.size()); + EXPECT_EQ(1u, profile2_target_devices.size()); + EXPECT_TRUE(send_tab_to_self::HasValidTargetDevice(GetProfile(0))); + EXPECT_TRUE(send_tab_to_self::HasValidTargetDevice(GetProfile(1))); } IN_PROC_BROWSER_TEST_F(TwoClientSendTabToSelfSyncTest,
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index 64480ad..27c768e 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -873,6 +873,7 @@ "//components/navigation_interception", "//components/optimization_guide/proto:optimization_guide_proto", "//components/page_info", + "//components/page_info:proto", "//components/page_info/android:android", "//components/query_tiles", "//components/resources:android_resources", @@ -1050,6 +1051,7 @@ "global_media_controls/cast_media_notification_producer.h", "global_media_controls/cast_media_session_controller.cc", "global_media_controls/cast_media_session_controller.h", + "global_media_controls/media_item_ui_device_selector_delegate.h", "global_media_controls/media_notification_device_monitor.cc", "global_media_controls/media_notification_device_monitor.h", "global_media_controls/media_notification_device_provider.h", @@ -1423,6 +1425,10 @@ "webui/downloads/downloads_list_tracker.h", "webui/downloads/downloads_ui.cc", "webui/downloads/downloads_ui.h", + "webui/enterprise_casting/enterprise_casting_handler.cc", + "webui/enterprise_casting/enterprise_casting_handler.h", + "webui/enterprise_casting/enterprise_casting_ui.cc", + "webui/enterprise_casting/enterprise_casting_ui.h", "webui/extensions/extensions_internals_source.cc", "webui/extensions/extensions_internals_source.h", "webui/extensions/extensions_ui.cc", @@ -1658,6 +1664,7 @@ "//chrome/browser/ui/commander:fuzzy_finder", "//chrome/browser/ui/webui/app_management:mojo_bindings", "//chrome/browser/ui/webui/app_service_internals:mojo_bindings", + "//chrome/browser/ui/webui/enterprise_casting:mojo_bindings", "//chrome/browser/ui/webui/internals/user_education:mojo_bindings", "//chrome/browser/ui/webui/tab_strip:mojo_bindings", "//chrome/browser/web_applications", @@ -2406,10 +2413,6 @@ "webui/chromeos/emoji/emoji_page_handler.h", "webui/chromeos/emoji/emoji_ui.cc", "webui/chromeos/emoji/emoji_ui.h", - "webui/chromeos/enterprise_casting/enterprise_casting_handler.cc", - "webui/chromeos/enterprise_casting/enterprise_casting_handler.h", - "webui/chromeos/enterprise_casting/enterprise_casting_ui.cc", - "webui/chromeos/enterprise_casting/enterprise_casting_ui.h", "webui/chromeos/image_source.cc", "webui/chromeos/image_source.h", "webui/chromeos/in_session_password_change/base_lock_dialog.cc", @@ -2862,7 +2865,6 @@ "//chrome/browser/ui/webui/chromeos/add_supervision:mojo_bindings", "//chrome/browser/ui/webui/chromeos/audio:mojo_bindings", "//chrome/browser/ui/webui/chromeos/crostini_upgrader:mojo_bindings", - "//chrome/browser/ui/webui/chromeos/enterprise_casting:mojo_bindings", "//chrome/browser/ui/webui/chromeos/launcher_internals:mojo_bindings", "//chrome/browser/ui/webui/chromeos/parent_access:mojo_bindings", "//chrome/browser/ui/webui/chromeos/vm:mojo_bindings", @@ -4066,22 +4068,18 @@ "views/fullscreen_control/fullscreen_control_host.h", "views/global_error_bubble_view.cc", "views/global_error_bubble_view.h", - "views/global_media_controls/global_media_controls_types.h", "views/global_media_controls/media_dialog_view.cc", "views/global_media_controls/media_dialog_view.h", "views/global_media_controls/media_dialog_view_observer.h", - "views/global_media_controls/media_notification_container_impl_view.cc", - "views/global_media_controls/media_notification_container_impl_view.h", + "views/global_media_controls/media_item_ui_device_selector_observer.h", + "views/global_media_controls/media_item_ui_device_selector_view.cc", + "views/global_media_controls/media_item_ui_device_selector_view.h", + "views/global_media_controls/media_item_ui_footer_view.cc", + "views/global_media_controls/media_item_ui_footer_view.h", + "views/global_media_controls/media_item_ui_legacy_cast_footer_view.cc", + "views/global_media_controls/media_item_ui_legacy_cast_footer_view.h", "views/global_media_controls/media_notification_device_entry_ui.cc", "views/global_media_controls/media_notification_device_entry_ui.h", - "views/global_media_controls/media_notification_device_selector_observer.h", - "views/global_media_controls/media_notification_device_selector_view.cc", - "views/global_media_controls/media_notification_device_selector_view.h", - "views/global_media_controls/media_notification_device_selector_view_delegate.h", - "views/global_media_controls/media_notification_footer_view.cc", - "views/global_media_controls/media_notification_footer_view.h", - "views/global_media_controls/media_notification_list_view.cc", - "views/global_media_controls/media_notification_list_view.h", "views/global_media_controls/media_toolbar_button_view.cc", "views/global_media_controls/media_toolbar_button_view.h", "views/hover_button.cc", @@ -4668,6 +4666,7 @@ "//components/live_caption", "//components/media_message_center", "//components/page_info", + "//components/page_info:proto", "//components/payments/content", "//components/payments/content:utils", "//components/payments/core",
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chrome/browser/ui/android/strings/android_chrome_strings.grd index a3c34cc..c42d3a9f 100644 --- a/chrome/browser/ui/android/strings/android_chrome_strings.grd +++ b/chrome/browser/ui/android/strings/android_chrome_strings.grd
@@ -1019,6 +1019,15 @@ <message name="IDS_PREFS_PRIVACY_REVIEW_SUMMARY" desc="The summary of the privacy menu item."> Review privacy and security settings </message> + <message name="IDS_PRIVACY_REVIEW_WELCOME_TITLE" desc="Title on the welcome page of the privacy review."> + The most important privacy and security controls in one place + </message> + <message name="IDS_PRIVACY_REVIEW_WELCOME_DESCRIPTION" desc="Description on the welcome page of the privacy review."> + Chrome provides reasonable defaults, but you can customize it to best fit your browsing habit + </message> + <message name="IDS_PRIVACY_REVIEW_START_BUTTON" desc="Text on the privacy review start button on the welcome screen."> + Let’s go + </message> <!-- Safety check --> <message name="IDS_PREFS_SAFETY_CHECK" desc="Title of the Safety check element in settings, allowing the user to check multiple areas of browser safety. [CHAR_LIMIT=32]">
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_PRIVACY_REVIEW_START_BUTTON.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_PRIVACY_REVIEW_START_BUTTON.png.sha1 new file mode 100644 index 0000000..dbfd6e6 --- /dev/null +++ b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_PRIVACY_REVIEW_START_BUTTON.png.sha1
@@ -0,0 +1 @@ +9f8fba0dbbddbe6c5fbe7f569961d2a092d888b1 \ No newline at end of file
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_PRIVACY_REVIEW_WELCOME_DESCRIPTION.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_PRIVACY_REVIEW_WELCOME_DESCRIPTION.png.sha1 new file mode 100644 index 0000000..dbfd6e6 --- /dev/null +++ b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_PRIVACY_REVIEW_WELCOME_DESCRIPTION.png.sha1
@@ -0,0 +1 @@ +9f8fba0dbbddbe6c5fbe7f569961d2a092d888b1 \ No newline at end of file
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_PRIVACY_REVIEW_WELCOME_TITLE.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_PRIVACY_REVIEW_WELCOME_TITLE.png.sha1 new file mode 100644 index 0000000..dbfd6e6 --- /dev/null +++ b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_PRIVACY_REVIEW_WELCOME_TITLE.png.sha1
@@ -0,0 +1 @@ +9f8fba0dbbddbe6c5fbe7f569961d2a092d888b1 \ No newline at end of file
diff --git a/chrome/browser/ui/ash/media_notification_provider_impl.cc b/chrome/browser/ui/ash/media_notification_provider_impl.cc index e39635b..8f60f4e3 100644 --- a/chrome/browser/ui/ash/media_notification_provider_impl.cc +++ b/chrome/browser/ui/ash/media_notification_provider_impl.cc
@@ -9,9 +9,9 @@ #include "chrome/browser/ash/profiles/profile_helper.h" #include "chrome/browser/ui/global_media_controls/media_notification_service.h" #include "chrome/browser/ui/global_media_controls/media_notification_service_factory.h" -#include "chrome/browser/ui/views/global_media_controls/media_notification_container_impl_view.h" -#include "chrome/browser/ui/views/global_media_controls/media_notification_list_view.h" #include "components/global_media_controls/public/media_item_manager.h" +#include "components/global_media_controls/public/views/media_item_ui_list_view.h" +#include "components/global_media_controls/public/views/media_item_ui_view.h" #include "components/session_manager/core/session_manager.h" #include "ui/views/view.h" @@ -57,13 +57,15 @@ int separator_thickness) { DCHECK(item_manager_); DCHECK(color_theme_); - auto notification_list_view = std::make_unique<MediaNotificationListView>( - MediaNotificationListView::SeparatorStyle(color_theme_->separator_color, - separator_thickness)); + auto notification_list_view = + std::make_unique<global_media_controls::MediaItemUIListView>( + global_media_controls::MediaItemUIListView::SeparatorStyle( + color_theme_->separator_color, separator_thickness)); active_session_view_ = notification_list_view.get(); item_manager_->SetDialogDelegate(this); - base::UmaHistogramEnumeration("Media.GlobalMediaControls.EntryPoint", - GlobalMediaControlsEntryPoint::kSystemTray); + base::UmaHistogramEnumeration( + "Media.GlobalMediaControls.EntryPoint", + global_media_controls::GlobalMediaControlsEntryPoint::kSystemTray); return std::move(notification_list_view); } @@ -88,14 +90,14 @@ if (!active_session_view_) return nullptr; - auto container = std::make_unique<MediaNotificationContainerImplView>( - id, item, service_, GlobalMediaControlsEntryPoint::kSystemTray, profile_, + auto item_ui = std::make_unique<global_media_controls::MediaItemUIView>( + id, item, /*footer_view=*/nullptr, /*device_selector_view=*/nullptr, color_theme_); - auto* item_ui_ptr = container.get(); + auto* item_ui_ptr = item_ui.get(); item_ui_ptr->AddObserver(this); observed_item_uis_[id] = item_ui_ptr; - active_session_view_->ShowNotification(id, std::move(container)); + active_session_view_->ShowItem(id, std::move(item_ui)); for (auto& observer : observers_) observer.OnNotificationListViewSizeChanged(); @@ -106,7 +108,7 @@ if (!active_session_view_) return; - active_session_view_->HideNotification(id); + active_session_view_->HideItem(id); for (auto& observer : observers_) observer.OnNotificationListViewSizeChanged(); } @@ -132,12 +134,13 @@ void MediaNotificationProviderImpl::OnUserProfileLoaded( const AccountId& account_id) { - profile_ = chromeos::ProfileHelper::Get()->GetProfileByAccountId(account_id); + auto* profile = + chromeos::ProfileHelper::Get()->GetProfileByAccountId(account_id); user_manager::User* user = - chromeos::ProfileHelper::Get()->GetUserByProfile(profile_); + chromeos::ProfileHelper::Get()->GetUserByProfile(profile); if (user_manager::UserManager::Get()->GetPrimaryUser() == user) { - service_ = MediaNotificationServiceFactory::GetForProfile(profile_); + service_ = MediaNotificationServiceFactory::GetForProfile(profile); item_manager_ = service_->media_item_manager(); item_manager_->AddObserver(this); }
diff --git a/chrome/browser/ui/ash/media_notification_provider_impl.h b/chrome/browser/ui/ash/media_notification_provider_impl.h index 40acd6f2..14340e5f 100644 --- a/chrome/browser/ui/ash/media_notification_provider_impl.h +++ b/chrome/browser/ui/ash/media_notification_provider_impl.h
@@ -18,11 +18,10 @@ namespace global_media_controls { class MediaItemManager; +class MediaItemUIListView; } // namespace global_media_controls class MediaNotificationService; -class MediaNotificationListView; -class Profile; class MediaNotificationProviderImpl : public ash::MediaNotificationProvider, @@ -72,9 +71,7 @@ private: base::ObserverList<ash::MediaNotificationProviderObserver> observers_; - MediaNotificationListView* active_session_view_ = nullptr; - - Profile* profile_ = nullptr; + global_media_controls::MediaItemUIListView* active_session_view_ = nullptr; MediaNotificationService* service_ = nullptr;
diff --git a/chrome/browser/ui/ash/media_notification_provider_impl_unittest.cc b/chrome/browser/ui/ash/media_notification_provider_impl_unittest.cc index 6c78fe70..5480109 100644 --- a/chrome/browser/ui/ash/media_notification_provider_impl_unittest.cc +++ b/chrome/browser/ui/ash/media_notification_provider_impl_unittest.cc
@@ -12,9 +12,9 @@ #include "chrome/browser/ui/global_media_controls/media_notification_service.h" #include "chrome/browser/ui/global_media_controls/media_notification_service_factory.h" #include "chrome/browser/ui/global_media_controls/media_session_notification_producer.h" -#include "chrome/browser/ui/views/global_media_controls/media_notification_list_view.h" #include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_profile_manager.h" +#include "components/global_media_controls/public/views/media_item_ui_list_view.h" #include "components/session_manager/core/session_manager.h" #include "content/public/test/browser_task_environment.h" #include "media/base/media_switches.h" @@ -144,12 +144,12 @@ provider()->GetMediaNotificationListView(1); auto* notification_list_view = - static_cast<MediaNotificationListView*>(view.get()); - EXPECT_EQ(notification_list_view->notifications_for_testing().size(), 2u); + static_cast<global_media_controls::MediaItemUIListView*>(view.get()); + EXPECT_EQ(notification_list_view->items_for_testing().size(), 2u); EXPECT_CALL(*observer(), OnNotificationListViewSizeChanged); SimulateHideNotification(id_1); - EXPECT_EQ(notification_list_view->notifications_for_testing().size(), 1u); + EXPECT_EQ(notification_list_view->items_for_testing().size(), 1u); provider()->OnBubbleClosing(); }
diff --git a/chrome/browser/ui/ash/projector/projector_app_client_impl.cc b/chrome/browser/ui/ash/projector/projector_app_client_impl.cc index 59997f3..b9abcf3 100644 --- a/chrome/browser/ui/ash/projector/projector_app_client_impl.cc +++ b/chrome/browser/ui/ash/projector/projector_app_client_impl.cc
@@ -9,6 +9,7 @@ #include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/signin/identity_manager_factory.h" #include "components/signin/public/identity_manager/identity_manager.h" +#include "content/public/browser/storage_partition.h" ProjectorAppClientImpl::ProjectorAppClientImpl() = default; ProjectorAppClientImpl::~ProjectorAppClientImpl() = default; @@ -26,3 +27,12 @@ void ProjectorAppClientImpl::RemoveObserver(Observer* observer) { observers_.RemoveObserver(observer); } + +network::mojom::URLLoaderFactory* +ProjectorAppClientImpl::GetUrlLoaderFactory() { + Profile* profile = ProfileManager::GetPrimaryUserProfile(); + DCHECK(chromeos::ProfileHelper::IsPrimaryProfile(profile)); + return profile->GetDefaultStoragePartition() + ->GetURLLoaderFactoryForBrowserProcess() + .get(); +}
diff --git a/chrome/browser/ui/ash/projector/projector_app_client_impl.h b/chrome/browser/ui/ash/projector/projector_app_client_impl.h index 65af0814..8c2f6bc8b 100644 --- a/chrome/browser/ui/ash/projector/projector_app_client_impl.h +++ b/chrome/browser/ui/ash/projector/projector_app_client_impl.h
@@ -8,6 +8,12 @@ #include "base/observer_list.h" #include "chromeos/components/projector_app/projector_app_client.h" +namespace network { +namespace mojom { +class URLLoaderFactory; +} +} // namespace network + // Implements the interface for Projector App. class ProjectorAppClientImpl : public chromeos::ProjectorAppClient { public: @@ -18,6 +24,7 @@ // chromeos::ProjectorAppClient: signin::IdentityManager* GetIdentityManager() override; + network::mojom::URLLoaderFactory* GetUrlLoaderFactory() override; void AddObserver(Observer* observer) override; void RemoveObserver(Observer* observer) override;
diff --git a/chrome/browser/ui/browser_focus_uitest.cc b/chrome/browser/ui/browser_focus_uitest.cc index 59cca50..4a3012588 100644 --- a/chrome/browser/ui/browser_focus_uitest.cc +++ b/chrome/browser/ui/browser_focus_uitest.cc
@@ -25,6 +25,7 @@ #include "chrome/browser/ui/browser_window.h" #include "chrome/browser/ui/chrome_pages.h" #include "chrome/browser/ui/find_bar/find_bar_host_unittest_util.h" +#include "chrome/browser/ui/frame/window_frame_util.h" #include "chrome/browser/ui/location_bar/location_bar.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/browser/ui/view_ids.h" @@ -125,6 +126,14 @@ reverse, false, false)); } + // From the location icon we must traverse backwards one more time to + // traverse past the tab search caption button if present. + if (WindowFrameUtil::IsWin10TabSearchCaptionButtonEnabled(browser()) && + reverse) { + ASSERT_TRUE(ui_test_utils::SendKeyPressSync(browser(), key, false, true, + false, false)); + } + for (size_t j = 0; j < base::size(kExpectedIDs); ++j) { SCOPED_TRACE(base::StringPrintf("focus inner loop %" PRIuS, j)); const size_t index = reverse ? base::size(kExpectedIDs) - 1 - j : j; @@ -161,6 +170,13 @@ } #endif + // Traverse over the tab search frame caption button if present. + if (WindowFrameUtil::IsWin10TabSearchCaptionButtonEnabled(browser()) && + !reverse) { + ASSERT_TRUE(ui_test_utils::SendKeyPressSync(browser(), key, false, + false, false, false)); + } + ui_test_utils::WaitForViewFocus( browser(), reverse ? VIEW_ID_OMNIBOX : VIEW_ID_LOCATION_ICON, true);
diff --git a/chrome/browser/ui/cocoa/task_manager_mac_browsertest.mm b/chrome/browser/ui/cocoa/task_manager_mac_browsertest.mm index caaca76..005887a 100644 --- a/chrome/browser/ui/cocoa/task_manager_mac_browsertest.mm +++ b/chrome/browser/ui/cocoa/task_manager_mac_browsertest.mm
@@ -168,7 +168,6 @@ // be nice to fake a click with -performClick: but that doesn't work (see // http://www.cocoabuilder.com/archive/cocoa/177610-programmatically-click-column-header-in-nstableview.html). bool is_sorted = false; - int sorted_col_id = -1; for (NSTableColumn* column in tableColumns) { if ([column isHidden]) continue; @@ -178,7 +177,6 @@ [[column sortDescriptorPrototype] reversedSortDescriptor]; [table setSortDescriptors:@[ newSortDescriptor ]]; is_sorted = true; - sorted_col_id = [[column identifier] intValue]; break; } }
diff --git a/chrome/browser/ui/frame/window_frame_util.cc b/chrome/browser/ui/frame/window_frame_util.cc index d50ad176..9b26827 100644 --- a/chrome/browser/ui/frame/window_frame_util.cc +++ b/chrome/browser/ui/frame/window_frame_util.cc
@@ -4,8 +4,15 @@ #include "chrome/browser/ui/frame/window_frame_util.h" +#include "build/build_config.h" #include "ui/gfx/geometry/size.h" +#if defined(OS_WIN) +#include "base/win/windows_version.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/ui_features.h" +#endif // defined(OS_WIN) + // static SkAlpha WindowFrameUtil::CalculateWindows10GlassCaptionButtonBackgroundAlpha( SkAlpha theme_alpha) { @@ -14,6 +21,8 @@ // static gfx::Size WindowFrameUtil::GetWindows10GlassCaptionButtonAreaSize() { + // TODO(crbug.com/1257470): Fix uses of this to dynamically compute the size + // of the glass caption button area. constexpr int kNumButtons = 3; return gfx::Size( @@ -21,3 +30,15 @@ ((kNumButtons - 1) * kWindows10GlassCaptionButtonVisualSpacing), kWindows10GlassCaptionButtonHeightRestored); } + +// static +bool WindowFrameUtil::IsWin10TabSearchCaptionButtonEnabled( + const Browser* browser) { +#if defined(OS_WIN) + return browser->is_type_normal() && + base::win::GetVersion() >= base::win::Version::WIN10 && + base::FeatureList::IsEnabled(features::kWin10TabSearchCaptionButton); +#else + return false; +#endif // defined(OS_WIN) +}
diff --git a/chrome/browser/ui/frame/window_frame_util.h b/chrome/browser/ui/frame/window_frame_util.h index e10a7a6..52203e9 100644 --- a/chrome/browser/ui/frame/window_frame_util.h +++ b/chrome/browser/ui/frame/window_frame_util.h
@@ -12,6 +12,8 @@ class Size; } +class Browser; + // Static-only class containing values and helper functions for frame classes // that need to be accessible outside of /browser/ui/views. class WindowFrameUtil { @@ -32,6 +34,9 @@ // browser frame view. static gfx::Size GetWindows10GlassCaptionButtonAreaSize(); + // Returns true if the windows 10 caption button is enabled. + static bool IsWin10TabSearchCaptionButtonEnabled(const Browser* browser); + private: WindowFrameUtil() {} };
diff --git a/chrome/browser/ui/global_media_controls/cast_media_notification_item.cc b/chrome/browser/ui/global_media_controls/cast_media_notification_item.cc index 22f0579..810bfd31 100644 --- a/chrome/browser/ui/global_media_controls/cast_media_notification_item.cc +++ b/chrome/browser/ui/global_media_controls/cast_media_notification_item.cc
@@ -8,11 +8,15 @@ #include "base/location.h" #include "base/metrics/histogram_functions.h" #include "base/strings/utf_string_conversions.h" +#include "chrome/browser/feature_engagement/tracker_factory.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/global_media_controls/cast_media_session_controller.h" +#include "components/feature_engagement/public/tracker.h" #include "components/global_media_controls/public/media_item_manager.h" #include "components/media_message_center/media_notification_view.h" #include "components/media_message_center/media_notification_view_impl.h" +#include "components/media_router/browser/media_router.h" +#include "components/media_router/browser/media_router_factory.h" #include "components/vector_icons/vector_icons.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/browser_task_traits.h" @@ -268,6 +272,36 @@ view_->UpdateWithMediaMetadata(metadata_); } +void CastMediaNotificationItem::StopCasting( + global_media_controls::GlobalMediaControlsEntryPoint entry_point) { + media_router::MediaRouterFactory::GetApiForBrowserContext(profile_) + ->TerminateRoute(media_route_id_); + + item_manager_->FocusDialog(); + + feature_engagement::TrackerFactory::GetForBrowserContext(profile_) + ->NotifyEvent("media_route_stopped_from_gmc"); + + global_media_controls::GlobalMediaControlsCastActionAndEntryPoint action; + switch (entry_point) { + case global_media_controls::GlobalMediaControlsEntryPoint::kToolbarIcon: + action = global_media_controls:: + GlobalMediaControlsCastActionAndEntryPoint::kStopViaToolbarIcon; + break; + case global_media_controls::GlobalMediaControlsEntryPoint::kPresentation: + action = global_media_controls:: + GlobalMediaControlsCastActionAndEntryPoint::kStopViaPresentation; + break; + case global_media_controls::GlobalMediaControlsEntryPoint::kSystemTray: + action = global_media_controls:: + GlobalMediaControlsCastActionAndEntryPoint::kStopViaSystemTray; + break; + } + base::UmaHistogramEnumeration( + media_message_center::MediaNotificationItem::kCastStartStopHistogramName, + action); +} + mojo::PendingRemote<media_router::mojom::MediaStatusObserver> CastMediaNotificationItem::GetObserverPendingRemote() { return observer_receiver_.BindNewPipeAndPassRemote();
diff --git a/chrome/browser/ui/global_media_controls/cast_media_notification_item.h b/chrome/browser/ui/global_media_controls/cast_media_notification_item.h index da9799d..d1d58a3 100644 --- a/chrome/browser/ui/global_media_controls/cast_media_notification_item.h +++ b/chrome/browser/ui/global_media_controls/cast_media_notification_item.h
@@ -8,6 +8,7 @@ #include "base/memory/weak_ptr.h" #include "chrome/browser/bitmap_fetcher/bitmap_fetcher.h" #include "chrome/browser/ui/global_media_controls/cast_media_session_controller.h" +#include "components/global_media_controls/public/constants.h" #include "components/media_message_center/media_notification_item.h" #include "components/media_router/common/media_route.h" #include "components/media_router/common/mojom/media_status.mojom.h" @@ -62,6 +63,10 @@ void OnRouteUpdated(const media_router::MediaRoute& route); + // Stops the cast session and logs UMA about the stop cast action. + void StopCasting( + global_media_controls::GlobalMediaControlsEntryPoint entry_point); + // Returns a pending remote bound to |this|. This should not be called more // than once per instance. mojo::PendingRemote<media_router::mojom::MediaStatusObserver>
diff --git a/chrome/browser/ui/global_media_controls/media_item_ui_device_selector_delegate.h b/chrome/browser/ui/global_media_controls/media_item_ui_device_selector_delegate.h new file mode 100644 index 0000000..e8a206c --- /dev/null +++ b/chrome/browser/ui/global_media_controls/media_item_ui_device_selector_delegate.h
@@ -0,0 +1,37 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_GLOBAL_MEDIA_CONTROLS_MEDIA_ITEM_UI_DEVICE_SELECTOR_DELEGATE_H_ +#define CHROME_BROWSER_UI_GLOBAL_MEDIA_CONTROLS_MEDIA_ITEM_UI_DEVICE_SELECTOR_DELEGATE_H_ + +#include "base/callback_list.h" +#include "chrome/browser/ui/global_media_controls/media_notification_device_provider.h" + +class MediaItemUIDeviceSelectorDelegate { + public: + // Called when the user selects an audio device on the + // |MediaItemUIDeviceSelectorView|. + virtual void OnAudioSinkChosen(const std::string& id, + const std::string& sink_id) = 0; + + // Used by a |MediaItemUIDeviceSelectorView| to query the system for connected + // audio output devices. + virtual base::CallbackListSubscription + RegisterAudioOutputDeviceDescriptionsCallback( + MediaNotificationDeviceProvider::GetOutputDevicesCallbackList:: + CallbackType callback) = 0; + + // Used by a |MediaItemUIDeviceSelectorView| to become notified of audio + // device switching capabilities. The callback will be immediately run with + // the current availability. + virtual base::CallbackListSubscription + RegisterIsAudioOutputDeviceSwitchingSupportedCallback( + const std::string& id, + base::RepeatingCallback<void(bool)> callback) = 0; + + protected: + virtual ~MediaItemUIDeviceSelectorDelegate() = default; +}; + +#endif // CHROME_BROWSER_UI_GLOBAL_MEDIA_CONTROLS_MEDIA_ITEM_UI_DEVICE_SELECTOR_DELEGATE_H_
diff --git a/chrome/browser/ui/global_media_controls/media_notification_service.cc b/chrome/browser/ui/global_media_controls/media_notification_service.cc index 8284753d..94537f2 100644 --- a/chrome/browser/ui/global_media_controls/media_notification_service.cc +++ b/chrome/browser/ui/global_media_controls/media_notification_service.cc
@@ -25,7 +25,6 @@ #include "components/global_media_controls/public/media_item_ui.h" #include "components/media_message_center/media_notification_item.h" #include "components/media_router/browser/presentation/start_presentation_context.h" -#include "content/public/browser/audio_service.h" #include "content/public/browser/media_session.h" #include "content/public/browser/media_session_service.h" #include "media/base/media_switches.h" @@ -142,22 +141,6 @@ : false; } -base::CallbackListSubscription -MediaNotificationService::RegisterAudioOutputDeviceDescriptionsCallback( - MediaNotificationDeviceProvider::GetOutputDevicesCallback callback) { - return media_session_notification_producer_ - ->RegisterAudioOutputDeviceDescriptionsCallback(std::move(callback)); -} - -base::CallbackListSubscription -MediaNotificationService::RegisterIsAudioOutputDeviceSwitchingSupportedCallback( - const std::string& id, - base::RepeatingCallback<void(bool)> callback) { - return media_session_notification_producer_ - ->RegisterIsAudioOutputDeviceSwitchingSupportedCallback( - id, std::move(callback)); -} - void MediaNotificationService::OnStartPresentationContextCreated( std::unique_ptr<media_router::StartPresentationContext> context) { auto* web_contents = content::WebContents::FromRenderFrameHost(
diff --git a/chrome/browser/ui/global_media_controls/media_notification_service.h b/chrome/browser/ui/global_media_controls/media_notification_service.h index a124fe7..7e398b1 100644 --- a/chrome/browser/ui/global_media_controls/media_notification_service.h +++ b/chrome/browser/ui/global_media_controls/media_notification_service.h
@@ -14,10 +14,10 @@ #include "base/memory/weak_ptr.h" #include "chrome/browser/ui/global_media_controls/cast_media_notification_producer.h" #include "chrome/browser/ui/global_media_controls/media_notification_device_provider.h" +#include "chrome/browser/ui/global_media_controls/media_session_notification_producer.h" #include "chrome/browser/ui/global_media_controls/presentation_request_notification_producer.h" #include "components/keyed_service/core/keyed_service.h" #include "components/media_router/browser/presentation/web_contents_presentation_manager.h" -#include "media/audio/audio_device_description.h" #include "third_party/abseil-cpp/absl/types/optional.h" namespace content { @@ -34,8 +34,6 @@ class CastDialogController; } // namespace media_router -class MediaSessionNotificationProducer; - class MediaNotificationService : public KeyedService { public: MediaNotificationService(Profile* profile, bool show_from_all_profiles); @@ -50,6 +48,10 @@ return item_manager_.get(); } + MediaItemUIDeviceSelectorDelegate* device_selector_delegate() { + return media_session_notification_producer_.get(); + } + void SetDialogDelegateForWebContents( global_media_controls::MediaDialogDelegate* delegate, content::WebContents* contents); @@ -62,19 +64,6 @@ // True if there are local cast notifications. bool HasLocalCastNotifications() const; - // Used by a |MediaNotificationDeviceSelectorView| to query the system - // for connected audio output devices. - base::CallbackListSubscription RegisterAudioOutputDeviceDescriptionsCallback( - MediaNotificationDeviceProvider::GetOutputDevicesCallback callback); - - // Used by a |MediaNotificationAudioDeviceSelectorView| to become notified of - // audio device switching capabilities. The callback will be immediately run - // with the current availability. - base::CallbackListSubscription - RegisterIsAudioOutputDeviceSwitchingSupportedCallback( - const std::string& id, - base::RepeatingCallback<void(bool)> callback); - void OnStartPresentationContextCreated( std::unique_ptr<media_router::StartPresentationContext> context);
diff --git a/chrome/browser/ui/global_media_controls/media_session_notification_producer.cc b/chrome/browser/ui/global_media_controls/media_session_notification_producer.cc index 058ab24..1121b3ee 100644 --- a/chrome/browser/ui/global_media_controls/media_session_notification_producer.cc +++ b/chrome/browser/ui/global_media_controls/media_session_notification_producer.cc
@@ -443,14 +443,6 @@ session->item()->Dismiss(); } -void MediaSessionNotificationProducer::OnAudioSinkChosen( - const std::string& id, - const std::string& sink_id) { - auto it = sessions_.find(id); - DCHECK(it != sessions_.end()); - it->second.SetAudioSinkId(sink_id); -} - void MediaSessionNotificationProducer::OnItemShown( const std::string& id, global_media_controls::MediaItemUI* item_ui) { @@ -560,6 +552,14 @@ .Record(recorder); } +void MediaSessionNotificationProducer::OnAudioSinkChosen( + const std::string& id, + const std::string& sink_id) { + auto it = sessions_.find(id); + DCHECK(it != sessions_.end()); + it->second.SetAudioSinkId(sink_id); +} + base::CallbackListSubscription MediaSessionNotificationProducer::RegisterAudioOutputDeviceDescriptionsCallback( MediaNotificationDeviceProvider::GetOutputDevicesCallback callback) {
diff --git a/chrome/browser/ui/global_media_controls/media_session_notification_producer.h b/chrome/browser/ui/global_media_controls/media_session_notification_producer.h index 717bf3de..e66f223 100644 --- a/chrome/browser/ui/global_media_controls/media_session_notification_producer.h +++ b/chrome/browser/ui/global_media_controls/media_session_notification_producer.h
@@ -5,6 +5,7 @@ #ifndef CHROME_BROWSER_UI_GLOBAL_MEDIA_CONTROLS_MEDIA_SESSION_NOTIFICATION_PRODUCER_H_ #define CHROME_BROWSER_UI_GLOBAL_MEDIA_CONTROLS_MEDIA_SESSION_NOTIFICATION_PRODUCER_H_ +#include "chrome/browser/ui/global_media_controls/media_item_ui_device_selector_delegate.h" #include "chrome/browser/ui/global_media_controls/media_notification_device_provider.h" #include "chrome/browser/ui/global_media_controls/media_session_notification_item.h" #include "components/global_media_controls/public/media_item_manager_observer.h" @@ -47,6 +48,7 @@ : public global_media_controls::MediaItemProducer, public MediaSessionNotificationItem::Delegate, public media_session::mojom::AudioFocusObserver, + public MediaItemUIDeviceSelectorDelegate, public global_media_controls::MediaItemUIObserver { public: MediaSessionNotificationProducer( @@ -82,8 +84,6 @@ // global_media_controls::MediaItemUIObserver implementation. void OnMediaItemUIClicked(const std::string& id) override; void OnMediaItemUIDismissed(const std::string& id) override; - void OnAudioSinkChosen(const std::string& id, - const std::string& sink_id) override; bool HasSession(const std::string& id) const; std::unique_ptr<media_router::CastDialogController> @@ -95,18 +95,16 @@ std::string GetActiveControllableSessionForWebContents( content::WebContents* web_contents) const; - // Used by a |MediaNotificationDeviceSelectorView| to query the system - // for connected audio output devices. + // MediaItemUIDeviceSelectorDelegate: + void OnAudioSinkChosen(const std::string& id, + const std::string& sink_id) override; base::CallbackListSubscription RegisterAudioOutputDeviceDescriptionsCallback( - MediaNotificationDeviceProvider::GetOutputDevicesCallback callback); - - // Used by a |MediaNotificationAudioDeviceSelectorView| to become notified of - // audio device switching capabilities. The callback will be immediately run - // with the current availability. + MediaNotificationDeviceProvider::GetOutputDevicesCallback callback) + override; base::CallbackListSubscription RegisterIsAudioOutputDeviceSwitchingSupportedCallback( const std::string& id, - base::RepeatingCallback<void(bool)> callback); + base::RepeatingCallback<void(bool)> callback) override; void OnStartPresentationContextCreated( std::unique_ptr<media_router::StartPresentationContext> context);
diff --git a/chrome/browser/ui/global_media_controls/test_helper.cc b/chrome/browser/ui/global_media_controls/test_helper.cc index 50765fe4..8735269 100644 --- a/chrome/browser/ui/global_media_controls/test_helper.cc +++ b/chrome/browser/ui/global_media_controls/test_helper.cc
@@ -7,17 +7,8 @@ #include <memory> #include <string> -#include "chrome/browser/ui/global_media_controls/media_notification_service.h" #include "testing/gmock/include/gmock/gmock.h" -MockMediaNotificationItem::MockMediaNotificationItem() = default; -MockMediaNotificationItem::~MockMediaNotificationItem() = default; - -base::WeakPtr<MockMediaNotificationItem> -MockMediaNotificationItem::GetWeakPtr() { - return weak_ptr_factory_.GetWeakPtr(); -} - MockWebContentsPresentationManager::MockWebContentsPresentationManager() = default; MockWebContentsPresentationManager::~MockWebContentsPresentationManager() =
diff --git a/chrome/browser/ui/global_media_controls/test_helper.h b/chrome/browser/ui/global_media_controls/test_helper.h index c602d403..6798179 100644 --- a/chrome/browser/ui/global_media_controls/test_helper.h +++ b/chrome/browser/ui/global_media_controls/test_helper.h
@@ -5,36 +5,12 @@ #ifndef CHROME_BROWSER_UI_GLOBAL_MEDIA_CONTROLS_TEST_HELPER_H_ #define CHROME_BROWSER_UI_GLOBAL_MEDIA_CONTROLS_TEST_HELPER_H_ -#include "components/media_message_center/media_notification_item.h" #include "components/media_router/browser/presentation/web_contents_presentation_manager.h" #include "content/public/browser/presentation_request.h" #include "testing/gmock/include/gmock/gmock.h" -using media_message_center::MediaNotificationView; using media_router::WebContentsPresentationManager; -class MockMediaNotificationItem - : public media_message_center::MediaNotificationItem { - public: - MockMediaNotificationItem(); - ~MockMediaNotificationItem() override; - - base::WeakPtr<MockMediaNotificationItem> GetWeakPtr(); - - MOCK_METHOD(void, SetView, (MediaNotificationView*)); - MOCK_METHOD(void, - OnMediaSessionActionButtonPressed, - (media_session::mojom::MediaSessionAction)); - MOCK_METHOD(void, SeekTo, (base::TimeDelta)); - MOCK_METHOD(void, Dismiss, ()); - MOCK_METHOD(void, SetVolume, (float)); - MOCK_METHOD(void, SetMute, (bool)); - MOCK_METHOD(media_message_center::SourceType, SourceType, ()); - - private: - base::WeakPtrFactory<MockMediaNotificationItem> weak_ptr_factory_{this}; -}; - class MockWebContentsPresentationManager : public WebContentsPresentationManager { public:
diff --git a/chrome/browser/ui/page_info/chrome_page_info_ui_delegate.cc b/chrome/browser/ui/page_info/chrome_page_info_ui_delegate.cc index afcd2e4..4e294a5 100644 --- a/chrome/browser/ui/page_info/chrome_page_info_ui_delegate.cc +++ b/chrome/browser/ui/page_info/chrome_page_info_ui_delegate.cc
@@ -4,6 +4,7 @@ #include "chrome/browser/ui/page_info/chrome_page_info_ui_delegate.h" +#include "base/strings/utf_string_conversions.h" #include "build/build_config.h" #include "chrome/browser/content_settings/chrome_content_settings_utils.h" #include "chrome/browser/page_info/about_this_site_service_factory.h" @@ -93,12 +94,13 @@ return std::u16string(); } -std::u16string ChromePageInfoUiDelegate::GetAboutThisSiteDescription() { +absl::optional<page_info::proto::SiteInfo> +ChromePageInfoUiDelegate::GetAboutThisSiteInfo() { if (auto* service = AboutThisSiteServiceFactory::GetForProfile(GetProfile())) { - return service->GetAboutThisSiteDescription(site_url_); + return service->GetAboutThisSiteInfo(site_url_); } - return std::u16string(); + return absl::nullopt; } bool ChromePageInfoUiDelegate::ShouldShowAsk(ContentSettingsType type) {
diff --git a/chrome/browser/ui/page_info/chrome_page_info_ui_delegate.h b/chrome/browser/ui/page_info/chrome_page_info_ui_delegate.h index 5440717..70fe2e4 100644 --- a/chrome/browser/ui/page_info/chrome_page_info_ui_delegate.h +++ b/chrome/browser/ui/page_info/chrome_page_info_ui_delegate.h
@@ -9,6 +9,7 @@ #include "build/build_config.h" #include "components/page_info/page_info_ui_delegate.h" +#include "components/page_info/proto/about_this_site_metadata.pb.h" #include "url/gurl.h" class Profile; @@ -33,8 +34,8 @@ // If "allow" option is not available, return the reason why. std::u16string GetAutomaticallyBlockedReason(ContentSettingsType type); - // Returns "About this site" description for the active page. - std::u16string GetAboutThisSiteDescription(); + // Returns "About this site" info for the active page. + absl::optional<page_info::proto::SiteInfo> GetAboutThisSiteInfo(); #if !defined(OS_ANDROID) // If PageInfo should show a link to the site or app's settings page, this
diff --git a/chrome/browser/ui/tabs/tab_menu_model.cc b/chrome/browser/ui/tabs/tab_menu_model.cc index 4149ef02..26c9863 100644 --- a/chrome/browser/ui/tabs/tab_menu_model.cc +++ b/chrome/browser/ui/tabs/tab_menu_model.cc
@@ -5,6 +5,7 @@ #include "chrome/browser/ui/tabs/tab_menu_model.h" #include "base/command_line.h" +#include "base/i18n/rtl.h" #include "base/metrics/user_metrics.h" #include "build/build_config.h" #include "chrome/app/vector_icons/vector_icons.h" @@ -158,7 +159,8 @@ AddItemWithStringId(TabStripModel::CommandCloseOtherTabs, IDS_TAB_CXMENU_CLOSEOTHERTABS); AddItemWithStringId(TabStripModel::CommandCloseTabsToRight, - IDS_TAB_CXMENU_CLOSETABSTORIGHT); + base::i18n::IsRTL() ? IDS_TAB_CXMENU_CLOSETABSTOLEFT + : IDS_TAB_CXMENU_CLOSETABSTORIGHT); } DEFINE_CLASS_ELEMENT_IDENTIFIER_VALUE(TabMenuModel,
diff --git a/chrome/browser/ui/user_education/tutorial/tutorial.cc b/chrome/browser/ui/user_education/tutorial/tutorial.cc index ec9dad2..894ce64 100644 --- a/chrome/browser/ui/user_education/tutorial/tutorial.cc +++ b/chrome/browser/ui/user_education/tutorial/tutorial.cc
@@ -24,6 +24,7 @@ Tutorial::StepBuilder::BuildFromDescriptionStep( TutorialDescription::Step step, absl::optional<std::pair<int, int>> progress, + bool is_last_step, TutorialService* tutorial_service, TutorialBubbleFactoryRegistry* bubble_factory_registry) { Tutorial::StepBuilder step_builder; @@ -33,7 +34,8 @@ .SetBodyText(step.body_text) .SetStepType(step.step_type) .SetProgress(progress) - .SetArrow(step.arrow); + .SetArrow(step.arrow) + .SetIsLastStep(is_last_step); return step_builder.Build(tutorial_service, bubble_factory_registry); } @@ -74,6 +76,12 @@ return *this; } +Tutorial::StepBuilder& Tutorial::StepBuilder::SetIsLastStep( + bool is_last_step_) { + this->is_last_step = is_last_step_; + return *this; +} + std::unique_ptr<ui::InteractionSequence::Step> Tutorial::StepBuilder::Build( TutorialService* tutorial_service, TutorialBubbleFactoryRegistry* bubble_factory_registry) { @@ -94,28 +102,29 @@ absl::optional<std::u16string> title_text_, absl::optional<std::u16string> body_text_, TutorialDescription::Step::Arrow arrow_, - absl::optional<std::pair<int, int>> progress_, + absl::optional<std::pair<int, int>> progress_, bool is_last_step_, ui::InteractionSequence* sequence, ui::TrackedElement* element) { DCHECK(tutorial_service); DCHECK(bubble_factory_registry); + tutorial_service->HideCurrentBubbleIfShowing(); + std::unique_ptr<TutorialBubble> bubble = bubble_factory_registry->CreateBubbleForTrackedElement( - element, title_text_, body_text_, arrow_, progress_); + element, title_text_, body_text_, arrow_, progress_, + is_last_step_); tutorial_service->SetCurrentBubble(std::move(bubble)); }, base::Unretained(tutorial_service), base::Unretained(bubble_factory_registry), title_text, body_text, arrow, - progress); + progress, is_last_step); } ui::InteractionSequence::StepEndCallback Tutorial::StepBuilder::BuildHideBubbleCallback( TutorialService* tutorial_service) { return base::BindOnce( - [](TutorialService* tutorial_service, ui::TrackedElement* element) { - tutorial_service->HideCurrentBubbleIfShowing(); - }, + [](TutorialService* tutorial_service, ui::TrackedElement* element) {}, base::Unretained(tutorial_service)); } @@ -142,8 +151,9 @@ int current_step = 0; for (const auto& step : description.steps) { builder.AddStep(Tutorial::StepBuilder::BuildFromDescriptionStep( - step, std::pair<int, int>(current_step, visible_step_count), - tutorial_service, bubble_factory_registry)); + step, std::pair<int, int>(current_step, visible_step_count - 1), + &step == &description.steps.back(), tutorial_service, + bubble_factory_registry)); if (step.ShouldShowBubble()) current_step++; }
diff --git a/chrome/browser/ui/user_education/tutorial/tutorial.h b/chrome/browser/ui/user_education/tutorial/tutorial.h index 623f6db..99713f5 100644 --- a/chrome/browser/ui/user_education/tutorial/tutorial.h +++ b/chrome/browser/ui/user_education/tutorial/tutorial.h
@@ -41,15 +41,27 @@ public: ~Tutorial(); + // Step Builder provides an interface for constructing an + // InteractionSequence::Step from a TutorialDescription::Step. + // TutorialDescription is used as the basis for the StepBuilder since all + // parameters of the Description will be needed to create the bubble or build + // the interaction sequence step. In order to use the The StepBuilder should + // only be used by Tutorial::Builder to construct the steps in the tutorial. class StepBuilder : public TutorialDescription::Step { public: StepBuilder(); ~StepBuilder(); + StepBuilder(const StepBuilder&) = delete; + StepBuilder& operator=(const StepBuilder&) = delete; + // Constructs the InteractionSequenceStepDirectly from the + // TutorialDescriptionStep. This method is used by + // Tutorial::Builder::BuildFromDescription to create tutorials. static std::unique_ptr<ui::InteractionSequence::Step> BuildFromDescriptionStep( TutorialDescription::Step step, absl::optional<std::pair<int, int>> progress, + bool is_last_step, TutorialService* tutorial_service, TutorialBubbleFactoryRegistry* bubble_factory_registry); @@ -57,8 +69,9 @@ StepBuilder& SetTitleText(absl::optional<std::u16string> title_text_); StepBuilder& SetBodyText(absl::optional<std::u16string> body_text_); StepBuilder& SetStepType(ui::InteractionSequence::StepType step_type_); - StepBuilder& SetProgress(absl::optional<std::pair<int, int>> progress_); StepBuilder& SetArrow(TutorialDescription::Step::Arrow arrow_); + StepBuilder& SetProgress(absl::optional<std::pair<int, int>> progress_); + StepBuilder& SetIsLastStep(bool is_last_step_); std::unique_ptr<ui::InteractionSequence::Step> Build( TutorialService* tutorial_service, @@ -66,6 +79,8 @@ private: absl::optional<std::pair<int, int>> progress; + bool is_last_step = false; + ui::InteractionSequence::StepStartCallback BuildShowBubbleCallback( TutorialService* tutorial_service, TutorialBubbleFactoryRegistry* bubble_factory_registry);
diff --git a/chrome/browser/ui/user_education/tutorial/tutorial_bubble_factory.cc b/chrome/browser/ui/user_education/tutorial/tutorial_bubble_factory.cc index ce0b48e1..67c22af 100644 --- a/chrome/browser/ui/user_education/tutorial/tutorial_bubble_factory.cc +++ b/chrome/browser/ui/user_education/tutorial/tutorial_bubble_factory.cc
@@ -15,8 +15,10 @@ absl::optional<std::u16string> title_text, absl::optional<std::u16string> body_text, TutorialDescription::Step::Arrow arrow, - absl::optional<std::pair<int, int>> progress) { - if (CanBuildBubbleForTrackedElement(element)) - return CreateBubble(element, title_text, body_text, arrow, progress); - return nullptr; + absl::optional<std::pair<int, int>> progress, + bool is_last_step) { + if (!CanBuildBubbleForTrackedElement(element)) + return nullptr; + return CreateBubble(element, title_text, body_text, arrow, progress, + is_last_step); }
diff --git a/chrome/browser/ui/user_education/tutorial/tutorial_bubble_factory.h b/chrome/browser/ui/user_education/tutorial/tutorial_bubble_factory.h index e4978bd..a0ceec8 100644 --- a/chrome/browser/ui/user_education/tutorial/tutorial_bubble_factory.h +++ b/chrome/browser/ui/user_education/tutorial/tutorial_bubble_factory.h
@@ -25,7 +25,8 @@ absl::optional<std::u16string> title_text, absl::optional<std::u16string> body_text, TutorialDescription::Step::Arrow arrow, - absl::optional<std::pair<int, int>> progress); + absl::optional<std::pair<int, int>> progress, + bool is_last_step); private: // Called by the Tutorial to show the bubble. @@ -34,7 +35,8 @@ absl::optional<std::u16string> title_text, absl::optional<std::u16string> body_text, TutorialDescription::Step::Arrow arrow, - absl::optional<std::pair<int, int>> progress) = 0; + absl::optional<std::pair<int, int>> progress, + bool is_last_step) = 0; // Returns true iff the bubble owner can show a bubble for the TrackedElement. virtual bool CanBuildBubbleForTrackedElement(ui::TrackedElement* element) = 0;
diff --git a/chrome/browser/ui/user_education/tutorial/tutorial_bubble_factory_registry.cc b/chrome/browser/ui/user_education/tutorial/tutorial_bubble_factory_registry.cc index 8adb04f..c67cde1 100644 --- a/chrome/browser/ui/user_education/tutorial/tutorial_bubble_factory_registry.cc +++ b/chrome/browser/ui/user_education/tutorial/tutorial_bubble_factory_registry.cc
@@ -24,11 +24,12 @@ absl::optional<std::u16string> title_text, absl::optional<std::u16string> body_text, TutorialDescription::Step::Arrow arrow, - absl::optional<std::pair<int, int>> progress) { + absl::optional<std::pair<int, int>> progress, + bool is_last_step) { for (const auto& bubble_factory : bubble_factories_) { std::unique_ptr<TutorialBubble> bubble = bubble_factory->CreateBubbleIfElementIsValid( - element, title_text, body_text, arrow, progress); + element, title_text, body_text, arrow, progress, is_last_step); if (bubble) return bubble; }
diff --git a/chrome/browser/ui/user_education/tutorial/tutorial_bubble_factory_registry.h b/chrome/browser/ui/user_education/tutorial/tutorial_bubble_factory_registry.h index 482e90e..70f9485 100644 --- a/chrome/browser/ui/user_education/tutorial/tutorial_bubble_factory_registry.h +++ b/chrome/browser/ui/user_education/tutorial/tutorial_bubble_factory_registry.h
@@ -34,7 +34,8 @@ absl::optional<std::u16string> title_text, absl::optional<std::u16string> body_text, TutorialDescription::Step::Arrow arrow, - absl::optional<std::pair<int, int>> progress); + absl::optional<std::pair<int, int>> progress, + bool is_last_step); private: // the list of registered bubble factories
diff --git a/chrome/browser/ui/user_education/tutorial/tutorial_service.cc b/chrome/browser/ui/user_education/tutorial/tutorial_service.cc index 53f28c8d..41800dd 100644 --- a/chrome/browser/ui/user_education/tutorial/tutorial_service.cc +++ b/chrome/browser/ui/user_education/tutorial/tutorial_service.cc
@@ -54,7 +54,7 @@ void TutorialService::HideCurrentBubbleIfShowing() { if (currently_displayed_bubble_) { - currently_displayed_bubble_.release(); + currently_displayed_bubble_.reset(); } }
diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc index 6fe66a440..f5910f1 100644 --- a/chrome/browser/ui/views/frame/browser_view.cc +++ b/chrome/browser/ui/views/frame/browser_view.cc
@@ -206,6 +206,7 @@ #include "ui/gfx/geometry/rect_conversions.h" #include "ui/gfx/scoped_canvas.h" #include "ui/gfx/scrollbar_size.h" +#include "ui/views/accessibility/view_accessibility.h" #include "ui/views/accessibility/view_accessibility_utils.h" #include "ui/views/bubble/bubble_dialog_delegate_view.h" #include "ui/views/controls/button/menu_button.h" @@ -1728,6 +1729,13 @@ if (frame_ && frame_->GetFrameView()) frame_->GetFrameView()->WindowControlsOverlayEnabledChanged(); + + GetViewAccessibility().AnnounceText( + IsWindowControlsOverlayEnabled() + ? l10n_util::GetStringUTF16( + IDS_WEB_APP_WINDOW_CONTROLS_OVERLAY_ENABLED_ALERT) + : l10n_util::GetStringUTF16( + IDS_WEB_APP_WINDOW_CONTROLS_OVERLAY_DISABLED_ALERT)); } void BrowserView::UpdateWindowControlsOverlayToggleVisible() {
diff --git a/chrome/browser/ui/views/frame/glass_browser_caption_button_container.cc b/chrome/browser/ui/views/frame/glass_browser_caption_button_container.cc index 94bf6f8..5c1acd0 100644 --- a/chrome/browser/ui/views/frame/glass_browser_caption_button_container.cc +++ b/chrome/browser/ui/views/frame/glass_browser_caption_button_container.cc
@@ -6,6 +6,7 @@ #include <memory> +#include "chrome/browser/ui/frame/window_frame_util.h" #include "chrome/browser/ui/views/frame/browser_view.h" #include "chrome/browser/ui/views/frame/glass_browser_frame_view.h" #include "chrome/browser/ui/views/frame/windows_10_caption_button.h" @@ -64,8 +65,8 @@ frame_view_, VIEW_ID_CLOSE_BUTTON, IDS_APP_ACCNAME_CLOSE))) { - if (Windows10TabSearchCaptionButton::IsTabSearchCaptionButtonEnabled( - frame_view_)) { + if (WindowFrameUtil::IsWin10TabSearchCaptionButtonEnabled( + frame_view_->browser_view()->browser())) { tab_search_button_ = AddChildViewAt(std::make_unique<Windows10TabSearchCaptionButton>( frame_view_, VIEW_ID_TAB_SEARCH_BUTTON,
diff --git a/chrome/browser/ui/views/frame/tab_strip_region_view.cc b/chrome/browser/ui/views/frame/tab_strip_region_view.cc index 3ffee76..6150e79 100644 --- a/chrome/browser/ui/views/frame/tab_strip_region_view.cc +++ b/chrome/browser/ui/views/frame/tab_strip_region_view.cc
@@ -8,6 +8,7 @@ #include "base/strings/utf_string_conversions.h" #include "build/build_config.h" #include "chrome/browser/themes/theme_properties.h" +#include "chrome/browser/ui/frame/window_frame_util.h" #include "chrome/browser/ui/layout_constants.h" #include "chrome/browser/ui/ui_features.h" #include "chrome/browser/ui/views/chrome_layout_provider.h" @@ -127,12 +128,13 @@ return; #endif -#if defined(OS_WIN) - if (base::FeatureList::IsEnabled(features::kWin10TabSearchCaptionButton)) - return; -#endif const Browser* browser = tab_strip_->controller()->GetBrowser(); - if (browser && browser->is_type_normal()) { + if (!browser || + WindowFrameUtil::IsWin10TabSearchCaptionButtonEnabled(browser)) { + return; + } + + if (browser->is_type_normal()) { auto tab_search_button = std::make_unique<TabSearchButton>(tab_strip_); tab_search_button->SetTooltipText( l10n_util::GetStringUTF16(IDS_TOOLTIP_TAB_SEARCH));
diff --git a/chrome/browser/ui/views/frame/windows_10_caption_button.cc b/chrome/browser/ui/views/frame/windows_10_caption_button.cc index e1461542..d14e6f7 100644 --- a/chrome/browser/ui/views/frame/windows_10_caption_button.cc +++ b/chrome/browser/ui/views/frame/windows_10_caption_button.cc
@@ -9,7 +9,6 @@ #include "chrome/browser/ui/frame/window_frame_util.h" #include "chrome/browser/ui/views/frame/browser_view.h" #include "chrome/browser/ui/views/frame/glass_browser_frame_view.h" -#include "chrome/browser/ui/views/frame/windows_10_tab_search_caption_button.h" #include "chrome/grit/theme_resources.h" #include "ui/base/metadata/metadata_impl_macros.h" #include "ui/base/theme_provider.h" @@ -147,8 +146,8 @@ int Windows10CaptionButton::GetButtonDisplayOrderIndex() const { int button_display_order = 0; const bool tab_search_enabled = - Windows10TabSearchCaptionButton::IsTabSearchCaptionButtonEnabled( - frame_view_); + WindowFrameUtil::IsWin10TabSearchCaptionButtonEnabled( + frame_view_->browser_view()->browser()); switch (button_type_) { case VIEW_ID_TAB_SEARCH_BUTTON: button_display_order = 0;
diff --git a/chrome/browser/ui/views/frame/windows_10_tab_search_caption_button.cc b/chrome/browser/ui/views/frame/windows_10_tab_search_caption_button.cc index 1bb9e4e..23edbdf 100644 --- a/chrome/browser/ui/views/frame/windows_10_tab_search_caption_button.cc +++ b/chrome/browser/ui/views/frame/windows_10_tab_search_caption_button.cc
@@ -4,19 +4,11 @@ #include "chrome/browser/ui/views/frame/windows_10_tab_search_caption_button.h" -#include "chrome/browser/ui/ui_features.h" #include "chrome/browser/ui/views/frame/browser_view.h" #include "chrome/browser/ui/views/frame/glass_browser_frame_view.h" #include "chrome/browser/ui/views/tab_search_bubble_host.h" #include "ui/base/metadata/metadata_impl_macros.h" -// static. -bool Windows10TabSearchCaptionButton::IsTabSearchCaptionButtonEnabled( - BrowserNonClientFrameView* frame_view) { - return frame_view->browser_view()->GetIsNormalType() && - base::FeatureList::IsEnabled(features::kWin10TabSearchCaptionButton); -} - Windows10TabSearchCaptionButton::Windows10TabSearchCaptionButton( GlassBrowserFrameView* frame_view, ViewID button_type,
diff --git a/chrome/browser/ui/views/frame/windows_10_tab_search_caption_button.h b/chrome/browser/ui/views/frame/windows_10_tab_search_caption_button.h index 57498c9..d38bf024 100644 --- a/chrome/browser/ui/views/frame/windows_10_tab_search_caption_button.h +++ b/chrome/browser/ui/views/frame/windows_10_tab_search_caption_button.h
@@ -8,17 +8,12 @@ #include "chrome/browser/ui/views/frame/windows_10_caption_button.h" #include "ui/base/metadata/metadata_header_macros.h" -class BrowserNonClientFrameView; class GlassBrowserFrameView; class TabSearchBubbleHost; class Windows10TabSearchCaptionButton : public Windows10CaptionButton { public: METADATA_HEADER(Windows10TabSearchCaptionButton); - - static bool IsTabSearchCaptionButtonEnabled( - BrowserNonClientFrameView* frame_view); - Windows10TabSearchCaptionButton(GlassBrowserFrameView* frame_view, ViewID button_type, const std::u16string& accessible_name);
diff --git a/chrome/browser/ui/views/global_media_controls/media_dialog_view.cc b/chrome/browser/ui/views/global_media_controls/media_dialog_view.cc index 53797f6..c3023d3 100644 --- a/chrome/browser/ui/views/global_media_controls/media_dialog_view.cc +++ b/chrome/browser/ui/views/global_media_controls/media_dialog_view.cc
@@ -11,15 +11,19 @@ #include "base/bind.h" #include "base/metrics/histogram_functions.h" #include "base/strings/utf_string_conversions.h" +#include "chrome/browser/media/router/media_router_feature.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/global_media_controls/media_notification_service.h" #include "chrome/browser/ui/views/chrome_layout_provider.h" #include "chrome/browser/ui/views/global_media_controls/media_dialog_view_observer.h" -#include "chrome/browser/ui/views/global_media_controls/media_notification_container_impl_view.h" -#include "chrome/browser/ui/views/global_media_controls/media_notification_list_view.h" +#include "chrome/browser/ui/views/global_media_controls/media_item_ui_device_selector_view.h" +#include "chrome/browser/ui/views/global_media_controls/media_item_ui_footer_view.h" +#include "chrome/browser/ui/views/global_media_controls/media_item_ui_legacy_cast_footer_view.h" #include "chrome/browser/ui/views/user_education/new_badge_label.h" #include "chrome/grit/generated_resources.h" #include "components/global_media_controls/public/media_item_manager.h" +#include "components/global_media_controls/public/views/media_item_ui_list_view.h" +#include "components/global_media_controls/public/views/media_item_ui_view.h" #include "components/live_caption/pref_names.h" #include "components/soda/constants.h" #include "components/sync_preferences/pref_service_syncable.h" @@ -61,7 +65,7 @@ views::View* anchor_view, MediaNotificationService* service, Profile* profile, - GlobalMediaControlsEntryPoint entry_point) { + global_media_controls::GlobalMediaControlsEntryPoint entry_point) { return ShowDialogForPresentationRequest(anchor_view, service, profile, nullptr, entry_point); } @@ -72,7 +76,7 @@ MediaNotificationService* service, Profile* profile, content::WebContents* contents, - GlobalMediaControlsEntryPoint entry_point) { + global_media_controls::GlobalMediaControlsEntryPoint entry_point) { DCHECK(!instance_); DCHECK(service); instance_ = @@ -113,23 +117,22 @@ global_media_controls::MediaItemUI* MediaDialogView::ShowMediaItem( const std::string& id, base::WeakPtr<media_message_center::MediaNotificationItem> item) { - auto container = std::make_unique<MediaNotificationContainerImplView>( - id, item, service_, entry_point_, profile_); - MediaNotificationContainerImplView* container_ptr = container.get(); - container_ptr->AddObserver(this); - observed_containers_[id] = container_ptr; + auto view = BuildMediaItemUIView(id, item); + auto* view_ptr = view.get(); + view_ptr->AddObserver(this); + observed_items_[id] = view_ptr; - active_sessions_view_->ShowNotification(id, std::move(container)); + active_sessions_view_->ShowItem(id, std::move(view)); UpdateBubbleSize(); for (auto& observer : observers_) observer.OnMediaSessionShown(); - return container_ptr; + return view_ptr; } void MediaDialogView::HideMediaItem(const std::string& id) { - active_sessions_view_->HideNotification(id); + active_sessions_view_->HideItem(id); if (active_sessions_view_->empty()) HideDialog(); @@ -155,7 +158,8 @@ if (frame) { frame->SetCornerRadius(corner_radius); } - if (entry_point_ == GlobalMediaControlsEntryPoint::kPresentation) { + if (entry_point_ == + global_media_controls::GlobalMediaControlsEntryPoint::kPresentation) { service_->SetDialogDelegateForWebContents( this, web_contents_for_presentation_request_); } else { @@ -200,11 +204,11 @@ } void MediaDialogView::OnMediaItemUIDestroyed(const std::string& id) { - auto iter = observed_containers_.find(id); - DCHECK(iter != observed_containers_.end()); + auto iter = observed_items_.find(id); + DCHECK(iter != observed_items_.end()); iter->second->RemoveObserver(this); - observed_containers_.erase(iter); + observed_items_.erase(iter); } void MediaDialogView::AddObserver(MediaDialogViewObserver* observer) { @@ -215,26 +219,27 @@ observers_.RemoveObserver(observer); } -const std::map<const std::string, MediaNotificationContainerImplView*>& -MediaDialogView::GetNotificationsForTesting() const { - return active_sessions_view_->notifications_for_testing(); +const std::map<const std::string, global_media_controls::MediaItemUIView*>& +MediaDialogView::GetItemsForTesting() const { + return active_sessions_view_->items_for_testing(); // IN-TEST } -const MediaNotificationListView* MediaDialogView::GetListViewForTesting() - const { +const global_media_controls::MediaItemUIListView* +MediaDialogView::GetListViewForTesting() const { return active_sessions_view_; } -MediaDialogView::MediaDialogView(views::View* anchor_view, - MediaNotificationService* service, - Profile* profile, - content::WebContents* contents, - GlobalMediaControlsEntryPoint entry_point) +MediaDialogView::MediaDialogView( + views::View* anchor_view, + MediaNotificationService* service, + Profile* profile, + content::WebContents* contents, + global_media_controls::GlobalMediaControlsEntryPoint entry_point) : BubbleDialogDelegateView(anchor_view, views::BubbleBorder::TOP_RIGHT), service_(service), profile_(profile->GetOriginalProfile()), - active_sessions_view_( - AddChildView(std::make_unique<MediaNotificationListView>())), + active_sessions_view_(AddChildView( + std::make_unique<global_media_controls::MediaItemUIListView>())), web_contents_for_presentation_request_(contents), entry_point_(entry_point) { // Enable layer based clipping to ensure children using layers are clipped @@ -247,8 +252,8 @@ } MediaDialogView::~MediaDialogView() { - for (auto container_pair : observed_containers_) - container_pair.second->RemoveObserver(this); + for (auto item_pair : observed_items_) + item_pair.second->RemoveObserver(this); } void MediaDialogView::Init() { @@ -374,5 +379,66 @@ combined_progress)); } +std::unique_ptr<global_media_controls::MediaItemUIView> +MediaDialogView::BuildMediaItemUIView( + const std::string& id, + base::WeakPtr<media_message_center::MediaNotificationItem> item) { + const bool is_cast_item = + item->SourceType() == media_message_center::SourceType::kCast; + const bool is_local_media_session = + item->SourceType() == + media_message_center::SourceType::kLocalMediaSession; + const bool gmc_cast_start_stop_enabled = + media_router::GlobalMediaControlsCastStartStopEnabled() && + media_router::MediaRouterEnabled(profile_); + + // Show a device selector view for media and supplemental notifications. + std::unique_ptr<MediaItemUIDeviceSelectorView> device_selector_view; + if (!is_cast_item && (gmc_cast_start_stop_enabled || + base::FeatureList::IsEnabled( + media::kGlobalMediaControlsSeamlessTransfer))) { + const bool show_expand_button = + !base::FeatureList::IsEnabled(media::kGlobalMediaControlsModernUI); + std::unique_ptr<media_router::CastDialogController> cast_controller; + if (media_router::GlobalMediaControlsCastStartStopEnabled() && + media_router::MediaRouterEnabled(profile_)) { + cast_controller = + is_local_media_session + ? service_->CreateCastDialogControllerForSession(id) + : service_->CreateCastDialogControllerForPresentationRequest(); + } + device_selector_view = std::make_unique<MediaItemUIDeviceSelectorView>( + id, service_->device_selector_delegate(), std::move(cast_controller), + /* has_audio_output */ is_local_media_session, entry_point_, + show_expand_button); + } + + base::RepeatingClosure stop_casting_closure = + is_cast_item ? base::BindRepeating( + &CastMediaNotificationItem::StopCasting, + static_cast<CastMediaNotificationItem*>(item.get()) + ->GetWeakPtr(), + entry_point_) + : base::NullCallback(); + + std::unique_ptr<global_media_controls::MediaItemUIFooter> footer_view; + if (base::FeatureList::IsEnabled(media::kGlobalMediaControlsModernUI)) { + footer_view = std::make_unique<MediaItemUIFooterView>(stop_casting_closure); + + if (device_selector_view) { + auto* modern_footer = + static_cast<MediaItemUIFooterView*>(footer_view.get()); + modern_footer->SetDelegate(device_selector_view.get()); + device_selector_view->AddObserver(modern_footer); + } + } else if (is_cast_item && gmc_cast_start_stop_enabled) { + footer_view = + std::make_unique<MediaItemUILegacyCastFooterView>(stop_casting_closure); + } + + return std::make_unique<global_media_controls::MediaItemUIView>( + id, item, std::move(footer_view), std::move(device_selector_view)); +} + BEGIN_METADATA(MediaDialogView, views::BubbleDialogDelegateView) END_METADATA
diff --git a/chrome/browser/ui/views/global_media_controls/media_dialog_view.h b/chrome/browser/ui/views/global_media_controls/media_dialog_view.h index ebd9631..60235c6 100644 --- a/chrome/browser/ui/views/global_media_controls/media_dialog_view.h +++ b/chrome/browser/ui/views/global_media_controls/media_dialog_view.h
@@ -10,7 +10,7 @@ #include <string> #include "base/observer_list.h" -#include "chrome/browser/ui/views/global_media_controls/global_media_controls_types.h" +#include "components/global_media_controls/public/constants.h" #include "components/global_media_controls/public/media_dialog_delegate.h" #include "components/global_media_controls/public/media_item_ui_observer.h" #include "components/soda/constants.h" @@ -18,21 +18,24 @@ #include "ui/base/metadata/metadata_header_macros.h" #include "ui/views/bubble/bubble_dialog_delegate_view.h" -class MediaDialogViewObserver; -class MediaNotificationContainerImplView; -class MediaNotificationListView; -class MediaNotificationService; -class NewBadgeLabel; -class Profile; +namespace content { +class WebContents; +} // namespace content + +namespace global_media_controls { +class MediaItemUIListView; +class MediaItemUIView; +} // namespace global_media_controls namespace views { class Label; class ToggleButton; } // namespace views -namespace content { -class WebContents; -} // namespace content +class MediaDialogViewObserver; +class MediaNotificationService; +class NewBadgeLabel; +class Profile; // Dialog that shows media controls that control the active media session. class MediaDialogView : public views::BubbleDialogDelegateView, @@ -45,16 +48,17 @@ MediaDialogView(const MediaDialogView&) = delete; MediaDialogView& operator=(const MediaDialogView&) = delete; - static views::Widget* ShowDialog(views::View* anchor_view, - MediaNotificationService* service, - Profile* profile, - GlobalMediaControlsEntryPoint entry_point); + static views::Widget* ShowDialog( + views::View* anchor_view, + MediaNotificationService* service, + Profile* profile, + global_media_controls::GlobalMediaControlsEntryPoint entry_point); static views::Widget* ShowDialogForPresentationRequest( views::View* anchor_view, MediaNotificationService* service, Profile* profile, content::WebContents* contents, - GlobalMediaControlsEntryPoint entry_point); + global_media_controls::GlobalMediaControlsEntryPoint entry_point); static void HideDialog(); static bool IsShowing(); @@ -79,24 +83,24 @@ void OnMediaItemUIClicked(const std::string& id) override {} void OnMediaItemUIDismissed(const std::string& id) override {} void OnMediaItemUIDestroyed(const std::string& id) override; - void OnAudioSinkChosen(const std::string& id, - const std::string& sink_id) override {} void AddObserver(MediaDialogViewObserver* observer); void RemoveObserver(MediaDialogViewObserver* observer); - const std::map<const std::string, MediaNotificationContainerImplView*>& - GetNotificationsForTesting() const; + const std::map<const std::string, global_media_controls::MediaItemUIView*>& + GetItemsForTesting() const; - const MediaNotificationListView* GetListViewForTesting() const; + const global_media_controls::MediaItemUIListView* GetListViewForTesting() + const; private: friend class MediaDialogViewBrowserTest; - MediaDialogView(views::View* anchor_view, - MediaNotificationService* service, - Profile* profile, - content::WebContents* contents, - GlobalMediaControlsEntryPoint entry_point); + MediaDialogView( + views::View* anchor_view, + MediaNotificationService* service, + Profile* profile, + content::WebContents* contents, + global_media_controls::GlobalMediaControlsEntryPoint entry_point); ~MediaDialogView() override; @@ -126,17 +130,21 @@ speech::LanguageCode language_code) override { } + std::unique_ptr<global_media_controls::MediaItemUIView> BuildMediaItemUIView( + const std::string& id, + base::WeakPtr<media_message_center::MediaNotificationItem> item); + MediaNotificationService* const service_; Profile* const profile_; - MediaNotificationListView* const active_sessions_view_; + global_media_controls::MediaItemUIListView* const active_sessions_view_; base::ObserverList<MediaDialogViewObserver> observers_; // A map of all containers we're currently observing. - std::map<const std::string, MediaNotificationContainerImplView*> - observed_containers_; + std::map<const std::string, global_media_controls::MediaItemUIView*> + observed_items_; views::View* live_caption_container_ = nullptr; // TODO(crbug.com/1055150): Remove live_caption_title_new_badge_ by M93. @@ -148,7 +156,7 @@ // opened the dialog for a presentation request. It is nullptr if the dialog // is opened from the toolbar. content::WebContents* const web_contents_for_presentation_request_ = nullptr; - const GlobalMediaControlsEntryPoint entry_point_; + const global_media_controls::GlobalMediaControlsEntryPoint entry_point_; }; #endif // CHROME_BROWSER_UI_VIEWS_GLOBAL_MEDIA_CONTROLS_MEDIA_DIALOG_VIEW_H_
diff --git a/chrome/browser/ui/views/global_media_controls/media_dialog_view_interactive_browsertest.cc b/chrome/browser/ui/views/global_media_controls/media_dialog_view_interactive_browsertest.cc index 9853a992..e25aae3 100644 --- a/chrome/browser/ui/views/global_media_controls/media_dialog_view_interactive_browsertest.cc +++ b/chrome/browser/ui/views/global_media_controls/media_dialog_view_interactive_browsertest.cc
@@ -16,8 +16,6 @@ #include "chrome/browser/ui/global_media_controls/media_toolbar_button_observer.h" #include "chrome/browser/ui/views/frame/browser_view.h" #include "chrome/browser/ui/views/global_media_controls/media_dialog_view_observer.h" -#include "chrome/browser/ui/views/global_media_controls/media_notification_container_impl_view.h" -#include "chrome/browser/ui/views/global_media_controls/media_notification_list_view.h" #include "chrome/browser/ui/views/global_media_controls/media_toolbar_button_view.h" #include "chrome/browser/ui/views/toolbar/toolbar_view.h" #include "chrome/browser/ui/views/user_education/new_badge_label.h" @@ -26,6 +24,8 @@ #include "chrome/test/base/interactive_test_utils.h" #include "chrome/test/base/ui_test_utils.h" #include "components/feature_engagement/public/feature_constants.h" +#include "components/global_media_controls/public/views/media_item_ui_list_view.h" +#include "components/global_media_controls/public/views/media_item_ui_view.h" #include "components/media_message_center/media_notification_view_impl.h" #include "components/media_router/browser/presentation/web_contents_presentation_manager.h" #include "components/media_router/browser/test/mock_media_router.h" @@ -120,12 +120,12 @@ Wait(); } - void WaitForNotificationCount(int count) { - if (GetNotificationCount() == count) + void WaitForItemCount(int count) { + if (GetItemCount() == count) return; - waiting_for_notification_count_ = true; - expected_notification_count_ = count; + waiting_for_item_count_ = true; + expected_item_count_ = count; observed_dialog_ = MediaDialogView::GetDialogViewForTesting(); observed_dialog_->AddObserver(this); Wait(); @@ -154,14 +154,14 @@ MaybeStopWaiting(); } - void CheckNotificationCount() { - if (!waiting_for_notification_count_) + void CheckItemCount() { + if (!waiting_for_item_count_) return; - if (GetNotificationCount() != expected_notification_count_) + if (GetItemCount() != expected_item_count_) return; - waiting_for_notification_count_ = false; + waiting_for_item_count_ = false; MaybeStopWaiting(); } @@ -181,8 +181,7 @@ return; if (!waiting_for_dialog_opened_ && !waiting_for_button_shown_ && - !waiting_for_dialog_to_contain_text_ && - !waiting_for_notification_count_ && + !waiting_for_dialog_to_contain_text_ && !waiting_for_item_count_ && !waiting_for_pip_visibility_changed_) { run_loop_->Quit(); } @@ -194,14 +193,13 @@ run_loop_->Run(); } - // Checks the title and artist of each notification in the dialog to see if + // Checks the title and artist of each item in the dialog to see if // |text| is contained anywhere in the dialog. bool DialogContainsText(const std::u16string& text) { - for (const auto& notification_pair : - MediaDialogView::GetDialogViewForTesting() - ->GetNotificationsForTesting()) { + for (const auto& item_pair : + MediaDialogView::GetDialogViewForTesting()->GetItemsForTesting()) { const media_message_center::MediaNotificationViewImpl* view = - notification_pair.second->view_for_testing(); + item_pair.second->view_for_testing(); if (view->title_label_for_testing()->GetText().find(text) != std::string::npos || view->artist_label_for_testing()->GetText().find(text) != @@ -214,19 +212,19 @@ } bool CheckPictureInPictureButtonVisibility(bool visible) { - const auto notification_pair = MediaDialogView::GetDialogViewForTesting() - ->GetNotificationsForTesting() - .begin(); + const auto item_pair = MediaDialogView::GetDialogViewForTesting() + ->GetItemsForTesting() + .begin(); const media_message_center::MediaNotificationViewImpl* view = - notification_pair->second->view_for_testing(); + item_pair->second->view_for_testing(); return view->picture_in_picture_button_for_testing()->GetVisible() == visible; } - int GetNotificationCount() { + int GetItemCount() { return MediaDialogView::GetDialogViewForTesting() - ->GetNotificationsForTesting() + ->GetItemsForTesting() .size(); } @@ -235,13 +233,13 @@ bool waiting_for_dialog_opened_ = false; bool waiting_for_button_shown_ = false; - bool waiting_for_notification_count_ = false; + bool waiting_for_item_count_ = false; bool waiting_for_pip_visibility_changed_ = false; MediaDialogView* observed_dialog_ = nullptr; bool waiting_for_dialog_to_contain_text_ = false; std::u16string expected_text_; - int expected_notification_count_ = 0; + int expected_item_count_ = 0; bool expected_pip_visibility_ = false; }; @@ -470,8 +468,8 @@ .WaitForDialogToContainText(text); } - void WaitForNotificationCount(int count) { - MediaToolbarButtonWatcher(GetToolbarIcon()).WaitForNotificationCount(count); + void WaitForItemCount(int count) { + MediaToolbarButtonWatcher(GetToolbarIcon()).WaitForItemCount(count); } void WaitForPictureInPictureButtonVisibility(bool visible) { @@ -511,12 +509,11 @@ ClickButton(live_caption_button); } - void ClickNotificationByTitle(const std::u16string& title) { + void ClickItemByTitle(const std::u16string& title) { ASSERT_TRUE(MediaDialogView::IsShowing()); - MediaNotificationContainerImplView* notification = - GetNotificationByTitle(title); - ASSERT_NE(nullptr, notification); - ClickButton(notification); + global_media_controls::MediaItemUIView* item = GetItemByTitle(title); + ASSERT_NE(nullptr, item); + ClickButton(item); } content::WebContents* GetActiveWebContents() { @@ -529,13 +526,13 @@ ->GetListViewForTesting() ->contents() ->children()) { - MediaNotificationContainerImplView* notification = - static_cast<MediaNotificationContainerImplView*>(view); + global_media_controls::MediaItemUIView* item = + static_cast<global_media_controls::MediaItemUIView*>(view); - if (seen_paused && notification->is_playing_for_testing()) + if (seen_paused && item->is_playing_for_testing()) return false; - if (!seen_paused && !notification->is_playing_for_testing()) + if (!seen_paused && !item->is_playing_for_testing()) seen_paused = true; } @@ -612,16 +609,15 @@ return nullptr; } - // Finds a MediaNotificationContainerImplView by title. - MediaNotificationContainerImplView* GetNotificationByTitle( + // Finds a global_media_controls::MediaItemUIView by title. + global_media_controls::MediaItemUIView* GetItemByTitle( const std::u16string& title) { - for (const auto& notification_pair : - MediaDialogView::GetDialogViewForTesting() - ->GetNotificationsForTesting()) { + for (const auto& item_pair : + MediaDialogView::GetDialogViewForTesting()->GetItemsForTesting()) { const media_message_center::MediaNotificationViewImpl* view = - notification_pair.second->view_for_testing(); + item_pair.second->view_for_testing(); if (view->title_label_for_testing()->GetText() == title) - return notification_pair.second; + return item_pair.second; } return nullptr; } @@ -723,7 +719,7 @@ // The view containing playback controls should not be mirrored. EXPECT_FALSE(MediaDialogView::GetDialogViewForTesting() - ->GetNotificationsForTesting() + ->GetItemsForTesting() .begin() ->second->view_for_testing() ->playback_button_container_for_testing() @@ -788,7 +784,7 @@ } IN_PROC_BROWSER_TEST_F(MediaDialogViewBrowserTest, - ClickingOnNotificationGoesBackToTab) { + ClickingOnItemGoesBackToTab) { // Open a tab and play media. OpenTestURL(); StartPlayback(); @@ -818,8 +814,8 @@ // The second tab should be the active tab. EXPECT_EQ(second_web_contents, GetActiveWebContents()); - // Clicking the first notification should make the first tab active. - ClickNotificationByTitle(u"Big Buck Bunny"); + // Clicking the first item should make the first tab active. + ClickItemByTitle(u"Big Buck Bunny"); // Allow the MediaSessionNotificationItem to flush its message to the // MediaSessionImpl. There isn't currently a clean way for us to access the @@ -850,7 +846,7 @@ EXPECT_TRUE(WaitForDialogOpened()); WaitForDialogToContainText( base::UTF8ToUTF16(route_description + " \xC2\xB7 " + sink_name)); - WaitForNotificationCount(1); + WaitForItemCount(1); } #if defined(OS_MAC) && defined(ARCH_CPU_ARM64)
diff --git a/chrome/browser/ui/views/global_media_controls/media_item_ui_device_selector_observer.h b/chrome/browser/ui/views/global_media_controls/media_item_ui_device_selector_observer.h new file mode 100644 index 0000000..e32644a --- /dev/null +++ b/chrome/browser/ui/views/global_media_controls/media_item_ui_device_selector_observer.h
@@ -0,0 +1,22 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_VIEWS_GLOBAL_MEDIA_CONTROLS_MEDIA_ITEM_UI_DEVICE_SELECTOR_OBSERVER_H_ +#define CHROME_BROWSER_UI_VIEWS_GLOBAL_MEDIA_CONTROLS_MEDIA_ITEM_UI_DEVICE_SELECTOR_OBSERVER_H_ + +#include <map> + +#include "base/observer_list_types.h" + +class DeviceEntryUI; + +class MediaItemUIDeviceSelectorObserver : public base::CheckedObserver { + public: + // Called by MediaNotificationDeviceSelector view when available devices + // changed. + virtual void OnMediaItemUIDeviceSelectorUpdated( + const std::map<int, DeviceEntryUI*>& device_entries_map) = 0; +}; + +#endif // CHROME_BROWSER_UI_VIEWS_GLOBAL_MEDIA_CONTROLS_MEDIA_ITEM_UI_DEVICE_SELECTOR_OBSERVER_H_
diff --git a/chrome/browser/ui/views/global_media_controls/media_notification_device_selector_view.cc b/chrome/browser/ui/views/global_media_controls/media_item_ui_device_selector_view.cc similarity index 74% rename from chrome/browser/ui/views/global_media_controls/media_notification_device_selector_view.cc rename to chrome/browser/ui/views/global_media_controls/media_item_ui_device_selector_view.cc index 792fa7b..fced918 100644 --- a/chrome/browser/ui/views/global_media_controls/media_notification_device_selector_view.cc +++ b/chrome/browser/ui/views/global_media_controls/media_item_ui_device_selector_view.cc
@@ -2,19 +2,20 @@ // 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/global_media_controls/media_notification_device_selector_view.h" +#include "chrome/browser/ui/views/global_media_controls/media_item_ui_device_selector_view.h" #include "base/bind.h" #include "base/containers/contains.h" #include "base/metrics/histogram_functions.h" #include "base/ranges/algorithm.h" #include "base/strings/utf_string_conversions.h" +#include "chrome/browser/ui/global_media_controls/media_item_ui_device_selector_delegate.h" #include "chrome/browser/ui/media_router/cast_dialog_model.h" #include "chrome/browser/ui/media_router/ui_media_sink.h" -#include "chrome/browser/ui/views/global_media_controls/media_notification_device_selector_observer.h" -#include "chrome/browser/ui/views/global_media_controls/media_notification_device_selector_view_delegate.h" +#include "chrome/browser/ui/views/global_media_controls/media_item_ui_device_selector_observer.h" #include "chrome/browser/ui/views/media_router/cast_dialog_sink_button.h" #include "chrome/grit/generated_resources.h" +#include "components/global_media_controls/public/views/media_item_ui_view.h" #include "components/media_message_center/media_notification_item.h" #include "components/media_router/browser/media_router_metrics.h" #include "components/media_router/common/media_sink.h" @@ -38,7 +39,7 @@ namespace { -// Constants for the MediaNotificationDeviceSelectorView +// Constants for the MediaItemUIDeviceSelectorView constexpr gfx::Insets kExpandButtonStripInsets{6, 15}; constexpr gfx::Size kExpandButtonStripSize{400, 30}; constexpr gfx::Insets kExpandButtonBorderInsets{4, 8}; @@ -50,19 +51,20 @@ const int kAudioDevicesCountHistogramMax = 30; media_router::MediaRouterDialogOpenOrigin ConvertToOrigin( - GlobalMediaControlsEntryPoint entry_point) { + global_media_controls::GlobalMediaControlsEntryPoint entry_point) { switch (entry_point) { - case GlobalMediaControlsEntryPoint::kPresentation: + case global_media_controls::GlobalMediaControlsEntryPoint::kPresentation: return media_router::MediaRouterDialogOpenOrigin::PAGE; - case GlobalMediaControlsEntryPoint::kSystemTray: + case global_media_controls::GlobalMediaControlsEntryPoint::kSystemTray: return media_router::MediaRouterDialogOpenOrigin::SYSTEM_TRAY; - case GlobalMediaControlsEntryPoint::kToolbarIcon: + case global_media_controls::GlobalMediaControlsEntryPoint::kToolbarIcon: return media_router::MediaRouterDialogOpenOrigin::TOOLBAR; } } -void RecordCastDeviceCountMetrics(GlobalMediaControlsEntryPoint entry_point, - std::vector<CastDeviceEntryView*> entries) { +void RecordCastDeviceCountMetrics( + global_media_controls::GlobalMediaControlsEntryPoint entry_point, + std::vector<CastDeviceEntryView*> entries) { MediaRouterMetrics::RecordDeviceCount(entries.size()); std::map<MediaRouteProviderId, std::map<bool, int>> counts = { @@ -132,20 +134,14 @@ delegate_->GetIconLabelBubbleSurroundingForegroundColor())); } -MediaNotificationDeviceSelectorView::MediaNotificationDeviceSelectorView( - MediaNotificationDeviceSelectorViewDelegate* delegate, +MediaItemUIDeviceSelectorView::MediaItemUIDeviceSelectorView( + const std::string& item_id, + MediaItemUIDeviceSelectorDelegate* delegate, std::unique_ptr<media_router::CastDialogController> cast_controller, bool has_audio_output, - const std::string& current_device_id, - const SkColor& foreground_color, - const SkColor& background_color, - GlobalMediaControlsEntryPoint entry_point, + global_media_controls::GlobalMediaControlsEntryPoint entry_point, bool show_expand_button) - : delegate_(delegate), - current_device_id_(current_device_id), - foreground_color_(foreground_color), - background_color_(background_color), - entry_point_(entry_point) { + : item_id_(item_id), delegate_(delegate), entry_point_(entry_point) { SetLayoutManager(std::make_unique<views::BoxLayout>( views::BoxLayout::Orientation::kVertical)); @@ -162,9 +158,9 @@ expand_button_ = expand_button_strip_->AddChildView( std::make_unique<ExpandDeviceSelectorButton>(this)); - expand_button_->SetCallback(base::BindRepeating( - &MediaNotificationDeviceSelectorView::ExpandButtonPressed, - base::Unretained(this))); + expand_button_->SetCallback( + base::BindRepeating(&MediaItemUIDeviceSelectorView::ExpandButtonPressed, + base::Unretained(this))); if (!show_expand_button) expand_button_strip_->SetVisible(false); @@ -175,7 +171,8 @@ views::BoxLayout::Orientation::kVertical)); device_entry_views_container_->SetVisible(false); - if (entry_point_ == GlobalMediaControlsEntryPoint::kPresentation) { + if (entry_point_ == + global_media_controls::GlobalMediaControlsEntryPoint::kPresentation) { ShowDevices(); } SetBackground(views::CreateSolidBackground(background_color_)); @@ -197,7 +194,7 @@ } } -void MediaNotificationDeviceSelectorView::UpdateCurrentAudioDevice( +void MediaItemUIDeviceSelectorView::UpdateCurrentAudioDevice( const std::string& current_device_id) { if (current_audio_device_entry_view_) current_audio_device_entry_view_->SetHighlighted(false); @@ -222,7 +219,7 @@ current_audio_device_entry_view_->Layout(); } -MediaNotificationDeviceSelectorView::~MediaNotificationDeviceSelectorView() { +MediaItemUIDeviceSelectorView::~MediaItemUIDeviceSelectorView() { audio_device_subscription_ = {}; // If this metric has not been recorded during the lifetime of this view, it @@ -235,7 +232,7 @@ } } -void MediaNotificationDeviceSelectorView::UpdateAvailableAudioDevices( +void MediaItemUIDeviceSelectorView::UpdateAvailableAudioDevices( const media::AudioDeviceDescriptions& device_descriptions) { RemoveDevicesOfType(DeviceEntryUIType::kAudio); current_audio_device_entry_view_ = nullptr; @@ -244,8 +241,8 @@ for (auto description : device_descriptions) { auto device_entry_view = std::make_unique<AudioDeviceEntryView>( base::BindRepeating( - &MediaNotificationDeviceSelectorViewDelegate::OnAudioSinkChosen, - base::Unretained(delegate_), description.unique_id), + &MediaItemUIDeviceSelectorDelegate::OnAudioSinkChosen, + base::Unretained(delegate_), item_id_, description.unique_id), foreground_color_, background_color_, description.unique_id, description.device_name); device_entry_view->set_tag(next_tag_++); @@ -264,12 +261,16 @@ UpdateVisibility(); for (auto& observer : observers_) - observer.OnMediaNotificationDeviceSelectorUpdated(device_entry_ui_map_); + observer.OnMediaItemUIDeviceSelectorUpdated(device_entry_ui_map_); } -void MediaNotificationDeviceSelectorView::OnColorsChanged( - const SkColor& foreground_color, - const SkColor& background_color) { +void MediaItemUIDeviceSelectorView::SetMediaItemUIView( + global_media_controls::MediaItemUIView* view) { + media_item_ui_ = view; +} + +void MediaItemUIDeviceSelectorView::OnColorsChanged(SkColor foreground_color, + SkColor background_color) { foreground_color_ = foreground_color; background_color_ = background_color; @@ -283,33 +284,34 @@ SchedulePaint(); } -SkColor MediaNotificationDeviceSelectorView:: - GetIconLabelBubbleSurroundingForegroundColor() const { +SkColor +MediaItemUIDeviceSelectorView::GetIconLabelBubbleSurroundingForegroundColor() + const { return foreground_color_; } -SkColor MediaNotificationDeviceSelectorView::GetIconLabelBubbleBackgroundColor() +SkColor MediaItemUIDeviceSelectorView::GetIconLabelBubbleBackgroundColor() const { return background_color_; } -views::Button* -MediaNotificationDeviceSelectorView::GetExpandButtonForTesting() { +views::Button* MediaItemUIDeviceSelectorView::GetExpandButtonForTesting() { return expand_button_; } -std::string MediaNotificationDeviceSelectorView::GetEntryLabelForTesting( +std::string MediaItemUIDeviceSelectorView::GetEntryLabelForTesting( views::View* entry_view) { return GetDeviceEntryUI(entry_view)->device_name(); } -bool MediaNotificationDeviceSelectorView::GetEntryIsHighlightedForTesting( +bool MediaItemUIDeviceSelectorView::GetEntryIsHighlightedForTesting( views::View* entry_view) { - return GetDeviceEntryUI(entry_view)->GetEntryIsHighlightedForTesting(); + return GetDeviceEntryUI(entry_view) + ->GetEntryIsHighlightedForTesting(); // IN-TEST } std::vector<media_router::CastDialogSinkButton*> -MediaNotificationDeviceSelectorView::GetCastSinkButtonsForTesting() { +MediaItemUIDeviceSelectorView::GetCastSinkButtonsForTesting() { std::vector<media_router::CastDialogSinkButton*> buttons; for (auto* view : device_entry_views_container_->children()) { if (GetDeviceEntryUI(view)->GetType() == DeviceEntryUIType::kCast) { @@ -319,7 +321,7 @@ return buttons; } -void MediaNotificationDeviceSelectorView::ShowDevices() { +void MediaItemUIDeviceSelectorView::ShowDevices() { DCHECK(!is_expanded_); is_expanded_ = true; NotifyAccessibilityEvent(ax::mojom::Event::kExpandedChanged, true); @@ -340,7 +342,7 @@ PreferredSizeChanged(); } -void MediaNotificationDeviceSelectorView::HideDevices() { +void MediaItemUIDeviceSelectorView::HideDevices() { DCHECK(is_expanded_); is_expanded_ = false; NotifyAccessibilityEvent(ax::mojom::Event::kExpandedChanged, true); @@ -351,7 +353,7 @@ PreferredSizeChanged(); } -void MediaNotificationDeviceSelectorView::UpdateVisibility() { +void MediaItemUIDeviceSelectorView::UpdateVisibility() { SetVisible(ShouldBeVisible()); if (!has_expand_button_been_shown_ && GetVisible()) { @@ -359,10 +361,11 @@ has_expand_button_been_shown_ = true; } - delegate_->OnDeviceSelectorViewSizeChanged(); + if (media_item_ui_) + media_item_ui_->OnDeviceSelectorViewSizeChanged(); } -bool MediaNotificationDeviceSelectorView::ShouldBeVisible() const { +bool MediaItemUIDeviceSelectorView::ShouldBeVisible() const { if (has_cast_device_) return true; if (!is_audio_device_switching_enabled_) @@ -385,15 +388,17 @@ return device_entry_views_container_->children().size() > 2; } -void MediaNotificationDeviceSelectorView::ExpandButtonPressed() { +void MediaItemUIDeviceSelectorView::ExpandButtonPressed() { if (is_expanded_) HideDevices(); else ShowDevices(); - delegate_->OnDeviceSelectorViewSizeChanged(); + + if (media_item_ui_) + media_item_ui_->OnDeviceSelectorViewSizeChanged(); } -void MediaNotificationDeviceSelectorView::UpdateIsAudioDeviceSwitchingEnabled( +void MediaItemUIDeviceSelectorView::UpdateIsAudioDeviceSwitchingEnabled( bool enabled) { if (enabled == is_audio_device_switching_enabled_) return; @@ -402,7 +407,7 @@ UpdateVisibility(); } -void MediaNotificationDeviceSelectorView::RemoveDevicesOfType( +void MediaItemUIDeviceSelectorView::RemoveDevicesOfType( DeviceEntryUIType type) { std::vector<views::View*> views_to_remove; for (auto* view : device_entry_views_container_->children()) { @@ -417,14 +422,14 @@ } } -DeviceEntryUI* MediaNotificationDeviceSelectorView::GetDeviceEntryUI( +DeviceEntryUI* MediaItemUIDeviceSelectorView::GetDeviceEntryUI( views::View* view) const { auto it = device_entry_ui_map_.find(static_cast<views::Button*>(view)->tag()); DCHECK(it != device_entry_ui_map_.end()); return it->second; } -void MediaNotificationDeviceSelectorView::OnModelUpdated( +void MediaItemUIDeviceSelectorView::OnModelUpdated( const media_router::CastDialogModel& model) { RemoveDevicesOfType(DeviceEntryUIType::kCast); has_cast_device_ = false; @@ -435,9 +440,8 @@ } has_cast_device_ = true; auto device_entry_view = std::make_unique<CastDeviceEntryView>( - base::BindRepeating( - &MediaNotificationDeviceSelectorView::StartCastSession, - base::Unretained(this)), + base::BindRepeating(&MediaItemUIDeviceSelectorView::StartCastSession, + base::Unretained(this)), foreground_color_, background_color_, sink); device_entry_view->set_tag(next_tag_++); device_entry_ui_map_[device_entry_view->tag()] = device_entry_view.get(); @@ -451,37 +455,37 @@ UpdateVisibility(); for (auto& observer : observers_) - observer.OnMediaNotificationDeviceSelectorUpdated(device_entry_ui_map_); + observer.OnMediaItemUIDeviceSelectorUpdated(device_entry_ui_map_); } -void MediaNotificationDeviceSelectorView::OnControllerInvalidated() { +void MediaItemUIDeviceSelectorView::OnControllerInvalidated() { cast_controller_.reset(); } -void MediaNotificationDeviceSelectorView::OnDeviceSelected(int tag) { +void MediaItemUIDeviceSelectorView::OnDeviceSelected(int tag) { auto it = device_entry_ui_map_.find(tag); DCHECK(it != device_entry_ui_map_.end()); if (it->second->GetType() == DeviceEntryUIType::kAudio) - delegate_->OnAudioSinkChosen(it->second->raw_device_id()); + delegate_->OnAudioSinkChosen(item_id_, it->second->raw_device_id()); else StartCastSession(static_cast<CastDeviceEntryView*>(it->second)); } -void MediaNotificationDeviceSelectorView::OnDropdownButtonClicked() { +void MediaItemUIDeviceSelectorView::OnDropdownButtonClicked() { ExpandButtonPressed(); } -bool MediaNotificationDeviceSelectorView::IsDeviceSelectorExpanded() { +bool MediaItemUIDeviceSelectorView::IsDeviceSelectorExpanded() { return is_expanded_; } -void MediaNotificationDeviceSelectorView::AddObserver( - MediaNotificationDeviceSelectorObserver* observer) { +void MediaItemUIDeviceSelectorView::AddObserver( + MediaItemUIDeviceSelectorObserver* observer) { observers_.AddObserver(observer); } -void MediaNotificationDeviceSelectorView::StartCastSession( +void MediaItemUIDeviceSelectorView::StartCastSession( CastDeviceEntryView* entry) { if (!cast_controller_) return; @@ -513,7 +517,7 @@ } } } -void MediaNotificationDeviceSelectorView::DoStartCastSession( +void MediaItemUIDeviceSelectorView::DoStartCastSession( media_router::UIMediaSink sink) { DCHECK(base::Contains(sink.cast_modes, media_router::MediaCastMode::PRESENTATION)); @@ -522,22 +526,24 @@ RecordStartCastingMetrics(sink.icon_type); } -void MediaNotificationDeviceSelectorView::RecordStartCastingMetrics( +void MediaItemUIDeviceSelectorView::RecordStartCastingMetrics( media_router::SinkIconType sink_icon_type) { MediaRouterMetrics::RecordMediaSinkTypeForGlobalMediaControls(sink_icon_type); RecordStartCastingWithCastAndDialPresent(sink_icon_type); - GlobalMediaControlsCastActionAndEntryPoint action; + global_media_controls::GlobalMediaControlsCastActionAndEntryPoint action; switch (entry_point_) { - case GlobalMediaControlsEntryPoint::kToolbarIcon: - action = GlobalMediaControlsCastActionAndEntryPoint::kStartViaToolbarIcon; + case global_media_controls::GlobalMediaControlsEntryPoint::kToolbarIcon: + action = global_media_controls:: + GlobalMediaControlsCastActionAndEntryPoint::kStartViaToolbarIcon; break; - case GlobalMediaControlsEntryPoint::kPresentation: - action = + case global_media_controls::GlobalMediaControlsEntryPoint::kPresentation: + action = global_media_controls:: GlobalMediaControlsCastActionAndEntryPoint::kStartViaPresentation; break; - case GlobalMediaControlsEntryPoint::kSystemTray: - action = GlobalMediaControlsCastActionAndEntryPoint::kStartViaSystemTray; + case global_media_controls::GlobalMediaControlsEntryPoint::kSystemTray: + action = global_media_controls:: + GlobalMediaControlsCastActionAndEntryPoint::kStartViaSystemTray; break; } base::UmaHistogramEnumeration( @@ -545,8 +551,8 @@ action); } -void MediaNotificationDeviceSelectorView:: - RecordStartCastingWithCastAndDialPresent(media_router::SinkIconType type) { +void MediaItemUIDeviceSelectorView::RecordStartCastingWithCastAndDialPresent( + media_router::SinkIconType type) { bool has_cast = false; bool has_dial = false; for (views::View* view : device_entry_views_container_->children()) { @@ -575,17 +581,20 @@ } } -void MediaNotificationDeviceSelectorView::RecordStopCastingMetrics() { - GlobalMediaControlsCastActionAndEntryPoint action; +void MediaItemUIDeviceSelectorView::RecordStopCastingMetrics() { + global_media_controls::GlobalMediaControlsCastActionAndEntryPoint action; switch (entry_point_) { - case GlobalMediaControlsEntryPoint::kToolbarIcon: - action = GlobalMediaControlsCastActionAndEntryPoint::kStopViaToolbarIcon; + case global_media_controls::GlobalMediaControlsEntryPoint::kToolbarIcon: + action = global_media_controls:: + GlobalMediaControlsCastActionAndEntryPoint::kStopViaToolbarIcon; break; - case GlobalMediaControlsEntryPoint::kPresentation: - action = GlobalMediaControlsCastActionAndEntryPoint::kStopViaPresentation; + case global_media_controls::GlobalMediaControlsEntryPoint::kPresentation: + action = global_media_controls:: + GlobalMediaControlsCastActionAndEntryPoint::kStopViaPresentation; break; - case GlobalMediaControlsEntryPoint::kSystemTray: - action = GlobalMediaControlsCastActionAndEntryPoint::kStopViaSystemTray; + case global_media_controls::GlobalMediaControlsEntryPoint::kSystemTray: + action = global_media_controls:: + GlobalMediaControlsCastActionAndEntryPoint::kStopViaSystemTray; break; } base::UmaHistogramEnumeration( @@ -593,16 +602,15 @@ action); } -void MediaNotificationDeviceSelectorView::RecordCastDeviceCountAfterDelay() { +void MediaItemUIDeviceSelectorView::RecordCastDeviceCountAfterDelay() { content::GetUIThreadTaskRunner({})->PostDelayedTask( FROM_HERE, - base::BindOnce( - &MediaNotificationDeviceSelectorView::RecordCastDeviceCount, - weak_ptr_factory_.GetWeakPtr()), + base::BindOnce(&MediaItemUIDeviceSelectorView::RecordCastDeviceCount, + weak_ptr_factory_.GetWeakPtr()), MediaRouterMetrics::kDeviceCountMetricDelay); } -void MediaNotificationDeviceSelectorView::RecordCastDeviceCount() { +void MediaItemUIDeviceSelectorView::RecordCastDeviceCount() { std::vector<CastDeviceEntryView*> entries; for (views::View* view : device_entry_views_container_->children()) { DeviceEntryUI* entry = GetDeviceEntryUI(view); @@ -613,21 +621,21 @@ RecordCastDeviceCountMetrics(entry_point_, entries); } -void MediaNotificationDeviceSelectorView::RegisterAudioDeviceCallbacks() { +void MediaItemUIDeviceSelectorView::RegisterAudioDeviceCallbacks() { // Get a list of the connected audio output devices. audio_device_subscription_ = delegate_->RegisterAudioOutputDeviceDescriptionsCallback( base::BindRepeating( - &MediaNotificationDeviceSelectorView::UpdateAvailableAudioDevices, + &MediaItemUIDeviceSelectorView::UpdateAvailableAudioDevices, weak_ptr_factory_.GetWeakPtr())); // Get the availability of audio output device switching. is_device_switching_enabled_subscription_ = delegate_->RegisterIsAudioOutputDeviceSwitchingSupportedCallback( - base::BindRepeating(&MediaNotificationDeviceSelectorView:: - UpdateIsAudioDeviceSwitchingEnabled, - weak_ptr_factory_.GetWeakPtr())); + item_id_, base::BindRepeating(&MediaItemUIDeviceSelectorView:: + UpdateIsAudioDeviceSwitchingEnabled, + weak_ptr_factory_.GetWeakPtr())); } -BEGIN_METADATA(MediaNotificationDeviceSelectorView, views::View) +BEGIN_METADATA(MediaItemUIDeviceSelectorView, views::View) END_METADATA
diff --git a/chrome/browser/ui/views/global_media_controls/media_notification_device_selector_view.h b/chrome/browser/ui/views/global_media_controls/media_item_ui_device_selector_view.h similarity index 63% rename from chrome/browser/ui/views/global_media_controls/media_notification_device_selector_view.h rename to chrome/browser/ui/views/global_media_controls/media_item_ui_device_selector_view.h index 2a2b3ec..cb996f9 100644 --- a/chrome/browser/ui/views/global_media_controls/media_notification_device_selector_view.h +++ b/chrome/browser/ui/views/global_media_controls/media_item_ui_device_selector_view.h
@@ -2,17 +2,18 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_UI_VIEWS_GLOBAL_MEDIA_CONTROLS_MEDIA_NOTIFICATION_DEVICE_SELECTOR_VIEW_H_ -#define CHROME_BROWSER_UI_VIEWS_GLOBAL_MEDIA_CONTROLS_MEDIA_NOTIFICATION_DEVICE_SELECTOR_VIEW_H_ +#ifndef CHROME_BROWSER_UI_VIEWS_GLOBAL_MEDIA_CONTROLS_MEDIA_ITEM_UI_DEVICE_SELECTOR_VIEW_H_ +#define CHROME_BROWSER_UI_VIEWS_GLOBAL_MEDIA_CONTROLS_MEDIA_ITEM_UI_DEVICE_SELECTOR_VIEW_H_ #include "base/callback_list.h" #include "base/gtest_prod_util.h" #include "chrome/browser/ui/global_media_controls/media_notification_device_provider.h" #include "chrome/browser/ui/media_router/cast_dialog_controller.h" -#include "chrome/browser/ui/views/global_media_controls/global_media_controls_types.h" +#include "chrome/browser/ui/views/global_media_controls/media_item_ui_footer_view.h" #include "chrome/browser/ui/views/global_media_controls/media_notification_device_entry_ui.h" -#include "chrome/browser/ui/views/global_media_controls/media_notification_footer_view.h" #include "chrome/browser/ui/views/location_bar/icon_label_bubble_view.h" +#include "components/global_media_controls/public/constants.h" +#include "components/global_media_controls/public/views/media_item_ui_device_selector.h" #include "components/media_router/common/media_sink.h" #include "media/audio/audio_device_description.h" #include "ui/base/metadata/metadata_header_macros.h" @@ -29,37 +30,42 @@ "Media.GlobalMediaControls.DeviceSelectorOpened"; } // anonymous namespace +namespace global_media_controls { +class MediaItemUIView; +} // namespace global_media_controls + namespace media_router { class CastDialogSinkButton; } -class MediaNotificationDeviceSelectorViewDelegate; -class MediaNotificationDeviceSelectorObserver; +class MediaItemUIDeviceSelectorDelegate; +class MediaItemUIDeviceSelectorObserver; -class MediaNotificationDeviceSelectorView - : public views::View, +class MediaItemUIDeviceSelectorView + : public global_media_controls::MediaItemUIDeviceSelector, public IconLabelBubbleView::Delegate, public media_router::CastDialogController::Observer, - public MediaNotificationFooterView::Delegate { + public MediaItemUIFooterView::Delegate { public: - METADATA_HEADER(MediaNotificationDeviceSelectorView); - MediaNotificationDeviceSelectorView( - MediaNotificationDeviceSelectorViewDelegate* delegate, + METADATA_HEADER(MediaItemUIDeviceSelectorView); + MediaItemUIDeviceSelectorView( + const std::string& item_id, + MediaItemUIDeviceSelectorDelegate* delegate, std::unique_ptr<media_router::CastDialogController> cast_controller, bool has_audio_output, - const std::string& current_device_id, - const SkColor& foreground_color, - const SkColor& background_color, - GlobalMediaControlsEntryPoint entry_point, + global_media_controls::GlobalMediaControlsEntryPoint entry_point, bool show_expand_button = true); - ~MediaNotificationDeviceSelectorView() override; + ~MediaItemUIDeviceSelectorView() override; // Called when audio output devices are discovered. void UpdateAvailableAudioDevices( const media::AudioDeviceDescriptions& device_descriptions); - // Called when an audio device switch has occurred - void UpdateCurrentAudioDevice(const std::string& current_device_id); - void OnColorsChanged(const SkColor& foreground_color, - const SkColor& background_color); + + // global_media_controls::MediaItemUIDeviceSelector: + void SetMediaItemUIView( + global_media_controls::MediaItemUIView* view) override; + void OnColorsChanged(SkColor foreground_color, + SkColor background_color) override; + void UpdateCurrentAudioDevice(const std::string& current_device_id) override; // Called when the audio device switching has become enabled or disabled. void UpdateIsAudioDeviceSwitchingEnabled(bool enabled); @@ -72,12 +78,12 @@ void OnModelUpdated(const media_router::CastDialogModel& model) override; void OnControllerInvalidated() override; - // MediaNotificationFooterview::Delegate + // MediaItemUIFooterView::Delegate void OnDeviceSelected(int tag) override; void OnDropdownButtonClicked() override; bool IsDeviceSelectorExpanded() override; - void AddObserver(MediaNotificationDeviceSelectorObserver* observer); + void AddObserver(MediaItemUIDeviceSelectorObserver* observer); views::Button* GetExpandButtonForTesting(); std::string GetEntryLabelForTesting(views::View* entry_view); @@ -86,27 +92,27 @@ GetCastSinkButtonsForTesting(); private: - FRIEND_TEST_ALL_PREFIXES(MediaNotificationDeviceSelectorViewTest, + FRIEND_TEST_ALL_PREFIXES(MediaItemUIDeviceSelectorViewTest, DeviceButtonsCreated); - FRIEND_TEST_ALL_PREFIXES(MediaNotificationDeviceSelectorViewTest, + FRIEND_TEST_ALL_PREFIXES(MediaItemUIDeviceSelectorViewTest, ExpandButtonOpensEntryContainer); - FRIEND_TEST_ALL_PREFIXES(MediaNotificationDeviceSelectorViewTest, + FRIEND_TEST_ALL_PREFIXES(MediaItemUIDeviceSelectorViewTest, DeviceEntryContainerVisibility); - FRIEND_TEST_ALL_PREFIXES(MediaNotificationDeviceSelectorViewTest, + FRIEND_TEST_ALL_PREFIXES(MediaItemUIDeviceSelectorViewTest, AudioDeviceButtonClickNotifiesContainer); - FRIEND_TEST_ALL_PREFIXES(MediaNotificationDeviceSelectorViewTest, + FRIEND_TEST_ALL_PREFIXES(MediaItemUIDeviceSelectorViewTest, CurrentAudioDeviceHighlighted); - FRIEND_TEST_ALL_PREFIXES(MediaNotificationDeviceSelectorViewTest, + FRIEND_TEST_ALL_PREFIXES(MediaItemUIDeviceSelectorViewTest, AudioDeviceHighlightedOnChange); - FRIEND_TEST_ALL_PREFIXES(MediaNotificationDeviceSelectorViewTest, + FRIEND_TEST_ALL_PREFIXES(MediaItemUIDeviceSelectorViewTest, AudioDeviceButtonsChange); - FRIEND_TEST_ALL_PREFIXES(MediaNotificationDeviceSelectorViewTest, + FRIEND_TEST_ALL_PREFIXES(MediaItemUIDeviceSelectorViewTest, AudioDevicesCountHistogramRecorded); - FRIEND_TEST_ALL_PREFIXES(MediaNotificationDeviceSelectorViewTest, + FRIEND_TEST_ALL_PREFIXES(MediaItemUIDeviceSelectorViewTest, DeviceSelectorOpenedHistogramRecorded); - FRIEND_TEST_ALL_PREFIXES(MediaNotificationDeviceSelectorViewTest, + FRIEND_TEST_ALL_PREFIXES(MediaItemUIDeviceSelectorViewTest, CastDeviceButtonClickStartsCasting); - FRIEND_TEST_ALL_PREFIXES(MediaNotificationDeviceSelectorViewTest, + FRIEND_TEST_ALL_PREFIXES(MediaItemUIDeviceSelectorViewTest, CastDeviceButtonClickClearsIssue); void UpdateVisibility(); @@ -132,10 +138,13 @@ bool is_expanded_ = false; bool is_audio_device_switching_enabled_ = false; bool has_cast_device_ = false; - MediaNotificationDeviceSelectorViewDelegate* const delegate_; - std::string current_device_id_; - SkColor foreground_color_, background_color_; - GlobalMediaControlsEntryPoint const entry_point_; + const std::string item_id_; + MediaItemUIDeviceSelectorDelegate* const delegate_; + std::string current_device_id_ = + media::AudioDeviceDescription::kDefaultDeviceId; + SkColor foreground_color_ = global_media_controls::kDefaultForegroundColor; + SkColor background_color_ = global_media_controls::kDefaultBackgroundColor; + global_media_controls::GlobalMediaControlsEntryPoint const entry_point_; // Child views AudioDeviceEntryView* current_audio_device_entry_view_ = nullptr; @@ -146,17 +155,18 @@ base::CallbackListSubscription audio_device_subscription_; base::CallbackListSubscription is_device_switching_enabled_subscription_; + global_media_controls::MediaItemUIView* media_item_ui_ = nullptr; + std::unique_ptr<media_router::CastDialogController> cast_controller_; - base::ObserverList<MediaNotificationDeviceSelectorObserver> observers_; + base::ObserverList<MediaItemUIDeviceSelectorObserver> observers_; // Each button has a unique tag, which is used to look up DeviceEntryUI* in // |device_entry_ui_map_|. int next_tag_ = 0; std::map<int, DeviceEntryUI*> device_entry_ui_map_; - base::WeakPtrFactory<MediaNotificationDeviceSelectorView> weak_ptr_factory_{ - this}; + base::WeakPtrFactory<MediaItemUIDeviceSelectorView> weak_ptr_factory_{this}; }; -#endif // CHROME_BROWSER_UI_VIEWS_GLOBAL_MEDIA_CONTROLS_MEDIA_NOTIFICATION_DEVICE_SELECTOR_VIEW_H_ +#endif // CHROME_BROWSER_UI_VIEWS_GLOBAL_MEDIA_CONTROLS_MEDIA_ITEM_UI_DEVICE_SELECTOR_VIEW_H_
diff --git a/chrome/browser/ui/views/global_media_controls/media_notification_device_selector_view_unittest.cc b/chrome/browser/ui/views/global_media_controls/media_item_ui_device_selector_view_unittest.cc similarity index 82% rename from chrome/browser/ui/views/global_media_controls/media_notification_device_selector_view_unittest.cc rename to chrome/browser/ui/views/global_media_controls/media_item_ui_device_selector_view_unittest.cc index a22de69..dc6b351 100644 --- a/chrome/browser/ui/views/global_media_controls/media_notification_device_selector_view_unittest.cc +++ b/chrome/browser/ui/views/global_media_controls/media_item_ui_device_selector_view_unittest.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/ui/views/global_media_controls/media_notification_device_selector_view.h" +#include "chrome/browser/ui/views/global_media_controls/media_item_ui_device_selector_view.h" #include <memory> #include <string> @@ -15,10 +15,10 @@ #include "base/test/metrics/histogram_tester.h" #include "base/test/scoped_feature_list.h" #include "base/time/time.h" +#include "chrome/browser/ui/global_media_controls/media_item_ui_device_selector_delegate.h" #include "chrome/browser/ui/global_media_controls/media_notification_device_provider.h" #include "chrome/browser/ui/global_media_controls/media_notification_service.h" #include "chrome/browser/ui/media_router/cast_dialog_model.h" -#include "chrome/browser/ui/views/global_media_controls/media_notification_device_selector_view_delegate.h" #include "chrome/test/views/chrome_views_test_base.h" #include "media/audio/audio_device_description.h" #include "media/base/media_switches.h" @@ -34,10 +34,9 @@ using testing::_; using testing::NiceMock; -class MediaNotificationContainerObserver; - namespace { +constexpr char kItemId[] = "item_id"; constexpr char kSinkId[] = "sink_id"; constexpr char kSinkFriendlyName[] = "Nest Hub"; constexpr char16_t kSinkFriendlyName16[] = u"Nest Hub"; @@ -90,18 +89,17 @@ GetOutputDevicesCallback output_devices_callback_; }; -class MockMediaNotificationDeviceSelectorViewDelegate - : public MediaNotificationDeviceSelectorViewDelegate { +class MockMediaItemUIDeviceSelectorDelegate + : public MediaItemUIDeviceSelectorDelegate { public: - MockMediaNotificationDeviceSelectorViewDelegate() { + MockMediaItemUIDeviceSelectorDelegate() { provider_ = std::make_unique<MockMediaNotificationDeviceProvider>(); } MOCK_METHOD(void, OnAudioSinkChosen, - (const std::string& sink_id), + (const std::string& item_id, const std::string& sink_id), (override)); - MOCK_METHOD(void, OnDeviceSelectorViewSizeChanged, (), (override)); base::CallbackListSubscription RegisterAudioOutputDeviceDescriptionsCallback( MediaNotificationDeviceProvider::GetOutputDevicesCallbackList:: @@ -114,6 +112,7 @@ base::CallbackListSubscription RegisterIsAudioOutputDeviceSwitchingSupportedCallback( + const std::string& item_id, base::RepeatingCallback<void(bool)> callback) override { callback.Run(supports_switching); supports_switching_callback_ = std::move(callback); @@ -144,12 +143,13 @@ void(base::OnceCallback<void(const ui::SelectedFileInfo*)> callback)); MOCK_METHOD1(ClearIssue, void(const media_router::Issue::Id& issue_id)); }; + } // anonymous namespace -class MediaNotificationDeviceSelectorViewTest : public ChromeViewsTestBase { +class MediaItemUIDeviceSelectorViewTest : public ChromeViewsTestBase { public: - MediaNotificationDeviceSelectorViewTest() = default; - ~MediaNotificationDeviceSelectorViewTest() override = default; + MediaItemUIDeviceSelectorViewTest() = default; + ~MediaItemUIDeviceSelectorViewTest() override = default; // ChromeViewsTestBase void SetUp() override { @@ -163,8 +163,7 @@ ChromeViewsTestBase::TearDown(); } - void AddAudioDevices( - MockMediaNotificationDeviceSelectorViewDelegate& delegate) { + void AddAudioDevices(MockMediaItemUIDeviceSelectorDelegate& delegate) { auto* provider = delegate.GetProvider(); provider->AddDevice("Speaker", "1"); provider->AddDevice("Headphones", "2"); @@ -189,27 +188,29 @@ return base::UTF16ToUTF8(static_cast<views::LabelButton*>(view)->GetText()); } - std::unique_ptr<MediaNotificationDeviceSelectorView> CreateDeviceSelectorView( - MockMediaNotificationDeviceSelectorViewDelegate* delegate, + std::unique_ptr<MediaItemUIDeviceSelectorView> CreateDeviceSelectorView( + MockMediaItemUIDeviceSelectorDelegate* delegate, std::unique_ptr<MockCastDialogController> controller = std::make_unique<NiceMock<MockCastDialogController>>(), - const std::string& device_description = "1", + const std::string& current_device = "1", bool has_audio_output = true, - GlobalMediaControlsEntryPoint entry_point = - GlobalMediaControlsEntryPoint::kToolbarIcon) { - return std::make_unique<MediaNotificationDeviceSelectorView>( - delegate, std::move(controller), has_audio_output, device_description, - gfx::kPlaceholderColor, gfx::kPlaceholderColor, entry_point); + global_media_controls::GlobalMediaControlsEntryPoint entry_point = + global_media_controls::GlobalMediaControlsEntryPoint::kToolbarIcon) { + auto device_selector_view = std::make_unique<MediaItemUIDeviceSelectorView>( + kItemId, delegate, std::move(controller), has_audio_output, + entry_point); + device_selector_view->UpdateCurrentAudioDevice(current_device); + return device_selector_view; } - std::unique_ptr<MediaNotificationDeviceSelectorView> view_; + std::unique_ptr<MediaItemUIDeviceSelectorView> view_; base::HistogramTester histogram_tester_; base::test::ScopedFeatureList feature_list_; }; -TEST_F(MediaNotificationDeviceSelectorViewTest, DeviceButtonsCreated) { +TEST_F(MediaItemUIDeviceSelectorViewTest, DeviceButtonsCreated) { // Buttons should be created for every device reported by the provider. - NiceMock<MockMediaNotificationDeviceSelectorViewDelegate> delegate; + NiceMock<MockMediaItemUIDeviceSelectorDelegate> delegate; AddAudioDevices(delegate); view_ = CreateDeviceSelectorView(&delegate); view_->OnModelUpdated(CreateModelWithSinks({CreateMediaSink()})); @@ -225,9 +226,8 @@ EXPECT_EQ(EntryLabelText(container_children.at(3)), kSinkFriendlyName); } -TEST_F(MediaNotificationDeviceSelectorViewTest, - ExpandButtonOpensEntryContainer) { - NiceMock<MockMediaNotificationDeviceSelectorViewDelegate> delegate; +TEST_F(MediaItemUIDeviceSelectorViewTest, ExpandButtonOpensEntryContainer) { + NiceMock<MockMediaItemUIDeviceSelectorDelegate> delegate; AddAudioDevices(delegate); view_ = CreateDeviceSelectorView(&delegate); @@ -237,9 +237,8 @@ EXPECT_TRUE(view_->device_entry_views_container_->GetVisible()); } -TEST_F(MediaNotificationDeviceSelectorViewTest, - DeviceEntryContainerVisibility) { - NiceMock<MockMediaNotificationDeviceSelectorViewDelegate> delegate; +TEST_F(MediaItemUIDeviceSelectorViewTest, DeviceEntryContainerVisibility) { + NiceMock<MockMediaItemUIDeviceSelectorDelegate> delegate; AddAudioDevices(delegate); // The device entry container should be collapsed if the media dialog is @@ -252,30 +251,29 @@ view_ = CreateDeviceSelectorView( &delegate, std::make_unique<NiceMock<MockCastDialogController>>(), "1", /* has_audio_output */ true, - GlobalMediaControlsEntryPoint::kPresentation); + global_media_controls::GlobalMediaControlsEntryPoint::kPresentation); EXPECT_TRUE(view_->device_entry_views_container_->GetVisible()); } -TEST_F(MediaNotificationDeviceSelectorViewTest, +TEST_F(MediaItemUIDeviceSelectorViewTest, AudioDeviceButtonClickNotifiesContainer) { // When buttons are clicked the media notification delegate should be // informed. - NiceMock<MockMediaNotificationDeviceSelectorViewDelegate> delegate; + NiceMock<MockMediaItemUIDeviceSelectorDelegate> delegate; AddAudioDevices(delegate); view_ = CreateDeviceSelectorView(&delegate); - EXPECT_CALL(delegate, OnAudioSinkChosen("1")).Times(1); - EXPECT_CALL(delegate, OnAudioSinkChosen("2")).Times(1); - EXPECT_CALL(delegate, OnAudioSinkChosen("3")).Times(1); + EXPECT_CALL(delegate, OnAudioSinkChosen(kItemId, "1")).Times(1); + EXPECT_CALL(delegate, OnAudioSinkChosen(kItemId, "2")).Times(1); + EXPECT_CALL(delegate, OnAudioSinkChosen(kItemId, "3")).Times(1); for (views::View* child : view_->device_entry_views_container_->children()) { SimulateButtonClick(child); } } -TEST_F(MediaNotificationDeviceSelectorViewTest, - CastDeviceButtonClickStartsCasting) { - NiceMock<MockMediaNotificationDeviceSelectorViewDelegate> delegate; +TEST_F(MediaItemUIDeviceSelectorViewTest, CastDeviceButtonClickStartsCasting) { + NiceMock<MockMediaItemUIDeviceSelectorDelegate> delegate; auto cast_controller = std::make_unique<NiceMock<MockCastDialogController>>(); auto* cast_controller_ptr = cast_controller.get(); view_ = CreateDeviceSelectorView(&delegate, std::move(cast_controller)); @@ -318,10 +316,10 @@ } } -TEST_F(MediaNotificationDeviceSelectorViewTest, CurrentAudioDeviceHighlighted) { +TEST_F(MediaItemUIDeviceSelectorViewTest, CurrentAudioDeviceHighlighted) { // The 'current' audio device should be highlighted in the UI and appear // before other devices. - NiceMock<MockMediaNotificationDeviceSelectorViewDelegate> delegate; + NiceMock<MockMediaItemUIDeviceSelectorDelegate> delegate; AddAudioDevices(delegate); view_ = CreateDeviceSelectorView( &delegate, std::make_unique<NiceMock<MockCastDialogController>>(), "3"); @@ -331,10 +329,9 @@ EXPECT_TRUE(IsHighlighted(first_entry)); } -TEST_F(MediaNotificationDeviceSelectorViewTest, - AudioDeviceHighlightedOnChange) { +TEST_F(MediaItemUIDeviceSelectorViewTest, AudioDeviceHighlightedOnChange) { // When the audio output device changes, the UI should highlight that one. - NiceMock<MockMediaNotificationDeviceSelectorViewDelegate> delegate; + NiceMock<MockMediaItemUIDeviceSelectorDelegate> delegate; AddAudioDevices(delegate); view_ = CreateDeviceSelectorView(&delegate); @@ -358,10 +355,10 @@ EXPECT_EQ(EntryLabelText(container_children.front()), "Earbuds"); } -TEST_F(MediaNotificationDeviceSelectorViewTest, AudioDeviceButtonsChange) { +TEST_F(MediaItemUIDeviceSelectorViewTest, AudioDeviceButtonsChange) { // If the device provider reports a change in connect audio devices, the UI // should update accordingly. - NiceMock<MockMediaNotificationDeviceSelectorViewDelegate> delegate; + NiceMock<MockMediaItemUIDeviceSelectorDelegate> delegate; AddAudioDevices(delegate); view_ = CreateDeviceSelectorView(&delegate); @@ -400,16 +397,15 @@ } } -TEST_F(MediaNotificationDeviceSelectorViewTest, VisibilityChanges) { +TEST_F(MediaItemUIDeviceSelectorViewTest, VisibilityChanges) { // The device selector view should become hidden when there is only one // unique device, unless there exists a cast device. - NiceMock<MockMediaNotificationDeviceSelectorViewDelegate> delegate; + NiceMock<MockMediaItemUIDeviceSelectorDelegate> delegate; auto* provider = delegate.GetProvider(); provider->AddDevice("Speaker", "1"); provider->AddDevice(media::AudioDeviceDescription::GetDefaultDeviceName(), media::AudioDeviceDescription::kDefaultDeviceId); - EXPECT_CALL(delegate, OnDeviceSelectorViewSizeChanged).Times(2); view_ = CreateDeviceSelectorView( &delegate, std::make_unique<NiceMock<MockCastDialogController>>(), media::AudioDeviceDescription::kDefaultDeviceId); @@ -417,7 +413,6 @@ testing::Mock::VerifyAndClearExpectations(&delegate); - EXPECT_CALL(delegate, OnDeviceSelectorViewSizeChanged); view_->OnModelUpdated(CreateModelWithSinks({CreateMediaSink()})); EXPECT_TRUE(view_->GetVisible()); @@ -427,7 +422,6 @@ provider->AddDevice("Speaker", "1"); provider->AddDevice("Headphones", media::AudioDeviceDescription::kDefaultDeviceId); - EXPECT_CALL(delegate, OnDeviceSelectorViewSizeChanged).Times(1); provider->RunUICallback(); EXPECT_TRUE(view_->GetVisible()); testing::Mock::VerifyAndClearExpectations(&delegate); @@ -437,15 +431,13 @@ provider->AddDevice("Headphones", "2"); provider->AddDevice(media::AudioDeviceDescription::GetDefaultDeviceName(), media::AudioDeviceDescription::kDefaultDeviceId); - EXPECT_CALL(delegate, OnDeviceSelectorViewSizeChanged).Times(1); provider->RunUICallback(); EXPECT_TRUE(view_->GetVisible()); testing::Mock::VerifyAndClearExpectations(&delegate); } -TEST_F(MediaNotificationDeviceSelectorViewTest, - AudioDeviceChangeIsNotSupported) { - NiceMock<MockMediaNotificationDeviceSelectorViewDelegate> delegate; +TEST_F(MediaItemUIDeviceSelectorViewTest, AudioDeviceChangeIsNotSupported) { + NiceMock<MockMediaItemUIDeviceSelectorDelegate> delegate; AddAudioDevices(delegate); delegate.supports_switching = false; @@ -459,9 +451,8 @@ EXPECT_TRUE(view_->GetVisible()); } -TEST_F(MediaNotificationDeviceSelectorViewTest, - CastDeviceButtonClickClearsIssue) { - NiceMock<MockMediaNotificationDeviceSelectorViewDelegate> delegate; +TEST_F(MediaItemUIDeviceSelectorViewTest, CastDeviceButtonClickClearsIssue) { + NiceMock<MockMediaItemUIDeviceSelectorDelegate> delegate; auto cast_controller = std::make_unique<NiceMock<MockCastDialogController>>(); auto* cast_controller_ptr = cast_controller.get(); view_ = CreateDeviceSelectorView(&delegate, std::move(cast_controller)); @@ -483,9 +474,8 @@ } } -TEST_F(MediaNotificationDeviceSelectorViewTest, - AudioDevicesCountHistogramRecorded) { - NiceMock<MockMediaNotificationDeviceSelectorViewDelegate> delegate; +TEST_F(MediaItemUIDeviceSelectorViewTest, AudioDevicesCountHistogramRecorded) { + NiceMock<MockMediaItemUIDeviceSelectorDelegate> delegate; AddAudioDevices(delegate); histogram_tester_.ExpectTotalCount(kAudioDevicesCountHistogramName, 0); @@ -505,9 +495,9 @@ histogram_tester_.ExpectBucketCount(kAudioDevicesCountHistogramName, 3, 1); } -TEST_F(MediaNotificationDeviceSelectorViewTest, +TEST_F(MediaItemUIDeviceSelectorViewTest, DeviceSelectorAvailableHistogramRecorded) { - NiceMock<MockMediaNotificationDeviceSelectorViewDelegate> delegate; + NiceMock<MockMediaItemUIDeviceSelectorDelegate> delegate; auto* provider = delegate.GetProvider(); provider->AddDevice("Speaker", media::AudioDeviceDescription::kDefaultDeviceId); @@ -546,9 +536,9 @@ histogram_tester_.ExpectTotalCount(kDeviceSelectorAvailableHistogramName, 2); } -TEST_F(MediaNotificationDeviceSelectorViewTest, +TEST_F(MediaItemUIDeviceSelectorViewTest, DeviceSelectorOpenedHistogramRecorded) { - NiceMock<MockMediaNotificationDeviceSelectorViewDelegate> delegate; + NiceMock<MockMediaItemUIDeviceSelectorDelegate> delegate; auto* provider = delegate.GetProvider(); provider->AddDevice("Speaker", media::AudioDeviceDescription::kDefaultDeviceId);
diff --git a/chrome/browser/ui/views/global_media_controls/media_notification_footer_view.cc b/chrome/browser/ui/views/global_media_controls/media_item_ui_footer_view.cc similarity index 83% rename from chrome/browser/ui/views/global_media_controls/media_notification_footer_view.cc rename to chrome/browser/ui/views/global_media_controls/media_item_ui_footer_view.cc index 27089a4..b52a157 100644 --- a/chrome/browser/ui/views/global_media_controls/media_notification_footer_view.cc +++ b/chrome/browser/ui/views/global_media_controls/media_item_ui_footer_view.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/ui/views/global_media_controls/media_notification_footer_view.h" +#include "chrome/browser/ui/views/global_media_controls/media_item_ui_footer_view.h" #include "chrome/app/vector_icons/vector_icons.h" #include "chrome/browser/ui/views/chrome_layout_provider.h" @@ -15,6 +15,8 @@ #include "ui/views/animation/ink_drop.h" #include "ui/views/border.h" #include "ui/views/controls/button/label_button.h" +#include "ui/views/controls/highlight_path_generator.h" +#include "ui/views/layout/box_layout.h" #include "ui/views/layout/flex_layout.h" namespace { @@ -88,9 +90,8 @@ } // anonymous namespace -MediaNotificationFooterView::MediaNotificationFooterView( - bool is_cast_session, - views::Button::PressedCallback stop_casting_callback) { +MediaItemUIFooterView::MediaItemUIFooterView( + base::RepeatingClosure stop_casting_callback) { SetLayoutManager(std::make_unique<views::FlexLayout>()) ->SetOrientation(views::LayoutOrientation::kHorizontal) .SetIgnoreDefaultMainAxisMargins(true) @@ -102,16 +103,19 @@ /*horizontal=*/ChromeLayoutProvider::Get()->GetDistanceMetric( views::DISTANCE_RELATED_BUTTON_HORIZONTAL))); - if (!is_cast_session) + if (stop_casting_callback.is_null()) return; + // |this| owns the DeviceEntryButton, so base::Unretained is safe here. AddChildView(std::make_unique<DeviceEntryButton>( stop_casting_callback, nullptr, l10n_util::GetStringUTF16( IDS_GLOBAL_MEDIA_CONTROLS_STOP_CASTING_BUTTON_LABEL))); } -void MediaNotificationFooterView::OnMediaNotificationDeviceSelectorUpdated( +MediaItemUIFooterView::~MediaItemUIFooterView() = default; + +void MediaItemUIFooterView::OnMediaItemUIDeviceSelectorUpdated( const std::map<int, DeviceEntryUI*>& device_entries_map) { RemoveAllChildViews(); @@ -121,7 +125,7 @@ auto* device_entry_button = AddChildView(std::make_unique<DeviceEntryButton>( - base::BindRepeating(&MediaNotificationFooterView::OnDeviceSelected, + base::BindRepeating(&MediaItemUIFooterView::OnDeviceSelected, base::Unretained(this), tag), device_entry->icon(), base::UTF8ToUTF16(device_entry->device_name()))); @@ -134,7 +138,7 @@ } overflow_button_ = AddChildView(std::make_unique<DeviceEntryButton>( - base::BindRepeating(&MediaNotificationFooterView::OnOverflowButtonClicked, + base::BindRepeating(&MediaItemUIFooterView::OnOverflowButtonClicked, base::Unretained(this)))); overflow_button_->SetProperty( views::kFlexBehaviorKey, @@ -149,7 +153,7 @@ UpdateButtonsColor(); } -void MediaNotificationFooterView::Layout() { +void MediaItemUIFooterView::Layout() { if (!overflow_button_) { views::View::Layout(); return; @@ -161,26 +165,27 @@ views::View::Layout(); } -void MediaNotificationFooterView::OnColorChanged(SkColor foreground) { +void MediaItemUIFooterView::OnColorsChanged(SkColor foreground, + SkColor background) { foreground_color_ = foreground; UpdateButtonsColor(); } -void MediaNotificationFooterView::SetDelegate(Delegate* delegate) { +void MediaItemUIFooterView::SetDelegate(Delegate* delegate) { delegate_ = delegate; } -void MediaNotificationFooterView::UpdateButtonsColor() { +void MediaItemUIFooterView::UpdateButtonsColor() { for (auto* view : children()) static_cast<DeviceEntryButton*>(view)->UpdateColor(foreground_color_); } -void MediaNotificationFooterView::OnDeviceSelected(int tag) { +void MediaItemUIFooterView::OnDeviceSelected(int tag) { if (delegate_) delegate_->OnDeviceSelected(tag); } -void MediaNotificationFooterView::OnOverflowButtonClicked() { +void MediaItemUIFooterView::OnOverflowButtonClicked() { if (!delegate_) return;
diff --git a/chrome/browser/ui/views/global_media_controls/media_item_ui_footer_view.h b/chrome/browser/ui/views/global_media_controls/media_item_ui_footer_view.h new file mode 100644 index 0000000..defa0b2 --- /dev/null +++ b/chrome/browser/ui/views/global_media_controls/media_item_ui_footer_view.h
@@ -0,0 +1,58 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_VIEWS_GLOBAL_MEDIA_CONTROLS_MEDIA_ITEM_UI_FOOTER_VIEW_H_ +#define CHROME_BROWSER_UI_VIEWS_GLOBAL_MEDIA_CONTROLS_MEDIA_ITEM_UI_FOOTER_VIEW_H_ + +#include "base/callback.h" +#include "chrome/browser/ui/views/global_media_controls/media_item_ui_device_selector_observer.h" +#include "components/global_media_controls/public/views/media_item_ui_footer.h" +#include "ui/gfx/color_palette.h" +#include "ui/views/controls/button/button.h" + +namespace { +class DeviceEntryButton; +} // anonymous namespace + +// A footer view attached to MediaItemUIView containing +// available cast devices and volume controls. +class MediaItemUIFooterView : public global_media_controls::MediaItemUIFooter, + public MediaItemUIDeviceSelectorObserver { + public: + class Delegate { + public: + virtual ~Delegate() = default; + + virtual void OnDeviceSelected(int tag) = 0; + virtual void OnDropdownButtonClicked() = 0; + virtual bool IsDeviceSelectorExpanded() = 0; + }; + + explicit MediaItemUIFooterView(base::RepeatingClosure stop_casting_callback); + ~MediaItemUIFooterView() override; + + // global_media_controls::MediaItemUIFooter: + void OnColorsChanged(SkColor foreground, SkColor background) override; + + void SetDelegate(Delegate* delegate); + + // MediaItemDeviceSelectorObserver: + void OnMediaItemUIDeviceSelectorUpdated( + const std::map<int, DeviceEntryUI*>& device_entries_map) override; + + void Layout() override; + + private: + void UpdateButtonsColor(); + void OnDeviceSelected(int tag); + void OnOverflowButtonClicked(); + + SkColor foreground_color_ = gfx::kPlaceholderColor; + + DeviceEntryButton* overflow_button_ = nullptr; + + Delegate* delegate_ = nullptr; +}; + +#endif // CHROME_BROWSER_UI_VIEWS_GLOBAL_MEDIA_CONTROLS_MEDIA_ITEM_UI_FOOTER_VIEW_H_
diff --git a/chrome/browser/ui/views/global_media_controls/media_notification_footer_view_unittest.cc b/chrome/browser/ui/views/global_media_controls/media_item_ui_footer_view_unittest.cc similarity index 83% rename from chrome/browser/ui/views/global_media_controls/media_notification_footer_view_unittest.cc rename to chrome/browser/ui/views/global_media_controls/media_item_ui_footer_view_unittest.cc index 30603ad..1399554 100644 --- a/chrome/browser/ui/views/global_media_controls/media_notification_footer_view_unittest.cc +++ b/chrome/browser/ui/views/global_media_controls/media_item_ui_footer_view_unittest.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/ui/views/global_media_controls/media_notification_footer_view.h" +#include "chrome/browser/ui/views/global_media_controls/media_item_ui_footer_view.h" #include <map> #include <memory> @@ -29,7 +29,7 @@ }; // A mock class for delegating media notification footer view. -class MockFooterViewDelegate : public MediaNotificationFooterView::Delegate { +class MockFooterViewDelegate : public MediaItemUIFooterView::Delegate { public: MockFooterViewDelegate() = default; ~MockFooterViewDelegate() override = default; @@ -42,10 +42,10 @@ } // namespace -class MediaNotificationFooterViewTest : public ChromeViewsTestBase { +class MediaItemUIFooterViewTest : public ChromeViewsTestBase { public: - MediaNotificationFooterViewTest() = default; - ~MediaNotificationFooterViewTest() override = default; + MediaItemUIFooterViewTest() = default; + ~MediaItemUIFooterViewTest() override = default; // ChromeViewsTestBase void SetUp() override { ChromeViewsTestBase::SetUp(); } @@ -62,11 +62,13 @@ handler_ = std::make_unique<StopCastingHandler>(); delegate_ = std::make_unique<NiceMock<MockFooterViewDelegate>>(); - view_ = - widget_->SetContentsView(std::make_unique<MediaNotificationFooterView>( - is_cast_session, - base::BindRepeating(&StopCastingHandler::StopCasting, - base::Unretained(handler_.get())))); + base::RepeatingClosure stop_casting_callback = + is_cast_session ? base::BindRepeating(&StopCastingHandler::StopCasting, + base::Unretained(handler_.get())) + : base::NullCallback(); + + view_ = widget_->SetContentsView( + std::make_unique<MediaItemUIFooterView>(stop_casting_callback)); view_->SetDelegate(delegate_.get()); widget_->Show(); @@ -89,7 +91,7 @@ views::Widget* get_widget() { return widget_.get(); } - MediaNotificationFooterView* get_view() { return view_; } + MediaItemUIFooterView* get_view() { return view_; } MockFooterViewDelegate* delegate() { return delegate_.get(); } @@ -99,10 +101,10 @@ std::unique_ptr<views::Widget> widget_; std::unique_ptr<StopCastingHandler> handler_; std::unique_ptr<MockFooterViewDelegate> delegate_; - MediaNotificationFooterView* view_ = nullptr; + MediaItemUIFooterView* view_ = nullptr; }; -TEST_F(MediaNotificationFooterViewTest, ViewDuringCast) { +TEST_F(MediaItemUIFooterViewTest, ViewDuringCast) { CreateView(true); EXPECT_EQ(get_view()->children().size(), 1u); @@ -110,7 +112,7 @@ SimulateButtonClicked(get_view()->children()[0]); } -TEST_F(MediaNotificationFooterViewTest, DevicesCanFit) { +TEST_F(MediaItemUIFooterViewTest, DevicesCanFit) { CreateView(false); get_widget()->SetBounds(gfx::Rect(200, 20)); EXPECT_EQ(get_view()->children().size(), 0u); @@ -129,7 +131,7 @@ devices[0] = &device1; devices[1] = &device2; - get_view()->OnMediaNotificationDeviceSelectorUpdated(devices); + get_view()->OnMediaItemUIDeviceSelectorUpdated(devices); get_widget()->LayoutRootViewIfNecessary(); auto visible_items = GetVisibleItems(); EXPECT_EQ(visible_items.size(), 2u); @@ -146,7 +148,7 @@ SimulateButtonClicked(view); } -TEST_F(MediaNotificationFooterViewTest, OverflowButton) { +TEST_F(MediaItemUIFooterViewTest, OverflowButton) { CreateView(false); get_widget()->SetBounds(gfx::Rect(200, 20)); EXPECT_EQ(get_view()->children().size(), 0u); @@ -159,7 +161,7 @@ devices[0] = &device; devices[1] = &device; - get_view()->OnMediaNotificationDeviceSelectorUpdated(devices); + get_view()->OnMediaItemUIDeviceSelectorUpdated(devices); get_widget()->LayoutRootViewIfNecessary(); auto visible_items = GetVisibleItems(); EXPECT_EQ(visible_items.size(), 2u); @@ -174,7 +176,7 @@ SimulateButtonClicked(visible_items[1]); } -TEST_F(MediaNotificationFooterViewTest, OverflowButtonFallback) { +TEST_F(MediaItemUIFooterViewTest, OverflowButtonFallback) { CreateView(false); get_widget()->SetBounds(gfx::Rect(310, 20)); EXPECT_EQ(get_view()->children().size(), 0u); @@ -188,7 +190,7 @@ devices[1] = &device; // Two devices with 130px width should fit in the footer view (296px). - get_view()->OnMediaNotificationDeviceSelectorUpdated(devices); + get_view()->OnMediaItemUIDeviceSelectorUpdated(devices); get_widget()->LayoutRootViewIfNecessary(); auto visible_items = GetVisibleItems(); EXPECT_EQ(visible_items.size(), 2u); @@ -203,7 +205,7 @@ // (130px device button + 8px spacing + 130px device button + 8px spacing + // 30px overflow button > 296px maximum footer size) devices[2] = &device; - get_view()->OnMediaNotificationDeviceSelectorUpdated(devices); + get_view()->OnMediaItemUIDeviceSelectorUpdated(devices); get_widget()->LayoutRootViewIfNecessary(); visible_items = GetVisibleItems(); EXPECT_EQ(visible_items.size(), 2u);
diff --git a/chrome/browser/ui/views/global_media_controls/media_item_ui_legacy_cast_footer_view.cc b/chrome/browser/ui/views/global_media_controls/media_item_ui_legacy_cast_footer_view.cc new file mode 100644 index 0000000..7e159dc --- /dev/null +++ b/chrome/browser/ui/views/global_media_controls/media_item_ui_legacy_cast_footer_view.cc
@@ -0,0 +1,97 @@ +// Copyright 2021 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/global_media_controls/media_item_ui_legacy_cast_footer_view.h" + +#include "chrome/app/vector_icons/vector_icons.h" +#include "chrome/browser/feature_engagement/tracker_factory.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/global_media_controls/cast_media_notification_item.h" +#include "chrome/browser/ui/global_media_controls/media_notification_service.h" +#include "chrome/grit/generated_resources.h" +#include "components/feature_engagement/public/tracker.h" +#include "components/global_media_controls/public/media_item_manager.h" +#include "components/media_message_center/media_notification_item.h" +#include "components/media_router/browser/media_router.h" +#include "components/media_router/browser/media_router_factory.h" +#include "ui/base/l10n/l10n_util.h" +#include "ui/gfx/paint_vector_icon.h" +#include "ui/views/animation/ink_drop.h" +#include "ui/views/background.h" +#include "ui/views/border.h" +#include "ui/views/controls/button/label_button.h" +#include "ui/views/controls/highlight_path_generator.h" +#include "ui/views/layout/box_layout.h" + +namespace { + +constexpr gfx::Insets kInsets{6, 15}; +constexpr gfx::Size kSize{400, 30}; +constexpr gfx::Insets kBorderInsets{4, 8}; + +} // anonymous namespace + +MediaItemUILegacyCastFooterView::MediaItemUILegacyCastFooterView( + base::RepeatingClosure stop_casting_callback) + : stop_casting_callback_(stop_casting_callback) { + DCHECK(!stop_casting_callback_.is_null()); + + auto* layout = SetLayoutManager(std::make_unique<views::BoxLayout>( + views::BoxLayout::Orientation::kHorizontal, kInsets)); + layout->set_main_axis_alignment(views::BoxLayout::MainAxisAlignment::kStart); + layout->set_cross_axis_alignment( + views::BoxLayout::CrossAxisAlignment::kCenter); + SetPreferredSize(kSize); + + stop_cast_button_ = AddChildView(std::make_unique<views::LabelButton>( + base::BindRepeating(&MediaItemUILegacyCastFooterView::StopCasting, + base::Unretained(this)), + l10n_util::GetStringUTF16( + IDS_GLOBAL_MEDIA_CONTROLS_STOP_CASTING_BUTTON_LABEL))); + views::InstallRoundRectHighlightPathGenerator( + stop_cast_button_, gfx::Insets(), kSize.height() / 2); + + views::InkDrop::Get(stop_cast_button_) + ->SetMode(views::InkDropHost::InkDropMode::ON); + stop_cast_button_->SetFocusBehavior(FocusBehavior::ALWAYS); + stop_cast_button_->SetBorder(views::CreatePaddedBorder( + views::CreateRoundedRectBorder(1, kSize.height() / 2, foreground_color_), + kBorderInsets)); + UpdateColors(); +} + +MediaItemUILegacyCastFooterView::~MediaItemUILegacyCastFooterView() = default; + +views::Button* +MediaItemUILegacyCastFooterView::GetStopCastingButtonForTesting() { + return stop_cast_button_; +} + +void MediaItemUILegacyCastFooterView::OnColorsChanged(SkColor foreground, + SkColor background) { + if (foreground == foreground_color_ && background == background_color_) + return; + + foreground_color_ = foreground; + background_color_ = background; + + UpdateColors(); +} + +void MediaItemUILegacyCastFooterView::StopCasting() { + stop_cast_button_->SetEnabled(false); + stop_casting_callback_.Run(); +} + +void MediaItemUILegacyCastFooterView::UpdateColors() { + // Update background. + SetBackground(views::CreateSolidBackground(background_color_)); + + // Update button icon. + stop_cast_button_->SetEnabledTextColors(foreground_color_); + views::InkDrop::Get(stop_cast_button_)->SetBaseColor(foreground_color_); + stop_cast_button_->SetBorder(views::CreatePaddedBorder( + views::CreateRoundedRectBorder(1, kSize.height() / 2, foreground_color_), + kBorderInsets)); +}
diff --git a/chrome/browser/ui/views/global_media_controls/media_item_ui_legacy_cast_footer_view.h b/chrome/browser/ui/views/global_media_controls/media_item_ui_legacy_cast_footer_view.h new file mode 100644 index 0000000..05366cd --- /dev/null +++ b/chrome/browser/ui/views/global_media_controls/media_item_ui_legacy_cast_footer_view.h
@@ -0,0 +1,45 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_VIEWS_GLOBAL_MEDIA_CONTROLS_MEDIA_ITEM_UI_LEGACY_CAST_FOOTER_VIEW_H_ +#define CHROME_BROWSER_UI_VIEWS_GLOBAL_MEDIA_CONTROLS_MEDIA_ITEM_UI_LEGACY_CAST_FOOTER_VIEW_H_ + +#include "base/callback.h" +#include "components/global_media_controls/public/constants.h" +#include "components/global_media_controls/public/views/media_item_ui_footer.h" +#include "ui/gfx/color_palette.h" + +namespace views { +class Button; +class LabelButton; +} // namespace views + +// A footer view attached to MediaItemUIView for Cast items when modern UI is +// disabled. +class MediaItemUILegacyCastFooterView + : public global_media_controls::MediaItemUIFooter { + public: + explicit MediaItemUILegacyCastFooterView( + base::RepeatingClosure stop_casting_callback); + ~MediaItemUILegacyCastFooterView() override; + + // global_media_controls::MediaItemUIFooter: + void OnColorsChanged(SkColor foreground, SkColor background) override; + + views::Button* GetStopCastingButtonForTesting(); + + private: + void StopCasting(); + + void UpdateColors(); + + SkColor foreground_color_ = global_media_controls::kDefaultForegroundColor; + SkColor background_color_ = global_media_controls::kDefaultBackgroundColor; + + views::LabelButton* stop_cast_button_ = nullptr; + + const base::RepeatingClosure stop_casting_callback_; +}; + +#endif // CHROME_BROWSER_UI_VIEWS_GLOBAL_MEDIA_CONTROLS_MEDIA_ITEM_UI_LEGACY_CAST_FOOTER_VIEW_H_
diff --git a/chrome/browser/ui/views/global_media_controls/media_notification_container_impl_view.cc b/chrome/browser/ui/views/global_media_controls/media_notification_container_impl_view.cc deleted file mode 100644 index 61f853d..0000000 --- a/chrome/browser/ui/views/global_media_controls/media_notification_container_impl_view.cc +++ /dev/null
@@ -1,574 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/ui/views/global_media_controls/media_notification_container_impl_view.h" - -#include "base/bind.h" -#include "base/containers/contains.h" -#include "base/feature_list.h" -#include "base/metrics/field_trial_params.h" -#include "base/metrics/histogram_functions.h" -#include "chrome/browser/feature_engagement/tracker_factory.h" -#include "chrome/browser/media/router/media_router_feature.h" -#include "chrome/browser/profiles/profile.h" -#include "chrome/browser/ui/global_media_controls/cast_media_notification_item.h" -#include "chrome/browser/ui/global_media_controls/media_notification_service.h" -#include "chrome/browser/ui/global_media_controls/media_toolbar_button_controller.h" -#include "chrome/browser/ui/views/global_media_controls/media_dialog_view.h" -#include "chrome/browser/ui/views/global_media_controls/media_notification_device_selector_view.h" -#include "chrome/browser/ui/views/global_media_controls/media_notification_footer_view.h" -#include "chrome/grit/generated_resources.h" -#include "components/feature_engagement/public/tracker.h" -#include "components/global_media_controls/public/media_item_manager.h" -#include "components/global_media_controls/public/media_item_ui_observer.h" -#include "components/media_message_center/media_notification_item.h" -#include "components/media_message_center/media_notification_view_modern_impl.h" -#include "components/media_router/browser/media_router.h" -#include "components/media_router/browser/media_router_factory.h" -#include "components/vector_icons/vector_icons.h" -#include "media/audio/audio_device_description.h" -#include "ui/base/l10n/l10n_util.h" -#include "ui/base/metadata/metadata_header_macros.h" -#include "ui/base/metadata/metadata_impl_macros.h" -#include "ui/compositor/canvas_painter.h" -#include "ui/compositor/layer.h" -#include "ui/message_center/public/cpp/message_center_constants.h" -#include "ui/views/animation/ink_drop.h" -#include "ui/views/animation/slide_out_controller.h" -#include "ui/views/background.h" -#include "ui/views/border.h" -#include "ui/views/controls/button/image_button.h" -#include "ui/views/controls/button/image_button_factory.h" -#include "ui/views/controls/highlight_path_generator.h" -#include "ui/views/controls/image_view.h" -#include "ui/views/layout/box_layout.h" -#include "ui/views/layout/fill_layout.h" - -namespace { - -// TODO(steimel): We need to decide on the correct values here. -constexpr int kWidth = 400; -constexpr int kModernUIWidth = 350; -constexpr gfx::Size kNormalSize = gfx::Size(kWidth, 100); -constexpr gfx::Size kExpandedSize = gfx::Size(kWidth, 150); -constexpr gfx::Size kModernUISize = gfx::Size(kModernUIWidth, 168); -constexpr gfx::Size kDismissButtonSize = gfx::Size(30, 30); -constexpr int kDismissButtonIconSize = 20; -constexpr int kDismissButtonBackgroundRadius = 15; -constexpr SkColor kDefaultForegroundColor = SK_ColorBLACK; -constexpr SkColor kDefaultBackgroundColor = SK_ColorTRANSPARENT; -constexpr gfx::Insets kStopCastButtonStripInsets{6, 15}; -constexpr gfx::Size kStopCastButtonStripSize{400, 30}; -constexpr gfx::Insets kStopCastButtonBorderInsets{4, 8}; -constexpr gfx::Size kCrOSDismissButtonSize = gfx::Size(20, 20); -constexpr int kCrOSDismissButtonIconSize = 12; -constexpr gfx::Size kModernDismissButtonSize = gfx::Size(14, 14); -constexpr int kModernDismissButtonIconSize = 10; - -// The minimum number of enabled and visible user actions such that we should -// force the MediaNotificationView to be expanded. -constexpr int kMinVisibleActionsForExpanding = 4; - -} // anonymous namespace - -class MediaNotificationContainerImplView::DismissButton - : public views::ImageButton { - public: - METADATA_HEADER(DismissButton); - - explicit DismissButton(PressedCallback callback) - : views::ImageButton(std::move(callback)) { - views::ConfigureVectorImageButton(this); - views::InstallFixedSizeCircleHighlightPathGenerator( - this, kDismissButtonBackgroundRadius); - SetFocusBehavior(views::View::FocusBehavior::ALWAYS); - } - DismissButton(const DismissButton&) = delete; - DismissButton& operator=(const DismissButton&) = delete; - ~DismissButton() override = default; -}; - -BEGIN_METADATA(MediaNotificationContainerImplView, - DismissButton, - views::ImageButton) -END_METADATA - -MediaNotificationContainerImplView::MediaNotificationContainerImplView( - const std::string& id, - base::WeakPtr<media_message_center::MediaNotificationItem> item, - MediaNotificationService* service, - GlobalMediaControlsEntryPoint entry_point, - Profile* profile, - absl::optional<media_message_center::NotificationTheme> theme) - : views::Button(base::BindRepeating( - &MediaNotificationContainerImplView::ContainerClicked, - base::Unretained(this))), - id_(id), - foreground_color_(kDefaultForegroundColor), - background_color_(kDefaultBackgroundColor), - service_(service), - is_cros_(theme.has_value()), - entry_point_(entry_point), - profile_(profile) { - DCHECK(item); - SetLayoutManager(std::make_unique<views::BoxLayout>( - views::BoxLayout::Orientation::kVertical)); - SetPreferredSize(kNormalSize); - SetNotifyEnterExitOnChild(true); - SetFocusBehavior(views::View::FocusBehavior::ALWAYS); - SetTooltipText( - l10n_util::GetStringUTF16(IDS_GLOBAL_MEDIA_CONTROLS_BACK_TO_TAB)); - - auto swipeable_container = std::make_unique<views::View>(); - swipeable_container->SetLayoutManager(std::make_unique<views::FillLayout>()); - swipeable_container->SetPaintToLayer(); - swipeable_container->layer()->SetFillsBoundsOpaquely(false); - swipeable_container_ = AddChildView(std::move(swipeable_container)); - - gfx::Size dismiss_button_size = - is_cros_ ? kCrOSDismissButtonSize : kDismissButtonSize; - if (base::FeatureList::IsEnabled(media::kGlobalMediaControlsModernUI)) - dismiss_button_size = kModernDismissButtonSize; - - auto dismiss_button_placeholder = std::make_unique<views::View>(); - dismiss_button_placeholder->SetPreferredSize(dismiss_button_size); - dismiss_button_placeholder->SetLayoutManager( - std::make_unique<views::FillLayout>()); - dismiss_button_placeholder_ = dismiss_button_placeholder.get(); - - auto dismiss_button_container = std::make_unique<views::View>(); - dismiss_button_container->SetPreferredSize(dismiss_button_size); - dismiss_button_container->SetLayoutManager( - std::make_unique<views::FillLayout>()); - dismiss_button_container->SetVisible(false); - dismiss_button_container_ = dismiss_button_placeholder_->AddChildView( - std::move(dismiss_button_container)); - - auto dismiss_button = std::make_unique<DismissButton>(base::BindRepeating( - &MediaNotificationContainerImplView::DismissNotification, - base::Unretained(this))); - dismiss_button->SetPreferredSize(dismiss_button_size); - dismiss_button->SetTooltipText(l10n_util::GetStringUTF16( - IDS_GLOBAL_MEDIA_CONTROLS_DISMISS_ICON_TOOLTIP_TEXT)); - dismiss_button_ = - dismiss_button_container_->AddChildView(std::move(dismiss_button)); - UpdateDismissButtonIcon(); - - // Compute a few things related to |item| before the construction of |view| - // below moves it. - const bool is_cast_notification = - item->SourceType() == media_message_center::SourceType::kCast; - auto* const cast_item = - is_cast_notification ? static_cast<CastMediaNotificationItem*>(item.get()) - : nullptr; - const bool is_local_media_session = - item->SourceType() == - media_message_center::SourceType::kLocalMediaSession; - - std::unique_ptr<media_message_center::MediaNotificationView> view; - if (base::FeatureList::IsEnabled(media::kGlobalMediaControlsModernUI)) { - auto footer_view = std::make_unique<MediaNotificationFooterView>( - is_cast_notification, - is_cast_notification - ? base::BindRepeating( - &MediaNotificationContainerImplView::StopCasting, - base::Unretained(this), base::Unretained(cast_item)) - : views::Button::PressedCallback()); - footer_view_ = footer_view.get(); - - view = - std::make_unique<media_message_center::MediaNotificationViewModernImpl>( - this, std::move(item), std::move(dismiss_button_placeholder), - std::move(footer_view), kModernUIWidth); - SetPreferredSize(kModernUISize); - } else { - view = std::make_unique<media_message_center::MediaNotificationViewImpl>( - this, std::move(item), std::move(dismiss_button_placeholder), - std::u16string(), kWidth, /*should_show_icon=*/false, theme); - SetPreferredSize(kNormalSize); - } - view_ = swipeable_container_->AddChildView(std::move(view)); - bool gmc_cast_start_stop_enabled = - media_router::GlobalMediaControlsCastStartStopEnabled() && - media_router::MediaRouterEnabled(profile_); - // Show a stop cast button for cast notifications. - if (is_cast_notification && gmc_cast_start_stop_enabled && - !base::FeatureList::IsEnabled(media::kGlobalMediaControlsModernUI)) { - AddStopCastButton(cast_item); - } - - // Show a device selector view for media and supplemental notifications. - if (!is_cast_notification && - (gmc_cast_start_stop_enabled || - base::FeatureList::IsEnabled( - media::kGlobalMediaControlsSeamlessTransfer))) { - AddDeviceSelectorView( - is_local_media_session, - /* show_expand_button */ !base::FeatureList::IsEnabled( - media::kGlobalMediaControlsModernUI)); - if (device_selector_view_ && footer_view_) { - footer_view_->SetDelegate(device_selector_view_); - device_selector_view_->AddObserver(footer_view_); - } - } - - ForceExpandedState(); - - slide_out_controller_ = - std::make_unique<views::SlideOutController>(this, this); -} - -MediaNotificationContainerImplView::~MediaNotificationContainerImplView() { - for (auto& observer : observers_) - observer.OnMediaItemUIDestroyed(id_); -} - -void MediaNotificationContainerImplView::AddedToWidget() { - if (GetFocusManager()) - GetFocusManager()->AddFocusChangeListener(this); -} - -void MediaNotificationContainerImplView::RemovedFromWidget() { - if (GetFocusManager()) - GetFocusManager()->RemoveFocusChangeListener(this); -} - -void MediaNotificationContainerImplView::OnMouseEntered( - const ui::MouseEvent& event) { - UpdateDismissButtonVisibility(); -} - -void MediaNotificationContainerImplView::OnMouseExited( - const ui::MouseEvent& event) { - UpdateDismissButtonVisibility(); -} - -void MediaNotificationContainerImplView::OnDidChangeFocus( - views::View* focused_before, - views::View* focused_now) { - UpdateDismissButtonVisibility(); -} - -void MediaNotificationContainerImplView::OnExpanded(bool expanded) { - is_expanded_ = expanded; - OnSizeChanged(); -} - -void MediaNotificationContainerImplView::OnMediaSessionInfoChanged( - const media_session::mojom::MediaSessionInfoPtr& session_info) { - is_playing_ = - session_info && session_info->playback_state == - media_session::mojom::MediaPlaybackState::kPlaying; - if (session_info) { - audio_sink_id_ = session_info->audio_sink_id.value_or( - media::AudioDeviceDescription::kDefaultDeviceId); - if (device_selector_view_ && - base::FeatureList::IsEnabled( - media::kGlobalMediaControlsSeamlessTransfer)) { - device_selector_view_->UpdateCurrentAudioDevice(audio_sink_id_); - } - } -} - -void MediaNotificationContainerImplView::OnMediaSessionMetadataChanged( - const media_session::MediaMetadata& metadata) { - title_ = metadata.title; - - for (auto& observer : observers_) - observer.OnMediaItemUIMetadataChanged(); -} - -void MediaNotificationContainerImplView::OnVisibleActionsChanged( - const base::flat_set<media_session::mojom::MediaSessionAction>& actions) { - has_many_actions_ = - (actions.size() >= kMinVisibleActionsForExpanding || - base::Contains( - actions, - media_session::mojom::MediaSessionAction::kEnterPictureInPicture) || - base::Contains( - actions, - media_session::mojom::MediaSessionAction::kExitPictureInPicture)); - ForceExpandedState(); - - for (auto& observer : observers_) - observer.OnMediaItemUIActionsChanged(); -} - -void MediaNotificationContainerImplView::OnMediaArtworkChanged( - const gfx::ImageSkia& image) { - has_artwork_ = !image.isNull(); - - UpdateDismissButtonBackground(); - ForceExpandedState(); -} - -void MediaNotificationContainerImplView::OnColorsChanged(SkColor foreground, - SkColor background) { - if (foreground_color_ != foreground) { - foreground_color_ = foreground; - UpdateDismissButtonIcon(); - UpdateStopCastButtonIcon(); - } - - if (background_color_ != background) { - background_color_ = background; - UpdateDismissButtonBackground(); - UpdateStopCastButtonBackground(); - } - if (footer_view_) - footer_view_->OnColorChanged(foreground); - - if (device_selector_view_) - device_selector_view_->OnColorsChanged(foreground, background); -} - -void MediaNotificationContainerImplView::OnHeaderClicked() { - // Since we disable the expand button, nothing happens on the - // MediaNotificationView when the header is clicked. Treat the click as if we - // were clicked directly. - ContainerClicked(); -} - -void MediaNotificationContainerImplView::OnAudioSinkChosen( - const std::string& sink_id) { - for (auto& observer : observers_) { - observer.OnAudioSinkChosen(id_, sink_id); - } -} - -void MediaNotificationContainerImplView::OnDeviceSelectorViewSizeChanged() { - OnSizeChanged(); -} - -base::CallbackListSubscription MediaNotificationContainerImplView:: - RegisterAudioOutputDeviceDescriptionsCallback( - MediaNotificationDeviceProvider::GetOutputDevicesCallbackList:: - CallbackType callback) { - return service_->RegisterAudioOutputDeviceDescriptionsCallback( - std::move(callback)); -} - -base::CallbackListSubscription MediaNotificationContainerImplView:: - RegisterIsAudioOutputDeviceSwitchingSupportedCallback( - base::RepeatingCallback<void(bool)> callback) { - return service_->RegisterIsAudioOutputDeviceSwitchingSupportedCallback( - id_, std::move(callback)); -} - -ui::Layer* MediaNotificationContainerImplView::GetSlideOutLayer() { - return swipeable_container_->layer(); -} - -void MediaNotificationContainerImplView::OnSlideOut() { - DismissNotification(); -} - -void MediaNotificationContainerImplView::AddObserver( - global_media_controls::MediaItemUIObserver* observer) { - observers_.AddObserver(observer); -} - -void MediaNotificationContainerImplView::RemoveObserver( - global_media_controls::MediaItemUIObserver* observer) { - observers_.RemoveObserver(observer); -} - -const std::u16string& MediaNotificationContainerImplView::GetTitle() const { - return title_; -} - -views::ImageButton* -MediaNotificationContainerImplView::GetDismissButtonForTesting() { - return dismiss_button_; -} - -views::Button* -MediaNotificationContainerImplView::GetStopCastingButtonForTesting() { - return stop_cast_button_; -} - -void MediaNotificationContainerImplView::AddStopCastButton( - CastMediaNotificationItem* cast_item) { - DCHECK(cast_item); - stop_button_strip_ = AddChildView(std::make_unique<views::View>()); - auto* stop_cast_button_strip_layout = - stop_button_strip_->SetLayoutManager(std::make_unique<views::BoxLayout>( - views::BoxLayout::Orientation::kHorizontal, - kStopCastButtonStripInsets)); - stop_cast_button_strip_layout->set_main_axis_alignment( - views::BoxLayout::MainAxisAlignment::kStart); - stop_cast_button_strip_layout->set_cross_axis_alignment( - views::BoxLayout::CrossAxisAlignment::kCenter); - stop_button_strip_->SetPreferredSize(kStopCastButtonStripSize); - UpdateStopCastButtonBackground(); - - stop_cast_button_ = - stop_button_strip_->AddChildView(std::make_unique<views::LabelButton>( - base::BindRepeating(&MediaNotificationContainerImplView::StopCasting, - base::Unretained(this), - base::Unretained(cast_item)), - l10n_util::GetStringUTF16( - IDS_GLOBAL_MEDIA_CONTROLS_STOP_CASTING_BUTTON_LABEL))); - views::InstallRoundRectHighlightPathGenerator( - stop_cast_button_, gfx::Insets(), kStopCastButtonStripSize.height() / 2); - - views::InkDrop::Get(stop_cast_button_) - ->SetMode(views::InkDropHost::InkDropMode::ON); - stop_cast_button_->SetFocusBehavior(FocusBehavior::ALWAYS); - stop_cast_button_->SetBorder(views::CreatePaddedBorder( - views::CreateRoundedRectBorder(1, kStopCastButtonStripSize.height() / 2, - foreground_color_), - kStopCastButtonBorderInsets)); - UpdateStopCastButtonIcon(); -} - -void MediaNotificationContainerImplView::AddDeviceSelectorView( - bool is_local_media_session, - bool show_expand_button) { - std::unique_ptr<media_router::CastDialogController> cast_controller; - if (media_router::GlobalMediaControlsCastStartStopEnabled() && - media_router::MediaRouterEnabled(profile_)) { - cast_controller = - is_local_media_session - ? service_->CreateCastDialogControllerForSession(id_) - : service_->CreateCastDialogControllerForPresentationRequest(); - } - auto device_selector_view = - std::make_unique<MediaNotificationDeviceSelectorView>( - this, std::move(cast_controller), - /* has_audio_output */ is_local_media_session, audio_sink_id_, - foreground_color_, background_color_, entry_point_, - show_expand_button); - device_selector_view_ = AddChildView(std::move(device_selector_view)); - view_->UpdateCornerRadius(message_center::kNotificationCornerRadius, 0); -} - -void MediaNotificationContainerImplView::StopCasting( - CastMediaNotificationItem* cast_item) { - stop_cast_button_->SetEnabled(false); - - media_router::MediaRouterFactory::GetApiForBrowserContext( - cast_item->profile()) - ->TerminateRoute(cast_item->route_id()); - - // |service_| is nullptr in MediaNotificationContainerImplViewTest. - if (service_) - service_->media_item_manager()->FocusDialog(); - - feature_engagement::TrackerFactory::GetForBrowserContext(profile_) - ->NotifyEvent("media_route_stopped_from_gmc"); - - GlobalMediaControlsCastActionAndEntryPoint action; - switch (entry_point_) { - case GlobalMediaControlsEntryPoint::kToolbarIcon: - action = GlobalMediaControlsCastActionAndEntryPoint::kStopViaToolbarIcon; - break; - case GlobalMediaControlsEntryPoint::kPresentation: - action = GlobalMediaControlsCastActionAndEntryPoint::kStopViaPresentation; - break; - case GlobalMediaControlsEntryPoint::kSystemTray: - action = GlobalMediaControlsCastActionAndEntryPoint::kStopViaSystemTray; - break; - } - base::UmaHistogramEnumeration( - media_message_center::MediaNotificationItem::kCastStartStopHistogramName, - action); -} - -void MediaNotificationContainerImplView::UpdateStopCastButtonIcon() { - if (!stop_cast_button_) - return; - stop_cast_button_->SetEnabledTextColors(foreground_color_); - views::InkDrop::Get(stop_cast_button_)->SetBaseColor(foreground_color_); - stop_cast_button_->SetBorder(views::CreatePaddedBorder( - views::CreateRoundedRectBorder(1, kStopCastButtonStripSize.height() / 2, - foreground_color_), - kStopCastButtonBorderInsets)); -} - -void MediaNotificationContainerImplView::UpdateStopCastButtonBackground() { - if (!stop_button_strip_) - return; - stop_button_strip_->SetBackground( - views::CreateSolidBackground(background_color_)); -} - -void MediaNotificationContainerImplView::UpdateDismissButtonIcon() { - int icon_size = - is_cros_ ? kCrOSDismissButtonIconSize : kDismissButtonIconSize; - if (base::FeatureList::IsEnabled(media::kGlobalMediaControlsModernUI)) - icon_size = kModernDismissButtonIconSize; - - views::SetImageFromVectorIconWithColor(dismiss_button_, - vector_icons::kCloseRoundedIcon, - icon_size, foreground_color_); -} - -void MediaNotificationContainerImplView::UpdateDismissButtonBackground() { - if (!has_artwork_) { - dismiss_button_container_->SetBackground(nullptr); - return; - } - - dismiss_button_container_->SetBackground(views::CreateRoundedRectBackground( - background_color_, kDismissButtonBackgroundRadius)); -} - -void MediaNotificationContainerImplView::UpdateDismissButtonVisibility() { - bool has_focus = false; - if (GetFocusManager()) { - views::View* focused_view = GetFocusManager()->GetFocusedView(); - if (focused_view) - has_focus = Contains(focused_view); - } - - dismiss_button_container_->SetVisible(IsMouseHovered() || has_focus); -} - -void MediaNotificationContainerImplView::DismissNotification() { - for (auto& observer : observers_) - observer.OnMediaItemUIDismissed(id_); -} - -void MediaNotificationContainerImplView::ForceExpandedState() { - if (view_) { - bool should_expand = has_many_actions_ || has_artwork_; - view_->SetForcedExpandedState(&should_expand); - } -} - -void MediaNotificationContainerImplView::ContainerClicked() { - for (auto& observer : observers_) - observer.OnMediaItemUIClicked(id_); -} - -void MediaNotificationContainerImplView::OnSizeChanged() { - gfx::Size new_size; - if (base::FeatureList::IsEnabled(media::kGlobalMediaControlsModernUI)) { - new_size = kModernUISize; - } else { - new_size = is_expanded_ ? kExpandedSize : kNormalSize; - } - - // |new_size| does not contain the height for the device selector view. - // If this view is present, we should query it for its preferred height and - // include that in |new_size|. - if (device_selector_view_) { - auto device_selector_view_size = device_selector_view_->GetPreferredSize(); - DCHECK(device_selector_view_size.width() == kWidth); - new_size.set_height(new_size.height() + device_selector_view_size.height()); - view_->UpdateDeviceSelectorAvailability( - device_selector_view_->GetVisible()); - } - - SetPreferredSize(new_size); - PreferredSizeChanged(); - - for (auto& observer : observers_) - observer.OnMediaItemUISizeChanged(); -} - -BEGIN_METADATA(MediaNotificationContainerImplView, views::Button) -ADD_READONLY_PROPERTY_METADATA(std::u16string, Title) -END_METADATA
diff --git a/chrome/browser/ui/views/global_media_controls/media_notification_container_impl_view_unittest.cc b/chrome/browser/ui/views/global_media_controls/media_notification_container_impl_view_unittest.cc deleted file mode 100644 index 7bfeb20f..0000000 --- a/chrome/browser/ui/views/global_media_controls/media_notification_container_impl_view_unittest.cc +++ /dev/null
@@ -1,458 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/ui/views/global_media_controls/media_notification_container_impl_view.h" - -#include <memory> -#include <utility> - -#include "base/containers/flat_set.h" -#include "base/strings/utf_string_conversions.h" -#include "base/test/scoped_feature_list.h" -#include "build/build_config.h" -#include "chrome/browser/media/router/media_router_feature.h" -#include "chrome/browser/ui/global_media_controls/cast_media_notification_item.h" -#include "chrome/browser/ui/global_media_controls/cast_media_session_controller.h" -#include "chrome/browser/ui/global_media_controls/test_helper.h" -#include "chrome/test/base/testing_profile.h" -#include "chrome/test/views/chrome_views_test_base.h" -#include "components/global_media_controls/public/test/mock_media_item_manager.h" -#include "components/global_media_controls/public/test/mock_media_item_ui_observer.h" -#include "components/media_router/browser/media_router_factory.h" -#include "components/media_router/browser/test/mock_media_router.h" -#include "media/base/media_switches.h" -#include "services/media_session/public/mojom/media_session.mojom.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "ui/display/test/scoped_screen_override.h" -#include "ui/display/test/test_screen.h" -#include "ui/events/base_event_utils.h" -#include "ui/events/test/event_generator.h" -#include "ui/views/test/button_test_api.h" -#include "ui/views/test/view_metadata_test_utils.h" -#include "ui/views/widget/widget_utils.h" - -using media_session::mojom::MediaPlaybackState; -using media_session::mojom::MediaSessionAction; -using ::testing::_; -using ::testing::NiceMock; - -namespace { - -const char kTestNotificationId[] = "testid"; -const char kOtherTestNotificationId[] = "othertestid"; -const char kRouteId[] = "route_id"; - -media_router::MediaRoute CreateMediaRoute() { - media_router::MediaRoute route(kRouteId, - media_router::MediaSource("source_id"), - "sink_id", "route_description", - /* is_local */ true, /* for_display */ true); - route.set_media_sink_name("sink_name"); - return route; -} - -class MockSessionController : public CastMediaSessionController { - public: - MockSessionController( - mojo::Remote<media_router::mojom::MediaController> remote) - : CastMediaSessionController(std::move(remote)) {} - - MOCK_METHOD1(Send, void(media_session::mojom::MediaSessionAction)); - MOCK_METHOD1(OnMediaStatusUpdated, void(media_router::mojom::MediaStatusPtr)); -}; - -} // anonymous namespace - -class MediaNotificationContainerImplViewTest : public ChromeViewsTestBase { - public: - MediaNotificationContainerImplViewTest() : screen_override_(&fake_screen_) {} - MediaNotificationContainerImplViewTest( - const MediaNotificationContainerImplViewTest&) = delete; - MediaNotificationContainerImplViewTest& operator=( - const MediaNotificationContainerImplViewTest&) = delete; - ~MediaNotificationContainerImplViewTest() override = default; - - // ViewsTestBase: - void SetUp() override { - ViewsTestBase::SetUp(); - item_ = std::make_unique<NiceMock<MockMediaNotificationItem>>(); - SetUpCommon(std::make_unique<MediaNotificationContainerImplView>( - kTestNotificationId, item_->GetWeakPtr(), nullptr, - GlobalMediaControlsEntryPoint::kToolbarIcon, nullptr)); - } - - void SetUpCommon(std::unique_ptr<MediaNotificationContainerImplView> - notification_container) { - widget_ = CreateTestWidget(); - - notification_container_ = - widget_->SetContentsView(std::move(notification_container)); - - observer_ = std::make_unique< - NiceMock<global_media_controls::test::MockMediaItemUIObserver>>(); - notification_container_->AddObserver(observer_.get()); - - SimulateMediaSessionData(); - - widget_->Show(); - } - - void TearDown() override { - notification_container_->RemoveObserver(observer_.get()); - widget_.reset(); - ViewsTestBase::TearDown(); - } - - void SimulateNotificationSwipedToDismiss() { - // When the notification is swiped, the SlideOutController sends this to the - // MediaNotificationContainerImplView. - notification_container()->OnSlideOut(); - } - - bool IsDismissButtonVisible() { return GetDismissButton()->IsDrawn(); } - - void SimulateHoverOverContainer() { - fake_screen_.set_cursor_screen_point( - notification_container_->GetBoundsInScreen().CenterPoint()); - - ui::MouseEvent event(ui::ET_MOUSE_ENTERED, gfx::Point(), gfx::Point(), - ui::EventTimeForNow(), 0, 0); - notification_container_->OnMouseEntered(event); - } - - void SimulateNotHoveringOverContainer() { - gfx::Rect container_bounds = notification_container_->GetBoundsInScreen(); - gfx::Point point_outside_container = - container_bounds.bottom_right() + gfx::Vector2d(1, 1); - fake_screen_.set_cursor_screen_point(point_outside_container); - - ui::MouseEvent event(ui::ET_MOUSE_EXITED, gfx::Point(), gfx::Point(), - ui::EventTimeForNow(), 0, 0); - notification_container_->OnMouseExited(event); - } - - void SimulateContainerClicked() { - ui::MouseEvent event(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(), - ui::EventTimeForNow(), 0, 0); - views::test::ButtonTestApi(notification_container_).NotifyClick(event); - } - - void SimulateHeaderClicked() { - ui::MouseEvent event(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(), - ui::EventTimeForNow(), 0, 0); - views::test::ButtonTestApi(GetView()->GetHeaderRowForTesting()) - .NotifyClick(event); - } - - void SimulateDismissButtonClicked() { - ui::MouseEvent event(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(), - ui::EventTimeForNow(), 0, 0); - views::test::ButtonTestApi(GetDismissButton()).NotifyClick(event); - } - - void SimulatePressingDismissButtonWithKeyboard() { - GetFocusManager()->SetFocusedView( - notification_container_->GetDismissButtonForTesting()); - -// On Mac OS, we need to use the space bar to press a button. -#if defined(OS_MAC) - ui::KeyboardCode button_press_keycode = ui::VKEY_SPACE; -#else - ui::KeyboardCode button_press_keycode = ui::VKEY_RETURN; -#endif // defined(OS_MAC) - - ui::test::EventGenerator generator(GetRootWindow(widget_.get())); - generator.PressKey(button_press_keycode, 0); - } - - void SimulateSessionPlaying() { SimulateSessionInfo(true); } - - void SimulateSessionPaused() { SimulateSessionInfo(false); } - - void SimulateMetadataChanged() { - media_session::MediaMetadata metadata; - metadata.source_title = u"source_title2"; - metadata.title = u"title2"; - metadata.artist = u"artist2"; - GetView()->UpdateWithMediaMetadata(metadata); - } - - void SimulateAllActionsEnabled() { - actions_.insert(MediaSessionAction::kPlay); - actions_.insert(MediaSessionAction::kPause); - actions_.insert(MediaSessionAction::kPreviousTrack); - actions_.insert(MediaSessionAction::kNextTrack); - actions_.insert(MediaSessionAction::kSeekBackward); - actions_.insert(MediaSessionAction::kSeekForward); - actions_.insert(MediaSessionAction::kStop); - - NotifyUpdatedActions(); - } - - void SimulateOnlyPlayPauseEnabled() { - actions_.clear(); - actions_.insert(MediaSessionAction::kPlay); - actions_.insert(MediaSessionAction::kPause); - NotifyUpdatedActions(); - } - - void SimulateHasArtwork() { - SkBitmap image; - image.allocN32Pixels(10, 10); - image.eraseColor(SK_ColorMAGENTA); - GetView()->UpdateWithMediaArtwork( - gfx::ImageSkia::CreateFrom1xBitmap(image)); - } - - void SimulateHasNoArtwork() { - GetView()->UpdateWithMediaArtwork(gfx::ImageSkia()); - } - - views::FocusManager* GetFocusManager() { - return notification_container_->GetFocusManager(); - } - - global_media_controls::test::MockMediaItemUIObserver& observer() { - return *observer_; - } - - MediaNotificationContainerImplView* notification_container() { - return notification_container_; - } - - base::WeakPtr<MockMediaNotificationItem> notification_item() { - return item_->GetWeakPtr(); - } - - private: - void SimulateSessionInfo(bool playing) { - media_session::mojom::MediaSessionInfoPtr session_info( - media_session::mojom::MediaSessionInfo::New()); - session_info->playback_state = - playing ? MediaPlaybackState::kPlaying : MediaPlaybackState::kPaused; - session_info->is_controllable = true; - - GetView()->UpdateWithMediaSessionInfo(std::move(session_info)); - } - - void SimulateMediaSessionData() { - SimulateSessionInfo(true); - - media_session::MediaMetadata metadata; - metadata.source_title = u"source_title"; - metadata.title = u"title"; - metadata.artist = u"artist"; - GetView()->UpdateWithMediaMetadata(metadata); - - SimulateOnlyPlayPauseEnabled(); - } - - void NotifyUpdatedActions() { GetView()->UpdateWithMediaActions(actions_); } - - media_message_center::MediaNotificationViewImpl* GetView() { - return notification_container()->view_for_testing(); - } - - views::ImageButton* GetDismissButton() { - return notification_container()->GetDismissButtonForTesting(); - } - - std::unique_ptr<views::Widget> widget_; - MediaNotificationContainerImplView* notification_container_ = nullptr; - std::unique_ptr<global_media_controls::test::MockMediaItemUIObserver> - observer_; - std::unique_ptr<MockMediaNotificationItem> item_; - - // Set of actions currently enabled. - base::flat_set<MediaSessionAction> actions_; - - display::test::TestScreen fake_screen_; - display::test::ScopedScreenOverride screen_override_; -}; - -// TODO(b/185139027): Remove this class once -// |media_router::kGlobalMediaControlsCastStartStop| is enabled by default. -class MediaNotificationContainerImplViewCastTest - : public MediaNotificationContainerImplViewTest { - public: - void SetUp() override { - ViewsTestBase::SetUp(); - feature_list_.InitWithFeatures( - {media::kGlobalMediaControlsForCast, - media_router::kGlobalMediaControlsCastStartStop}, - {}); - - media_router::MediaRouterFactory::GetInstance()->SetTestingFactory( - &profile_, base::BindRepeating(&media_router::MockMediaRouter::Create)); - - auto session_controller = std::make_unique<MockSessionController>( - mojo::Remote<media_router::mojom::MediaController>()); - session_controller_ = session_controller.get(); - item_ = std::make_unique<CastMediaNotificationItem>( - CreateMediaRoute(), &item_manager_, std::move(session_controller), - &profile_); - - SetUpCommon(std::make_unique<MediaNotificationContainerImplView>( - kTestNotificationId, item_->GetWeakPtr(), nullptr, - GlobalMediaControlsEntryPoint::kToolbarIcon, profile())); - } - - void TearDown() override { - // Delete |item_| before |item_manager_|. - item_.reset(); - MediaNotificationContainerImplViewTest::TearDown(); - } - - void SimulateStopCastingButtonClicked() { - ui::MouseEvent event(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(), - ui::EventTimeForNow(), 0, 0); - views::test::ButtonTestApi( - notification_container()->GetStopCastingButtonForTesting()) - .NotifyClick(event); - } - - CastMediaNotificationItem* item() { return item_.get(); } - Profile* profile() { return &profile_; } - global_media_controls::test::MockMediaItemManager* item_manager() { - return &item_manager_; - } - - private: - base::test::ScopedFeatureList feature_list_; - TestingProfile profile_; - std::unique_ptr<CastMediaNotificationItem> item_; - NiceMock<global_media_controls::test::MockMediaItemManager> item_manager_; - MockSessionController* session_controller_ = nullptr; -}; - -TEST_F(MediaNotificationContainerImplViewCastTest, StopCasting) { - auto* mock_router = static_cast<media_router::MockMediaRouter*>( - media_router::MediaRouterFactory::GetApiForBrowserContext(profile())); - EXPECT_CALL(*mock_router, TerminateRoute(kRouteId)); - - SimulateStopCastingButtonClicked(); -} - -TEST_F(MediaNotificationContainerImplViewTest, SwipeToDismiss) { - EXPECT_CALL(observer(), OnMediaItemUIDismissed(kTestNotificationId)); - SimulateNotificationSwipedToDismiss(); -} - -TEST_F(MediaNotificationContainerImplViewTest, ClickToDismiss) { - // Ensure that the mouse is not over the container and that nothing is - // focused. The dismiss button should not be visible. - SimulateNotHoveringOverContainer(); - ASSERT_EQ(nullptr, GetFocusManager()->GetFocusedView()); - ASSERT_FALSE(notification_container()->IsMouseHovered()); - EXPECT_FALSE(IsDismissButtonVisible()); - - // Hovering over the notification should show the dismiss button. - SimulateHoverOverContainer(); - EXPECT_TRUE(IsDismissButtonVisible()); - - // Moving the mouse away from the notification should hide the dismiss button. - SimulateNotHoveringOverContainer(); - EXPECT_FALSE(IsDismissButtonVisible()); - - // Moving the mouse back over the notification should re-show it. - SimulateHoverOverContainer(); - EXPECT_TRUE(IsDismissButtonVisible()); - - // Clicking it should inform observers that we've been dismissed. - EXPECT_CALL(observer(), OnMediaItemUIDismissed(kTestNotificationId)); - SimulateDismissButtonClicked(); - testing::Mock::VerifyAndClearExpectations(&observer()); -} - -TEST_F(MediaNotificationContainerImplViewTest, KeyboardToDismiss) { - // Ensure that the mouse is not over the container and that nothing is - // focused. The dismiss button should not be visible. - SimulateNotHoveringOverContainer(); - ASSERT_EQ(nullptr, GetFocusManager()->GetFocusedView()); - ASSERT_FALSE(notification_container()->IsMouseHovered()); - EXPECT_FALSE(IsDismissButtonVisible()); - - // When the notification receives keyboard focus, the dismiss button should be - // visible. - GetFocusManager()->SetFocusedView(notification_container()); - EXPECT_TRUE(IsDismissButtonVisible()); - - // When the notification loses keyboard focus, the dismiss button should be - // hidden. - GetFocusManager()->SetFocusedView(nullptr); - EXPECT_FALSE(IsDismissButtonVisible()); - - // If it gets focus again, it should re-show the dismiss button. - GetFocusManager()->SetFocusedView(notification_container()); - EXPECT_TRUE(IsDismissButtonVisible()); - - // Clicking it should inform observers that we've been dismissed. - EXPECT_CALL(observer(), OnMediaItemUIDismissed(kTestNotificationId)); - SimulatePressingDismissButtonWithKeyboard(); - testing::Mock::VerifyAndClearExpectations(&observer()); -} - -TEST_F(MediaNotificationContainerImplViewTest, ForceExpandedState) { - // When we have many actions enabled, we should be forced into the expanded - // state. - SimulateAllActionsEnabled(); - EXPECT_TRUE(notification_container()->is_expanded_for_testing()); - - // When we don't have many actions enabled, we should be forced out of the - // expanded state. - SimulateOnlyPlayPauseEnabled(); - EXPECT_FALSE(notification_container()->is_expanded_for_testing()); - - // We will also be forced into the expanded state when artwork is present. - SimulateHasArtwork(); - EXPECT_TRUE(notification_container()->is_expanded_for_testing()); - - // Once the artwork is gone, we should be forced back out of the expanded - // state. - SimulateHasNoArtwork(); - EXPECT_FALSE(notification_container()->is_expanded_for_testing()); -} - -TEST_F(MediaNotificationContainerImplViewTest, SendsMetadataUpdates) { - EXPECT_CALL(observer(), OnMediaItemUIMetadataChanged()); - SimulateMetadataChanged(); -} - -TEST_F(MediaNotificationContainerImplViewTest, SendsDestroyedUpdates) { - auto container = std::make_unique<MediaNotificationContainerImplView>( - kOtherTestNotificationId, notification_item(), nullptr, - GlobalMediaControlsEntryPoint::kToolbarIcon, nullptr); - global_media_controls::test::MockMediaItemUIObserver observer; - container->AddObserver(&observer); - - // When the container is destroyed, it should notify the observer. - EXPECT_CALL(observer, OnMediaItemUIDestroyed(kOtherTestNotificationId)); - container.reset(); - testing::Mock::VerifyAndClearExpectations(&observer); -} - -TEST_F(MediaNotificationContainerImplViewTest, SendsClicks) { - // When the container is clicked directly, it should notify its observers. - EXPECT_CALL(observer(), OnMediaItemUIClicked(kTestNotificationId)); - SimulateContainerClicked(); - testing::Mock::VerifyAndClearExpectations(&observer()); - - // It should also notify its observers when the header is clicked. - EXPECT_CALL(observer(), OnMediaItemUIClicked(kTestNotificationId)); - SimulateHeaderClicked(); -} - -TEST_F(MediaNotificationContainerImplViewTest, SendsSinkUpdates) { - // The container should notify its observers when an audio output device has - // been chosen. - EXPECT_CALL(observer(), OnAudioSinkChosen(kTestNotificationId, "foobar")); - notification_container()->OnAudioSinkChosen("foobar"); -} - -TEST_F(MediaNotificationContainerImplViewTest, MetadataTest) { - auto container_view = std::make_unique<MediaNotificationContainerImplView>( - kOtherTestNotificationId, notification_item(), nullptr, - GlobalMediaControlsEntryPoint::kToolbarIcon, nullptr); - views::test::TestViewMetadata(container_view.get()); -}
diff --git a/chrome/browser/ui/views/global_media_controls/media_notification_device_selector_observer.h b/chrome/browser/ui/views/global_media_controls/media_notification_device_selector_observer.h deleted file mode 100644 index d9d5824..0000000 --- a/chrome/browser/ui/views/global_media_controls/media_notification_device_selector_observer.h +++ /dev/null
@@ -1,22 +0,0 @@ -// Copyright 2021 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_UI_VIEWS_GLOBAL_MEDIA_CONTROLS_MEDIA_NOTIFICATION_DEVICE_SELECTOR_OBSERVER_H_ -#define CHROME_BROWSER_UI_VIEWS_GLOBAL_MEDIA_CONTROLS_MEDIA_NOTIFICATION_DEVICE_SELECTOR_OBSERVER_H_ - -#include <map> - -#include "base/observer_list_types.h" - -class DeviceEntryUI; - -class MediaNotificationDeviceSelectorObserver : public base::CheckedObserver { - public: - // Called by MediaNotificationDeviceSelector view when available devices - // changed. - virtual void OnMediaNotificationDeviceSelectorUpdated( - const std::map<int, DeviceEntryUI*>& device_entries_map) = 0; -}; - -#endif // CHROME_BROWSER_UI_VIEWS_GLOBAL_MEDIA_CONTROLS_MEDIA_NOTIFICATION_DEVICE_SELECTOR_OBSERVER_H_
diff --git a/chrome/browser/ui/views/global_media_controls/media_notification_device_selector_view_delegate.h b/chrome/browser/ui/views/global_media_controls/media_notification_device_selector_view_delegate.h deleted file mode 100644 index 0b94983..0000000 --- a/chrome/browser/ui/views/global_media_controls/media_notification_device_selector_view_delegate.h +++ /dev/null
@@ -1,23 +0,0 @@ -// Copyright 2020 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -#ifndef CHROME_BROWSER_UI_VIEWS_GLOBAL_MEDIA_CONTROLS_MEDIA_NOTIFICATION_DEVICE_SELECTOR_VIEW_DELEGATE_H_ -#define CHROME_BROWSER_UI_VIEWS_GLOBAL_MEDIA_CONTROLS_MEDIA_NOTIFICATION_DEVICE_SELECTOR_VIEW_DELEGATE_H_ - -#include "base/callback_list.h" -#include "chrome/browser/ui/global_media_controls/media_notification_device_provider.h" - -class MediaNotificationDeviceSelectorViewDelegate { - public: - virtual void OnAudioSinkChosen(const std::string& sink_id) = 0; - virtual void OnDeviceSelectorViewSizeChanged() = 0; - virtual base::CallbackListSubscription - RegisterAudioOutputDeviceDescriptionsCallback( - MediaNotificationDeviceProvider::GetOutputDevicesCallbackList:: - CallbackType callback) = 0; - virtual base::CallbackListSubscription - RegisterIsAudioOutputDeviceSwitchingSupportedCallback( - base::RepeatingCallback<void(bool)> callback) = 0; -}; - -#endif // CHROME_BROWSER_UI_VIEWS_GLOBAL_MEDIA_CONTROLS_MEDIA_NOTIFICATION_DEVICE_SELECTOR_VIEW_DELEGATE_H_
diff --git a/chrome/browser/ui/views/global_media_controls/media_notification_footer_view.h b/chrome/browser/ui/views/global_media_controls/media_notification_footer_view.h deleted file mode 100644 index 8070ae1..0000000 --- a/chrome/browser/ui/views/global_media_controls/media_notification_footer_view.h +++ /dev/null
@@ -1,58 +0,0 @@ -// Copyright 2021 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_UI_VIEWS_GLOBAL_MEDIA_CONTROLS_MEDIA_NOTIFICATION_FOOTER_VIEW_H_ -#define CHROME_BROWSER_UI_VIEWS_GLOBAL_MEDIA_CONTROLS_MEDIA_NOTIFICATION_FOOTER_VIEW_H_ - -#include "chrome/browser/ui/views/global_media_controls/media_notification_device_selector_observer.h" -#include "ui/gfx/color_palette.h" -#include "ui/views/controls/button/button.h" -#include "ui/views/view.h" - -namespace { -class DeviceEntryButton; -} // anonymous namespace - -// A footer view attached to media_notification_view_impl containing -// available cast devices and volume controls. -class MediaNotificationFooterView - : public views::View, - public MediaNotificationDeviceSelectorObserver { - public: - class Delegate { - public: - virtual ~Delegate() = default; - - virtual void OnDeviceSelected(int tag) = 0; - virtual void OnDropdownButtonClicked() = 0; - virtual bool IsDeviceSelectorExpanded() = 0; - }; - - MediaNotificationFooterView( - bool is_cast_session, - views::Button::PressedCallback stop_casting_callback); - ~MediaNotificationFooterView() override = default; - - void OnColorChanged(SkColor foreground); - void SetDelegate(Delegate* delegate); - - // MediaNotificationDeviceselectorobserver - void OnMediaNotificationDeviceSelectorUpdated( - const std::map<int, DeviceEntryUI*>& device_entries_map) override; - - void Layout() override; - - private: - void UpdateButtonsColor(); - void OnDeviceSelected(int tag); - void OnOverflowButtonClicked(); - - SkColor foreground_color_ = gfx::kPlaceholderColor; - - DeviceEntryButton* overflow_button_ = nullptr; - - Delegate* delegate_ = nullptr; -}; - -#endif // CHROME_BROWSER_UI_VIEWS_GLOBAL_MEDIA_CONTROLS_MEDIA_NOTIFICATION_FOOTER_VIEW_H_
diff --git a/chrome/browser/ui/views/global_media_controls/media_notification_list_view.cc b/chrome/browser/ui/views/global_media_controls/media_notification_list_view.cc deleted file mode 100644 index 86cd1ad9..0000000 --- a/chrome/browser/ui/views/global_media_controls/media_notification_list_view.cc +++ /dev/null
@@ -1,116 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/ui/views/global_media_controls/media_notification_list_view.h" - -#include "base/containers/contains.h" -#include "chrome/browser/ui/views/global_media_controls/media_notification_container_impl_view.h" -#include "ui/base/metadata/metadata_impl_macros.h" -#include "ui/color/color_id.h" -#include "ui/color/color_provider.h" -#include "ui/views/border.h" -#include "ui/views/controls/scrollbar/overlay_scroll_bar.h" -#include "ui/views/layout/box_layout.h" - -namespace { - -constexpr int kMediaListMaxHeight = 478; - -// Thickness of separator border. -constexpr int kMediaListSeparatorThickness = 2; - -std::unique_ptr<views::Border> CreateMediaListSeparatorBorder(SkColor color, - int thickness) { - return views::CreateSolidSidedBorder(/*top=*/thickness, - /*left=*/0, - /*bottom=*/0, - /*right=*/0, color); -} - -} // anonymous namespace - -MediaNotificationListView::SeparatorStyle::SeparatorStyle( - SkColor separator_color, - int separator_thickness) - : separator_color(separator_color), - separator_thickness(separator_thickness) {} - -MediaNotificationListView::MediaNotificationListView() - : MediaNotificationListView(absl::nullopt) {} - -MediaNotificationListView::MediaNotificationListView( - const absl::optional<SeparatorStyle>& separator_style) - : separator_style_(separator_style) { - SetBackgroundColor(absl::nullopt); - SetContents(std::make_unique<views::View>()); - contents()->SetLayoutManager(std::make_unique<views::BoxLayout>( - views::BoxLayout::Orientation::kVertical)); - ClipHeightTo(0, kMediaListMaxHeight); - - SetVerticalScrollBar( - std::make_unique<views::OverlayScrollBar>(/*horizontal=*/false)); - SetHorizontalScrollBar( - std::make_unique<views::OverlayScrollBar>(/*horizontal=*/true)); -} - -MediaNotificationListView::~MediaNotificationListView() = default; - -void MediaNotificationListView::ShowNotification( - const std::string& id, - std::unique_ptr<MediaNotificationContainerImplView> notification) { - DCHECK(!base::Contains(notifications_, id)); - DCHECK_NE(nullptr, notification.get()); - - // If this isn't the first notification, then create a top-sided separator - // border. - if (!notifications_.empty()) { - if (separator_style_.has_value()) { - notification->SetBorder(CreateMediaListSeparatorBorder( - separator_style_->separator_color, - separator_style_->separator_thickness)); - } else { - notification->SetBorder(CreateMediaListSeparatorBorder( - GetColorProvider()->GetColor(ui::kColorMenuSeparator), - kMediaListSeparatorThickness)); - } - } - - notifications_[id] = contents()->AddChildView(std::move(notification)); - - contents()->InvalidateLayout(); - PreferredSizeChanged(); -} - -void MediaNotificationListView::HideNotification(const std::string& id) { - RemoveNotification(id); -} - -std::unique_ptr<MediaNotificationContainerImplView> -MediaNotificationListView::RemoveNotification(const std::string& id) { - if (!base::Contains(notifications_, id)) - return nullptr; - - // If we're removing the topmost notification and there are others, then we - // need to remove the top-sided separator border from the new topmost - // notification. - if (contents()->children().size() > 1 && - contents()->children().at(0) == notifications_[id]) { - contents()->children().at(1)->SetBorder(nullptr); - } - - // Remove the notification. Note that since |RemoveChildView()| does not - // delete the notification, we now have ownership. - contents()->RemoveChildView(notifications_[id]); - std::unique_ptr<MediaNotificationContainerImplView> notification( - notifications_[id]); - notifications_.erase(id); - - contents()->InvalidateLayout(); - PreferredSizeChanged(); - - return notification; -} - -BEGIN_METADATA(MediaNotificationListView, views::ScrollView) -END_METADATA
diff --git a/chrome/browser/ui/views/global_media_controls/media_notification_list_view.h b/chrome/browser/ui/views/global_media_controls/media_notification_list_view.h deleted file mode 100644 index ed08c91..0000000 --- a/chrome/browser/ui/views/global_media_controls/media_notification_list_view.h +++ /dev/null
@@ -1,62 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_UI_VIEWS_GLOBAL_MEDIA_CONTROLS_MEDIA_NOTIFICATION_LIST_VIEW_H_ -#define CHROME_BROWSER_UI_VIEWS_GLOBAL_MEDIA_CONTROLS_MEDIA_NOTIFICATION_LIST_VIEW_H_ - -#include <map> -#include <memory> - -#include "third_party/abseil-cpp/absl/types/optional.h" -#include "ui/base/metadata/metadata_header_macros.h" -#include "ui/views/controls/scroll_view.h" - -class MediaNotificationContainerImplView; - -// MediaNotificationListView is a container that holds a list of active media -// sessions. -class MediaNotificationListView : public views::ScrollView { - public: - METADATA_HEADER(MediaNotificationListView); - struct SeparatorStyle { - SeparatorStyle(SkColor separator_color, int separator_thickness); - - const SkColor separator_color; - const int separator_thickness; - }; - - explicit MediaNotificationListView( - const absl::optional<SeparatorStyle>& separator_style); - MediaNotificationListView(); - MediaNotificationListView(const MediaNotificationListView&) = delete; - MediaNotificationListView& operator=(const MediaNotificationListView&) = - delete; - ~MediaNotificationListView() override; - - // Adds the given notification into the list. - void ShowNotification( - const std::string& id, - std::unique_ptr<MediaNotificationContainerImplView> notification); - - // Removes the given notification from the list. - void HideNotification(const std::string& id); - - bool empty() { return notifications_.empty(); } - - const std::map<const std::string, MediaNotificationContainerImplView*>& - notifications_for_testing() const { - return notifications_; - } - - private: - std::unique_ptr<MediaNotificationContainerImplView> RemoveNotification( - const std::string& id); - - std::map<const std::string, MediaNotificationContainerImplView*> - notifications_; - - absl::optional<SeparatorStyle> separator_style_; -}; - -#endif // CHROME_BROWSER_UI_VIEWS_GLOBAL_MEDIA_CONTROLS_MEDIA_NOTIFICATION_LIST_VIEW_H_
diff --git a/chrome/browser/ui/views/global_media_controls/media_notification_list_view_unittest.cc b/chrome/browser/ui/views/global_media_controls/media_notification_list_view_unittest.cc deleted file mode 100644 index 8d4a678..0000000 --- a/chrome/browser/ui/views/global_media_controls/media_notification_list_view_unittest.cc +++ /dev/null
@@ -1,142 +0,0 @@ -// Copyright 2019 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/ui/views/global_media_controls/media_notification_list_view.h" - -#include <memory> -#include <string> - -#include "chrome/browser/ui/global_media_controls/test_helper.h" -#include "chrome/browser/ui/views/global_media_controls/media_notification_container_impl_view.h" -#include "chrome/test/views/chrome_views_test_base.h" - -using testing::NiceMock; - -namespace { - -// Test IDs for notifications. -const char kTestNotificationId1[] = "testid1"; -const char kTestNotificationId2[] = "testid2"; -const char kTestNotificationId3[] = "testid3"; - -} // anonymous namespace - -class MediaNotificationListViewTest : public ChromeViewsTestBase { - public: - MediaNotificationListViewTest() = default; - MediaNotificationListViewTest(const MediaNotificationListViewTest&) = delete; - MediaNotificationListViewTest& operator=( - const MediaNotificationListViewTest&) = delete; - ~MediaNotificationListViewTest() override = default; - - // ViewsTestBase: - void SetUp() override { - ViewsTestBase::SetUp(); - - widget_ = CreateTestWidget(); - - list_view_ = - widget_->SetContentsView(std::make_unique<MediaNotificationListView>()); - - item_ = std::make_unique<NiceMock<MockMediaNotificationItem>>(); - widget_->Show(); - } - - void TearDown() override { - widget_.reset(); - ViewsTestBase::TearDown(); - } - - void ShowNotification(const std::string& id) { - list_view_->ShowNotification( - id, std::make_unique<MediaNotificationContainerImplView>( - id, item_->GetWeakPtr(), nullptr, - GlobalMediaControlsEntryPoint::kToolbarIcon, nullptr)); - } - - void HideNotification(const std::string& id) { - list_view_->HideNotification(id); - } - - MediaNotificationListView* list_view() { return list_view_; } - - private: - std::unique_ptr<views::Widget> widget_; - MediaNotificationListView* list_view_ = nullptr; - std::unique_ptr<MockMediaNotificationItem> item_; -}; - -TEST_F(MediaNotificationListViewTest, NoSeparatorForOneNotification) { - // Show a single notification. - ShowNotification(kTestNotificationId1); - - // There should be just one notification. - EXPECT_EQ(1u, list_view()->notifications_for_testing().size()); - - // Since there's only one, there should be no separator line. - EXPECT_EQ(nullptr, list_view() - ->notifications_for_testing() - .at(kTestNotificationId1) - ->GetBorder()); -} - -TEST_F(MediaNotificationListViewTest, SeparatorBetweenNotifications) { - // Show two notifications. - ShowNotification(kTestNotificationId1); - ShowNotification(kTestNotificationId2); - - // There should be two notifications. - EXPECT_EQ(2u, list_view()->notifications_for_testing().size()); - - // There should be a separator between them. Since the separators are - // top-sided, the bottom notification should have one. - EXPECT_EQ(nullptr, list_view() - ->notifications_for_testing() - .at(kTestNotificationId1) - ->GetBorder()); - EXPECT_NE(nullptr, list_view() - ->notifications_for_testing() - .at(kTestNotificationId2) - ->GetBorder()); -} - -TEST_F(MediaNotificationListViewTest, SeparatorRemovedWhenNotificationRemoved) { - // Show three notifications. - ShowNotification(kTestNotificationId1); - ShowNotification(kTestNotificationId2); - ShowNotification(kTestNotificationId3); - - // There should be three notifications. - EXPECT_EQ(3u, list_view()->notifications_for_testing().size()); - - // There should be separators. - EXPECT_EQ(nullptr, list_view() - ->notifications_for_testing() - .at(kTestNotificationId1) - ->GetBorder()); - EXPECT_NE(nullptr, list_view() - ->notifications_for_testing() - .at(kTestNotificationId2) - ->GetBorder()); - EXPECT_NE(nullptr, list_view() - ->notifications_for_testing() - .at(kTestNotificationId3) - ->GetBorder()); - - // Remove the topmost notification. - HideNotification(kTestNotificationId1); - - // There should be two notifications. - EXPECT_EQ(2u, list_view()->notifications_for_testing().size()); - - // The new top notification should have lost its top separator. - EXPECT_EQ(nullptr, list_view() - ->notifications_for_testing() - .at(kTestNotificationId2) - ->GetBorder()); - EXPECT_NE(nullptr, list_view() - ->notifications_for_testing() - .at(kTestNotificationId3) - ->GetBorder()); -}
diff --git a/chrome/browser/ui/views/global_media_controls/media_toolbar_button_view.cc b/chrome/browser/ui/views/global_media_controls/media_toolbar_button_view.cc index eb43f0f..bd46690 100644 --- a/chrome/browser/ui/views/global_media_controls/media_toolbar_button_view.cc +++ b/chrome/browser/ui/views/global_media_controls/media_toolbar_button_view.cc
@@ -145,8 +145,9 @@ if (MediaDialogView::IsShowing()) { MediaDialogView::HideDialog(); } else { - MediaDialogView::ShowDialog(this, service_, browser_->profile(), - GlobalMediaControlsEntryPoint::kToolbarIcon); + MediaDialogView::ShowDialog( + this, service_, browser_->profile(), + global_media_controls::GlobalMediaControlsEntryPoint::kToolbarIcon); ClosePromoBubble(); for (auto& observer : observers_)
diff --git a/chrome/browser/ui/views/media_router/media_router_dialog_controller_views.cc b/chrome/browser/ui/views/media_router/media_router_dialog_controller_views.cc index 7b02719..844c460 100644 --- a/chrome/browser/ui/views/media_router/media_router_dialog_controller_views.cc +++ b/chrome/browser/ui/views/media_router/media_router_dialog_controller_views.cc
@@ -81,7 +81,7 @@ scoped_widget_observations_.AddObservation( MediaDialogView::ShowDialogForPresentationRequest( media_button, service, profile, initiator(), - GlobalMediaControlsEntryPoint::kPresentation)); + global_media_controls::GlobalMediaControlsEntryPoint::kPresentation)); return true; }
diff --git a/chrome/browser/ui/views/page_info/page_info_main_view.cc b/chrome/browser/ui/views/page_info/page_info_main_view.cc index d96fb23a..77840fd 100644 --- a/chrome/browser/ui/views/page_info/page_info_main_view.cc +++ b/chrome/browser/ui/views/page_info/page_info_main_view.cc
@@ -88,11 +88,11 @@ ->SetOrientation(views::LayoutOrientation::kVertical); if (base::FeatureList::IsEnabled(page_info::kPageInfoAboutThisSite)) { - std::u16string description = ui_delegate_->GetAboutThisSiteDescription(); - if (!description.empty()) { + auto info = ui_delegate_->GetAboutThisSiteInfo(); + if (info) { layout->StartRow(views::GridLayout::kFixedSize, kColumnId); about_this_site_section_ = - layout->AddView(CreateAboutThisSiteSection(description)); + layout->AddView(CreateAboutThisSiteSection(info)); } } @@ -501,7 +501,7 @@ } std::unique_ptr<views::View> PageInfoMainView::CreateAboutThisSiteSection( - std::u16string description) { + const absl::optional<page_info::proto::SiteInfo> info) { auto about_this_site_section = std::make_unique<views::View>(); about_this_site_section ->SetLayoutManager(std::make_unique<views::FlexLayout>()) @@ -509,6 +509,8 @@ about_this_site_section->AddChildView(PageInfoViewFactory::CreateSeparator()); // TODO(crbug.com/1250653): Update with the actual strings. + // TODO(crbug.com/1250653): Update checks for the data being available and + // logic to determine short description showed as subtitle. auto* about_this_site_button = about_this_site_section->AddChildView( std::make_unique<PageInfoHoverButton>( base::BindRepeating( @@ -518,7 +520,7 @@ this), PageInfoViewFactory::GetAboutThisSiteIcon(), 0, std::u16string(), PageInfoViewFactory::VIEW_ID_PAGE_INFO_ABOUT_THIS_SITE_BUTTON, - std::u16string(), description, + std::u16string(), base::ASCIIToUTF16(info->entity_description()), PageInfoViewFactory::GetOpenSubpageIcon())); about_this_site_button->SetTitleText(u"About this site");
diff --git a/chrome/browser/ui/views/page_info/page_info_main_view.h b/chrome/browser/ui/views/page_info/page_info_main_view.h index a329af5..b13d1e4 100644 --- a/chrome/browser/ui/views/page_info/page_info_main_view.h +++ b/chrome/browser/ui/views/page_info/page_info_main_view.h
@@ -12,6 +12,7 @@ #include "chrome/browser/ui/views/page_info/chosen_object_view_observer.h" #include "chrome/browser/ui/views/page_info/permission_selector_row_observer.h" #include "components/page_info/page_info_ui.h" +#include "components/page_info/proto/about_this_site_metadata.pb.h" #include "device/vr/buildflags/buildflags.h" #include "ui/views/view.h" @@ -95,7 +96,7 @@ // Creates 'About this site' section which contains a button that opens a // subpage and two separators. std::unique_ptr<views::View> CreateAboutThisSiteSection( - std::u16string description) WARN_UNUSED_RESULT; + const absl::optional<page_info::proto::SiteInfo> info) WARN_UNUSED_RESULT; PageInfo* presenter_;
diff --git a/chrome/browser/ui/views/sad_tab_view_interactive_uitest.cc b/chrome/browser/ui/views/sad_tab_view_interactive_uitest.cc index 09025c1..bb5b4f6 100644 --- a/chrome/browser/ui/views/sad_tab_view_interactive_uitest.cc +++ b/chrome/browser/ui/views/sad_tab_view_interactive_uitest.cc
@@ -7,8 +7,10 @@ #include "build/build_config.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_commands.h" +#include "chrome/browser/ui/frame/window_frame_util.h" #include "chrome/browser/ui/sad_tab.h" #include "chrome/browser/ui/sad_tab_helper.h" +#include "chrome/browser/ui/views/frame/browser_non_client_frame_view.h" #include "chrome/browser/ui/views/frame/browser_view.h" #include "chrome/browser/ui/views/toolbar/toolbar_view.h" #include "chrome/test/base/in_process_browser_test.h" @@ -155,10 +157,19 @@ ASSERT_TRUE(IsFocusedViewInsideSadTab()); ASSERT_FALSE(IsFocusedViewInsideBrowserToolbar()); - // Pressing the Tab key should cycle focus back to the toolbar. + // Pressing the Tab key should cycle focus back to the toolbar or the browser + // frame if the tab search caption button is enabled. PressTab(); - ASSERT_FALSE(IsFocusedViewInsideSadTab()); - ASSERT_TRUE(IsFocusedViewInsideBrowserToolbar()); + if (WindowFrameUtil::IsWin10TabSearchCaptionButtonEnabled(browser())) { + const auto* frame_view = BrowserView::GetBrowserViewForBrowser(browser()) + ->frame() + ->GetFrameView(); + ASSERT_FALSE(IsFocusedViewInsideSadTab()); + ASSERT_TRUE(frame_view->Contains(GetFocusedView())); + } else { + ASSERT_FALSE(IsFocusedViewInsideSadTab()); + ASSERT_TRUE(IsFocusedViewInsideBrowserToolbar()); + } // Keep pressing the Tab key and make sure we make it back to the sad tab. while (!IsFocusedViewInsideSadTab())
diff --git a/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc b/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc index 3fc2bde..01372c2 100644 --- a/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc +++ b/chrome/browser/ui/views/tabs/tab_drag_controller_interactive_uitest.cc
@@ -2535,8 +2535,10 @@ AddTabsAndResetBrowser(browser(), 1); + // We must ensure that we set the bounds of the browser window such that it is + // wide enough to allow the tab strip to expand to accommodate this tab. browser()->window()->SetBounds( - gfx::Rect(0, 0, TabStyle::GetStandardWidth() * 4, 400)); + gfx::Rect(0, 0, TabStyle::GetStandardWidth() * 5, 400)); const int tab_strip_width = tab_strip->width(); const gfx::Point tab_1_center =
diff --git a/chrome/browser/ui/views/tabs/tab_search_button_browsertest.cc b/chrome/browser/ui/views/tabs/tab_search_button_browsertest.cc index 0d506da..76af028 100644 --- a/chrome/browser/ui/views/tabs/tab_search_button_browsertest.cc +++ b/chrome/browser/ui/views/tabs/tab_search_button_browsertest.cc
@@ -6,12 +6,14 @@ #include <vector> +#include "base/feature_list.h" #include "base/run_loop.h" #include "base/test/scoped_feature_list.h" #include "build/build_config.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_tabstrip.h" #include "chrome/browser/ui/test/test_browser_dialog.h" +#include "chrome/browser/ui/ui_features.h" #include "chrome/browser/ui/views/bubble/webui_bubble_dialog_view.h" #include "chrome/browser/ui/views/bubble/webui_bubble_manager.h" #include "chrome/browser/ui/views/frame/browser_view.h" @@ -31,6 +33,15 @@ class TabSearchButtonBrowserTest : public InProcessBrowserTest { public: +#if defined(OS_WIN) + // InProcessBrowserTest: + void SetUp() override { + scoped_feature_list_.InitAndDisableFeature( + features::kWin10TabSearchCaptionButton); + InProcessBrowserTest::SetUp(); + } +#endif // defined(OS_WIN); + BrowserView* browser_view() { return BrowserView::GetBrowserViewForBrowser(browser()); } @@ -55,6 +66,11 @@ run_loop.Run(); ASSERT_EQ(nullptr, bubble_manager()->GetBubbleWidget()); } + +#if defined(OS_WIN) + private: + base::test::ScopedFeatureList scoped_feature_list_; +#endif // defined(OS_WIN); }; IN_PROC_BROWSER_TEST_F(TabSearchButtonBrowserTest, ButtonClickCreatesBubble) { @@ -71,6 +87,13 @@ class TabSearchButtonBrowserUITest : public DialogBrowserTest { public: // DialogBrowserTest: +#if defined(OS_WIN) + void SetUp() override { + scoped_feature_list_.InitAndDisableFeature( + features::kWin10TabSearchCaptionButton); + DialogBrowserTest::SetUp(); + } +#endif // defined(OS_WIN); void ShowUi(const std::string& name) override { AppendTab(chrome::kChromeUISettingsURL); AppendTab(chrome::kChromeUIHistoryURL); @@ -84,6 +107,11 @@ void AppendTab(std::string url) { chrome::AddTabAt(browser(), GURL(url), -1, true); } + +#if defined(OS_WIN) + private: + base::test::ScopedFeatureList scoped_feature_list_; +#endif // defined(OS_WIN); }; // Invokes a tab search bubble.
diff --git a/chrome/browser/ui/views/tabs/tab_strip.cc b/chrome/browser/ui/views/tabs/tab_strip.cc index 249acbf..74a6244 100644 --- a/chrome/browser/ui/views/tabs/tab_strip.cc +++ b/chrome/browser/ui/views/tabs/tab_strip.cc
@@ -1355,6 +1355,8 @@ base::TimeTicks::Now() - new_tab_button_pressed_start_time_.value()); new_tab_button_pressed_start_time_.reset(); } + + LogTabWidthsForTabScrolling(); } void TabStrip::MoveTab(int from_model_index, @@ -3367,6 +3369,19 @@ StartResizeLayoutAnimation(); } +void TabStrip::LogTabWidthsForTabScrolling() { + int active_tab_width = GetActiveTabWidth(); + int inactive_tab_width = GetInactiveTabWidth(); + + if (active_tab_width > 1) { + UMA_HISTOGRAM_EXACT_LINEAR("Tabs.ActiveTabWidth", active_tab_width, 257); + } + if (inactive_tab_width > 1) { + UMA_HISTOGRAM_EXACT_LINEAR("Tabs.InactiveTabWidth", inactive_tab_width, + 257); + } +} + void TabStrip::ResizeLayoutTabsFromTouch() { // Don't resize if the user is interacting with the tabstrip. if (!drag_context_->IsDragSessionActive())
diff --git a/chrome/browser/ui/views/tabs/tab_strip.h b/chrome/browser/ui/views/tabs/tab_strip.h index 8319fac..128c0dff 100644 --- a/chrome/browser/ui/views/tabs/tab_strip.h +++ b/chrome/browser/ui/views/tabs/tab_strip.h
@@ -658,6 +658,10 @@ void AnnounceTabAddedToGroup(tab_groups::TabGroupId group_id); void AnnounceTabRemovedFromGroup(tab_groups::TabGroupId group_id); + // For metrics on the best size for tab scrolling, log if the different + // sizes would trigger tab scrolling + void LogTabWidthsForTabScrolling(); + // -- Member Variables ------------------------------------------------------ base::ObserverList<TabStripObserver>::Unchecked observers_;
diff --git a/chrome/browser/ui/views/user_education/tip_marquee_view.cc b/chrome/browser/ui/views/user_education/tip_marquee_view.cc index 788d87d..9a80ebd 100644 --- a/chrome/browser/ui/views/user_education/tip_marquee_view.cc +++ b/chrome/browser/ui/views/user_education/tip_marquee_view.cc
@@ -300,7 +300,7 @@ } std::u16string TipMarqueeView::GetTooltipText(const gfx::Point& p) const { - if (!IsPointInIcon(p)) + if (!GetVisible() || !IsPointInIcon(p)) return View::GetTooltipText(p); // TODO(pkasting): Localize
diff --git a/chrome/browser/ui/views/user_education/tutorial_bubble_factory_views.cc b/chrome/browser/ui/views/user_education/tutorial_bubble_factory_views.cc index 5359f5a..59147d6 100644 --- a/chrome/browser/ui/views/user_education/tutorial_bubble_factory_views.cc +++ b/chrome/browser/ui/views/user_education/tutorial_bubble_factory_views.cc
@@ -15,6 +15,17 @@ #include "ui/base/interaction/element_tracker.h" #include "ui/views/interaction/element_tracker_views.h" +namespace { + +// The amount of time the tutorial should stay onscreen depending on if the +// bubble is interacted with it. similar to FeaturePromoBubbleView's timeouts +constexpr base::TimeDelta kDelayNoInteraction = + base::TimeDelta::FromSeconds(10); +constexpr base::TimeDelta kDelayWithInteraction = + base::TimeDelta::FromSeconds(3); +constexpr base::TimeDelta kDelayZero = base::TimeDelta::FromSeconds(0); +} // namespace + TutorialBubbleViews::TutorialBubbleViews(absl::optional<base::Token> bubble_id) : bubble_id_(bubble_id) {} @@ -34,7 +45,8 @@ absl::optional<std::u16string> title_text, absl::optional<std::u16string> body_text, TutorialDescription::Step::Arrow arrow, - absl::optional<std::pair<int, int>> progress) { + absl::optional<std::pair<int, int>> progress, + bool is_last_step) { if (!element->IsA<views::TrackedElementViews>()) return nullptr; @@ -81,6 +93,11 @@ break; } + params.timeout_no_interaction = + is_last_step ? kDelayNoInteraction : kDelayZero; + params.timeout_after_interaction = + is_last_step ? kDelayWithInteraction : kDelayZero; + return std::make_unique<TutorialBubbleViews>( owner_impl->ShowBubble(std::move(params), base::BindOnce([] {}))); }
diff --git a/chrome/browser/ui/views/user_education/tutorial_bubble_factory_views.h b/chrome/browser/ui/views/user_education/tutorial_bubble_factory_views.h index 26bc785..a929281 100644 --- a/chrome/browser/ui/views/user_education/tutorial_bubble_factory_views.h +++ b/chrome/browser/ui/views/user_education/tutorial_bubble_factory_views.h
@@ -29,7 +29,8 @@ absl::optional<std::u16string> title_text, absl::optional<std::u16string> body_text, TutorialDescription::Step::Arrow arrow, - absl::optional<std::pair<int, int>> progress) override; + absl::optional<std::pair<int, int>> progress, + bool is_last_step) override; bool CanBuildBubbleForTrackedElement(ui::TrackedElement* element) override; };
diff --git a/chrome/browser/ui/web_applications/web_app_browsertest.cc b/chrome/browser/ui/web_applications/web_app_browsertest.cc index cd680b58..38d965a 100644 --- a/chrome/browser/ui/web_applications/web_app_browsertest.cc +++ b/chrome/browser/ui/web_applications/web_app_browsertest.cc
@@ -152,12 +152,15 @@ } AppId InstallPwaForCurrentUrl() { + // Depending on the installability criteria, different dialogs can be used. + chrome::SetAutoAcceptWebAppDialogForTesting(true, true); chrome::SetAutoAcceptPWAInstallConfirmationForTesting(true); WebAppTestInstallObserver observer(profile()); observer.BeginListening(); CHECK(chrome::ExecuteCommand(browser(), IDC_INSTALL_PWA)); AppId app_id = observer.Wait(); chrome::SetAutoAcceptPWAInstallConfirmationForTesting(false); + chrome::SetAutoAcceptWebAppDialogForTesting(false, false); return app_id; }
diff --git a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc index 7951094..b814191 100644 --- a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc +++ b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
@@ -127,6 +127,7 @@ #include "chrome/browser/ui/webui/devtools_ui.h" #include "chrome/browser/ui/webui/download_shelf/download_shelf_ui.h" #include "chrome/browser/ui/webui/downloads/downloads_ui.h" +#include "chrome/browser/ui/webui/enterprise_casting/enterprise_casting_ui.h" #include "chrome/browser/ui/webui/feedback/feedback_ui.h" #include "chrome/browser/ui/webui/history/history_ui.h" #include "chrome/browser/ui/webui/identity_internals_ui.h" @@ -212,7 +213,6 @@ #include "chrome/browser/ui/webui/chromeos/cryptohome_ui.h" #include "chrome/browser/ui/webui/chromeos/drive_internals_ui.h" #include "chrome/browser/ui/webui/chromeos/emoji/emoji_ui.h" -#include "chrome/browser/ui/webui/chromeos/enterprise_casting/enterprise_casting_ui.h" #include "chrome/browser/ui/webui/chromeos/in_session_password_change/lock_screen_network_ui.h" #include "chrome/browser/ui/webui/chromeos/in_session_password_change/lock_screen_start_reauth_ui.h" #include "chrome/browser/ui/webui/chromeos/in_session_password_change/password_change_ui.h" @@ -744,6 +744,10 @@ // Inline login UI is available on all platforms except Android. if (url.host_piece() == chrome::kChromeUIChromeSigninHost) return &NewWebUI<InlineLoginUI>; + if (base::FeatureList::IsEnabled(features::kEnterpriseCastingUI)) { + if (url.host_piece() == chrome::kChromeUIEnterpriseCastingHost) + return &NewWebUI<EnterpriseCastingUI>; + } #endif // !defined(OS_ANDROID) #if defined(OS_WIN) if (url.host_piece() == chrome::kChromeUIConflictsHost) @@ -829,9 +833,6 @@ return &NewWebUI<chromeos::DriveInternalsUI>; if (url.host_piece() == chrome::kChromeUILauncherInternalsHost) return &NewWebUI<chromeos::LauncherInternalsUI>; - if (base::FeatureList::IsEnabled(features::kEnterpriseCastingUI) && - url.host_piece() == chrome::kChromeUIEnterpriseCastingHost) - return &NewWebUI<chromeos::EnterpriseCastingUI>; if (url.host_piece() == ash::kChromeUIHelpAppHost) return &NewComponentUI<ash::HelpAppUI, ash::ChromeHelpAppUIDelegate>; if (url.host_piece() == chrome::kChromeUIMobileSetupHost)
diff --git a/chrome/browser/ui/webui/chromeos/parent_access/parent_access_ui_handler_impl.cc b/chrome/browser/ui/webui/chromeos/parent_access/parent_access_ui_handler_impl.cc index 6ef9a9b..3204918 100644 --- a/chrome/browser/ui/webui/chromeos/parent_access/parent_access_ui_handler_impl.cc +++ b/chrome/browser/ui/webui/chromeos/parent_access/parent_access_ui_handler_impl.cc
@@ -31,7 +31,8 @@ void ParentAccessUIHandlerImpl::GetOAuthToken(GetOAuthTokenCallback callback) { signin::ScopeSet scopes; - scopes.insert(GaiaConstants::kKidsSupervisionSetupChildOAuth2Scope); + scopes.insert(GaiaConstants::kParentApprovalOAuth2Scope); + scopes.insert(GaiaConstants::kProgrammaticChallengeOAuth2Scope); if (oauth2_access_token_fetcher_) { // Only one GetOAuthToken call can happen at a time.
diff --git a/chrome/browser/ui/webui/connectors_internals/zero_trust_utils.cc b/chrome/browser/ui/webui/connectors_internals/zero_trust_utils.cc index 461b85b..12247c9 100644 --- a/chrome/browser/ui/webui/connectors_internals/zero_trust_utils.cc +++ b/chrome/browser/ui/webui/connectors_internals/zero_trust_utils.cc
@@ -4,13 +4,17 @@ #include "chrome/browser/ui/webui/connectors_internals/zero_trust_utils.h" +#include "base/containers/span.h" #include "base/strings/string_number_conversions.h" +#include "base/strings/string_util.h" namespace enterprise_connectors { namespace utils { namespace { +using google::protobuf::RepeatedPtrField; + void TrySetSignal(base::flat_map<std::string, std::string>& map, const std::string& key, bool has_value, @@ -38,6 +42,20 @@ } } +// Encodes repeated fields into a single string with values separated by commas. +// TODO(seblalancette): Uncomment once both CrOS and Chrome versions of the +// DeviceTrustSignals proto have been updated. +// void TrySetSignal(base::flat_map<std::string, std::string>& map, +// const std::string& key, +// const RepeatedPtrField<std::string>& values) { +// if (values.empty()) { +// return; +// } + +// map[key] = base::JoinString( +// std::vector<base::StringPiece>(values.begin(), values.end()), ", "); +// } + } // namespace base::flat_map<std::string, std::string> SignalsToMap( @@ -64,8 +82,12 @@ signals->device_manufacturer()); TrySetSignal(map, "device_model", signals->has_device_model(), signals->device_model()); - TrySetSignal(map, "imei", signals->has_imei(), signals->imei()); - TrySetSignal(map, "meid", signals->has_meid(), signals->meid()); + + // TODO(seblalancette): Uncomment once both CrOS and Chrome versions of the + // DeviceTrustSignals proto have been updated. + // TrySetSignal(map, "imei", signals->imei()); + // TrySetSignal(map, "meid", signals->meid()); + TrySetSignal(map, "tpm_hash", signals->has_tpm_hash(), signals->tpm_hash()); TrySetSignal(map, "is_disk_encrypted", signals->has_is_disk_encrypted(), signals->is_disk_encrypted());
diff --git a/chrome/browser/ui/webui/chromeos/enterprise_casting/BUILD.gn b/chrome/browser/ui/webui/enterprise_casting/BUILD.gn similarity index 83% rename from chrome/browser/ui/webui/chromeos/enterprise_casting/BUILD.gn rename to chrome/browser/ui/webui/enterprise_casting/BUILD.gn index 1a73667..78d19e8 100644 --- a/chrome/browser/ui/webui/chromeos/enterprise_casting/BUILD.gn +++ b/chrome/browser/ui/webui/enterprise_casting/BUILD.gn
@@ -4,7 +4,7 @@ import("//mojo/public/tools/bindings/mojom.gni") -assert(is_chromeos, "EnterpriseCasting is Chrome OS only.") +assert(!is_android, "EnterpriseCasting is not for android.") mojom("mojo_bindings") { sources = [ "enterprise_casting.mojom" ]
diff --git a/chrome/browser/ui/webui/chromeos/enterprise_casting/OWNERS b/chrome/browser/ui/webui/enterprise_casting/OWNERS similarity index 85% rename from chrome/browser/ui/webui/chromeos/enterprise_casting/OWNERS rename to chrome/browser/ui/webui/enterprise_casting/OWNERS index 57d67b8..1c4f5ce 100644 --- a/chrome/browser/ui/webui/chromeos/enterprise_casting/OWNERS +++ b/chrome/browser/ui/webui/enterprise_casting/OWNERS
@@ -1,5 +1,5 @@ gbj@google.com -bmalcolm@google.com +bmalcolm@chromium.org bzielinski@google.com jacqueli@google.com
diff --git a/chrome/browser/ui/webui/chromeos/enterprise_casting/enterprise_casting.mojom b/chrome/browser/ui/webui/enterprise_casting/enterprise_casting.mojom similarity index 100% rename from chrome/browser/ui/webui/chromeos/enterprise_casting/enterprise_casting.mojom rename to chrome/browser/ui/webui/enterprise_casting/enterprise_casting.mojom
diff --git a/chrome/browser/ui/webui/chromeos/enterprise_casting/enterprise_casting_handler.cc b/chrome/browser/ui/webui/enterprise_casting/enterprise_casting_handler.cc similarity index 83% rename from chrome/browser/ui/webui/chromeos/enterprise_casting/enterprise_casting_handler.cc rename to chrome/browser/ui/webui/enterprise_casting/enterprise_casting_handler.cc index 96d4154..2405343 100644 --- a/chrome/browser/ui/webui/chromeos/enterprise_casting/enterprise_casting_handler.cc +++ b/chrome/browser/ui/webui/enterprise_casting/enterprise_casting_handler.cc
@@ -2,13 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/ui/webui/chromeos/enterprise_casting/enterprise_casting_handler.h" +#include "chrome/browser/ui/webui/enterprise_casting/enterprise_casting_handler.h" #include "base/rand_util.h" #include "base/strings/string_number_conversions.h" -namespace chromeos { - EnterpriseCastingHandler::EnterpriseCastingHandler( mojo::PendingReceiver<enterprise_casting::mojom::PageHandler> page_handler, mojo::PendingRemote<enterprise_casting::mojom::Page> page) @@ -19,5 +17,3 @@ void EnterpriseCastingHandler::UpdatePin() { page_->SetPin(base::NumberToString(base::RandInt(0, 9999))); } - -} // namespace chromeos
diff --git a/chrome/browser/ui/webui/chromeos/enterprise_casting/enterprise_casting_handler.h b/chrome/browser/ui/webui/enterprise_casting/enterprise_casting_handler.h similarity index 68% rename from chrome/browser/ui/webui/chromeos/enterprise_casting/enterprise_casting_handler.h rename to chrome/browser/ui/webui/enterprise_casting/enterprise_casting_handler.h index aba0c316..54c0078f 100644 --- a/chrome/browser/ui/webui/chromeos/enterprise_casting/enterprise_casting_handler.h +++ b/chrome/browser/ui/webui/enterprise_casting/enterprise_casting_handler.h
@@ -2,17 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_UI_WEBUI_CHROMEOS_ENTERPRISE_CASTING_ENTERPRISE_CASTING_HANDLER_H_ -#define CHROME_BROWSER_UI_WEBUI_CHROMEOS_ENTERPRISE_CASTING_ENTERPRISE_CASTING_HANDLER_H_ +#ifndef CHROME_BROWSER_UI_WEBUI_ENTERPRISE_CASTING_ENTERPRISE_CASTING_HANDLER_H_ +#define CHROME_BROWSER_UI_WEBUI_ENTERPRISE_CASTING_ENTERPRISE_CASTING_HANDLER_H_ #include "base/scoped_observation.h" #include "chrome/browser/ui/app_list/search/search_controller.h" -#include "chrome/browser/ui/webui/chromeos/enterprise_casting/enterprise_casting.mojom.h" +#include "chrome/browser/ui/webui/enterprise_casting/enterprise_casting.mojom.h" #include "mojo/public/cpp/bindings/pending_remote.h" #include "mojo/public/cpp/bindings/remote.h" -namespace chromeos { - class EnterpriseCastingHandler : public enterprise_casting::mojom::PageHandler { public: EnterpriseCastingHandler( @@ -29,6 +27,4 @@ mojo::Receiver<enterprise_casting::mojom::PageHandler> receiver_; }; -} // namespace chromeos - -#endif // CHROME_BROWSER_UI_WEBUI_CHROMEOS_ENTERPRISE_CASTING_ENTERPRISE_CASTING_HANDLER_H_ +#endif // CHROME_BROWSER_UI_WEBUI_ENTERPRISE_CASTING_ENTERPRISE_CASTING_HANDLER_H_
diff --git a/chrome/browser/ui/webui/chromeos/enterprise_casting/enterprise_casting_ui.cc b/chrome/browser/ui/webui/enterprise_casting/enterprise_casting_ui.cc similarity index 92% rename from chrome/browser/ui/webui/chromeos/enterprise_casting/enterprise_casting_ui.cc rename to chrome/browser/ui/webui/enterprise_casting/enterprise_casting_ui.cc index bcea12f..97b7996 100644 --- a/chrome/browser/ui/webui/chromeos/enterprise_casting/enterprise_casting_ui.cc +++ b/chrome/browser/ui/webui/enterprise_casting/enterprise_casting_ui.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/ui/webui/chromeos/enterprise_casting/enterprise_casting_ui.h" +#include "chrome/browser/ui/webui/enterprise_casting/enterprise_casting_ui.h" #include "base/containers/span.h" #include "chrome/browser/ui/webui/webui_util.h" @@ -12,8 +12,6 @@ #include "content/public/browser/web_contents.h" #include "content/public/browser/web_ui_data_source.h" -namespace chromeos { - EnterpriseCastingUI::EnterpriseCastingUI(content::WebUI* web_ui) : MojoWebUIController(web_ui) { auto source = base::WrapUnique( @@ -47,5 +45,3 @@ } WEB_UI_CONTROLLER_TYPE_IMPL(EnterpriseCastingUI) - -} // namespace chromeos
diff --git a/chrome/browser/ui/webui/chromeos/enterprise_casting/enterprise_casting_ui.h b/chrome/browser/ui/webui/enterprise_casting/enterprise_casting_ui.h similarity index 73% rename from chrome/browser/ui/webui/chromeos/enterprise_casting/enterprise_casting_ui.h rename to chrome/browser/ui/webui/enterprise_casting/enterprise_casting_ui.h index 3f9abee..dbd81c1 100644 --- a/chrome/browser/ui/webui/chromeos/enterprise_casting/enterprise_casting_ui.h +++ b/chrome/browser/ui/webui/enterprise_casting/enterprise_casting_ui.h
@@ -2,18 +2,16 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_UI_WEBUI_CHROMEOS_ENTERPRISE_CASTING_ENTERPRISE_CASTING_UI_H_ -#define CHROME_BROWSER_UI_WEBUI_CHROMEOS_ENTERPRISE_CASTING_ENTERPRISE_CASTING_UI_H_ +#ifndef CHROME_BROWSER_UI_WEBUI_ENTERPRISE_CASTING_ENTERPRISE_CASTING_UI_H_ +#define CHROME_BROWSER_UI_WEBUI_ENTERPRISE_CASTING_ENTERPRISE_CASTING_UI_H_ -#include "chrome/browser/ui/webui/chromeos/enterprise_casting/enterprise_casting.mojom.h" -#include "chrome/browser/ui/webui/chromeos/enterprise_casting/enterprise_casting_handler.h" +#include "chrome/browser/ui/webui/enterprise_casting/enterprise_casting.mojom.h" +#include "chrome/browser/ui/webui/enterprise_casting/enterprise_casting_handler.h" #include "mojo/public/cpp/bindings/pending_receiver.h" #include "mojo/public/cpp/bindings/pending_remote.h" #include "mojo/public/cpp/bindings/receiver.h" #include "ui/webui/mojo_web_ui_controller.h" -namespace chromeos { - // The WebUI controller for chrome://enterprise-casting. class EnterpriseCastingUI : public ui::MojoWebUIController, @@ -43,6 +41,4 @@ WEB_UI_CONTROLLER_TYPE_DECL(); }; -} // namespace chromeos - -#endif // CHROME_BROWSER_UI_WEBUI_CHROMEOS_ENTERPRISE_CASTING_ENTERPRISE_CASTING_UI_H_ +#endif // CHROME_BROWSER_UI_WEBUI_ENTERPRISE_CASTING_ENTERPRISE_CASTING_UI_H_
diff --git a/chrome/browser/ui/webui/tab_strip/tab_strip_page_handler.cc b/chrome/browser/ui/webui/tab_strip/tab_strip_page_handler.cc index 274fccd8..109c68f 100644 --- a/chrome/browser/ui/webui/tab_strip/tab_strip_page_handler.cc +++ b/chrome/browser/ui/webui/tab_strip/tab_strip_page_handler.cc
@@ -56,6 +56,11 @@ #include "ui/gfx/range/range.h" #include "url/gurl.h" +// This should be after all other #includes. +#if defined(_WINDOWS_) // Detect whether windows.h was included. +#include "base/win/windows_h_disallowed.h" +#endif // defined(_WINDOWS_) + namespace { // Delay in milliseconds of when the dragging UI should be shown for touch drag.
diff --git a/chrome/browser/web_applications/manifest_update_manager_browsertest.cc b/chrome/browser/web_applications/manifest_update_manager_browsertest.cc index cceed3a..1a9fb3d 100644 --- a/chrome/browser/web_applications/manifest_update_manager_browsertest.cc +++ b/chrome/browser/web_applications/manifest_update_manager_browsertest.cc
@@ -620,33 +620,6 @@ features::kPwaUpdateDialogForNameAndIcon}; }; -IN_PROC_BROWSER_TEST_F(ManifestUpdateManagerAppIdentityBrowserTest, - VerifyAppIdentityUpdatesWithDlgForUserInstalledApps) { - chrome::SetAutoAcceptAppIdentityUpdateForTesting(true); - - constexpr char kManifestTemplate[] = R"( - { - "name": "$1", - "start_url": ".", - "scope": "/", - "display": "standalone", - "icons": $2 - } - )"; - OverrideManifest(kManifestTemplate, {"Test app name", kInstallableIconList}); - AppId app_id = InstallWebApp(); - - OverrideManifest(kManifestTemplate, - {"Different app name", kAnotherInstallableIconList}); - EXPECT_EQ(GetResultAfterPageLoad(GetAppURL()), - ManifestUpdateResult::kAppUpdated); - histogram_tester_.ExpectBucketCount(kUpdateHistogramName, - ManifestUpdateResult::kAppUpdated, 1); - EXPECT_EQ(GetProvider().registrar().GetAppShortName(app_id), - "Different app name"); - CheckShortcutInfoUpdated(app_id, kAnotherInstallableIconTopLeftColor); -} - IN_PROC_BROWSER_TEST_F(ManifestUpdateManagerBrowserTest, CheckIgnoresStartUrlChange) { constexpr char kManifestTemplate[] = R"( @@ -2641,7 +2614,7 @@ features::kWebAppManifestIconUpdating}; }; -IN_PROC_BROWSER_TEST_F(ManifestUpdateManagerIconUpdatingBrowserTest, +IN_PROC_BROWSER_TEST_P(ManifestUpdateManagerBrowserTest_UpdateDialog, CheckFindsIconContentChange) { constexpr char kManifest[] = R"( { @@ -2651,39 +2624,52 @@ "display": "standalone", "icons": [ { - "src": "/web_apps/basic-192.png?ignore", - "sizes": "192x192", + "src": "/banners/256x256-green.png?ignore", + "sizes": "256x256", "type": "image/png" } ] } )"; + + if (IsUpdateDialogEnabled()) + chrome::SetAutoAcceptAppIdentityUpdateForTesting(true); + OverrideManifest(kManifest, {}); AppId app_id = InstallWebApp(); - // Replace the contents of basic-192.png with blue-192.png without changing - // the URL. + // Replace the green icon with a red icon without changing the URL. content::URLLoaderInterceptor url_interceptor(base::BindLambdaForTesting( [this](content::URLLoaderInterceptor::RequestParams* params) -> bool /*intercepted*/ { if (params->url_request.url == - http_server_.GetURL("/web_apps/basic-192.png?ignore")) { + http_server_.GetURL("/banners/256x256-green.png?ignore")) { content::URLLoaderInterceptor::WriteResponse( - "chrome/test/data/web_apps/blue-192.png", params->client.get()); + "chrome/test/data/banners/256x256-red.png", params->client.get()); return true; } return false; })); - EXPECT_EQ(GetResultAfterPageLoad(GetAppURL()), - ManifestUpdateResult::kAppUpdated); - histogram_tester_.ExpectBucketCount(kUpdateHistogramName, - ManifestUpdateResult::kAppUpdated, 1); - // The icon should have changed, as the file has been updated (but the url is - // the same). - CheckShortcutInfoUpdated(app_id, SK_ColorBLUE); + if (IsUpdateDialogEnabled()) { + EXPECT_EQ(GetResultAfterPageLoad(GetAppURL()), + ManifestUpdateResult::kAppUpdated); + histogram_tester_.ExpectBucketCount(kUpdateHistogramName, + ManifestUpdateResult::kAppUpdated, 1); + // The icon should have changed, as the file has been updated (but the url + // is the same). + CheckShortcutInfoUpdated(app_id, SK_ColorRED); - EXPECT_EQ(ReadAppIconPixel(app_id, /*size=*/192), SK_ColorBLUE); + EXPECT_EQ(ReadAppIconPixel(app_id, /*size=*/256), SK_ColorRED); + } else { + EXPECT_EQ(GetResultAfterPageLoad(GetAppURL()), + ManifestUpdateResult::kAppUpToDate); + histogram_tester_.ExpectBucketCount(kUpdateHistogramName, + ManifestUpdateResult::kAppUpdated, 0); + CheckShortcutInfoUpdated(app_id, SK_ColorGREEN); + + EXPECT_EQ(ReadAppIconPixel(app_id, /*size=*/256), SK_ColorGREEN); + } } IN_PROC_BROWSER_TEST_F(ManifestUpdateManagerIconUpdatingBrowserTest, @@ -3444,4 +3430,328 @@ run_loop.Run(); } +enum AppIdTestParam { + kInvalid = 0, + kTypeWebApp = 1 << 1, + kTypeDefaultApp = 1 << 2, + kTypePolicyApp = 1 << 3, + kWithFlagNone = 1 << 4, + kWithFlagPolicyAppIdentity = 1 << 5, + kWithFlagAppIdDialog = 1 << 6, + kActionUpdateTitle = 1 << 7, + kActionUpdateSingleIcon = 1 << 8, + kActionUpdateTitleAndSingleIcon = 1 << 9, + kActionAddSingleIcon = 1 << 10, + kActionUpdateMultiIcons = 1 << 11, + kActionRemoveSingleIcon = 1 << 12, + kActionSwitchIconSize = 1 << 13, +}; + +class ManifestUpdateManagerBrowserTest_AppIdentityParameterized + : public ManifestUpdateManagerBrowserTest, + public testing::WithParamInterface< + std::tuple<AppIdTestParam, AppIdTestParam, AppIdTestParam>> { + public: + ManifestUpdateManagerBrowserTest_AppIdentityParameterized() { + std::vector<base::Feature> enabled_features; + std::vector<base::Feature> disabled_features; + if (IsAppIdentityUpdateDialogEnabled()) { + enabled_features.push_back(features::kPwaUpdateDialogForNameAndIcon); + } else { + disabled_features.push_back(features::kPwaUpdateDialogForNameAndIcon); + } + if (IsPolicyAppIdentityOverrideEnabled()) { + enabled_features.push_back( + features::kWebAppManifestPolicyAppIdentityUpdate); + } else { + disabled_features.push_back( + features::kWebAppManifestPolicyAppIdentityUpdate); + } + + scoped_feature_list_.InitWithFeatures(enabled_features, disabled_features); + } + + bool IsWebApp() const { + return std::get<1>(GetParam()) & AppIdTestParam::kTypeWebApp; + } + bool IsDefaultApp() const { + return std::get<1>(GetParam()) & AppIdTestParam::kTypeDefaultApp; + } + bool IsPolicyApp() const { + return std::get<1>(GetParam()) & AppIdTestParam::kTypePolicyApp; + } + + bool IsAppIdentityUpdateDialogEnabled() const { + return std::get<2>(GetParam()) & AppIdTestParam::kWithFlagAppIdDialog; + } + bool IsPolicyAppIdentityOverrideEnabled() const { + return std::get<2>(GetParam()) & AppIdTestParam::kWithFlagPolicyAppIdentity; + } + + bool TitleUpdateRequested() const { + return std::get<0>(GetParam()) & AppIdTestParam::kActionUpdateTitle || + std::get<0>(GetParam()) & + AppIdTestParam::kActionUpdateTitleAndSingleIcon; + } + + bool AnyIconUpdateRequested() const { + return SingleIconAddRequested() || SingleIconRemoveRequested() || + SingleIconUpdateRequested() || MultiIconUpdateRequested() || + IconSwitchUpdateRequested(); + } + bool SingleIconAddRequested() const { + return std::get<0>(GetParam()) & AppIdTestParam::kActionAddSingleIcon; + } + bool SingleIconRemoveRequested() const { + return std::get<0>(GetParam()) & AppIdTestParam::kActionRemoveSingleIcon; + } + bool SingleIconUpdateRequested() const { + return std::get<0>(GetParam()) & AppIdTestParam::kActionUpdateSingleIcon || + std::get<0>(GetParam()) & + AppIdTestParam::kActionUpdateTitleAndSingleIcon; + } + bool MultiIconUpdateRequested() const { + return std::get<0>(GetParam()) & AppIdTestParam::kActionUpdateMultiIcons; + } + bool IconSwitchUpdateRequested() const { + return std::get<0>(GetParam()) & AppIdTestParam::kActionSwitchIconSize; + } + + bool ExpectTitleUpdate() const { + if (!TitleUpdateRequested()) + return false; + + if (IsDefaultApp()) + return true; + if (IsPolicyApp() && IsPolicyAppIdentityOverrideEnabled()) + return true; + return IsAppIdentityUpdateDialogEnabled(); + } + + bool ExpectIconUpdate() const { + // Ideally, this should just check AnyIconUpdateRequested(), but adding and + // removing of icons results in kAppNotEligible when updating, even for + // Default apps. Therefore, only the supported upgrade paths must be + // enumerated here. + if (!SingleIconUpdateRequested() && !MultiIconUpdateRequested() && + !IconSwitchUpdateRequested()) + return false; + + if (IsDefaultApp()) + return true; + if (IsPolicyApp() && IsPolicyAppIdentityOverrideEnabled()) + return true; + if (SingleIconUpdateRequested() && IsAppIdentityUpdateDialogEnabled()) + return true; + + return false; + } + + ManifestUpdateResult ExpectedResultWhenNoUpdate() const { + if (SingleIconAddRequested() || SingleIconRemoveRequested()) + return ManifestUpdateResult::kAppNotEligible; + return ManifestUpdateResult::kAppUpToDate; + } + + static std::string ParamToString( + testing::TestParamInfo< + std::tuple<AppIdTestParam, AppIdTestParam, AppIdTestParam>> + param_info) { + std::string result = ""; + + AppIdTestParam action = std::get<0>(param_info.param); + if (action & AppIdTestParam::kActionUpdateTitle) + result += "UpdateTitle_"; + if (action & AppIdTestParam::kActionUpdateSingleIcon) + result += "UpdateSingleIcon_"; + if (action & AppIdTestParam::kActionUpdateTitleAndSingleIcon) + result += "UpdateTitleAndSingleIcon_"; + if (action & AppIdTestParam::kActionRemoveSingleIcon) + result += "RemoveSingleIcon_"; + if (action & AppIdTestParam::kActionAddSingleIcon) + result += "AddSingleIcon_"; + if (action & AppIdTestParam::kActionUpdateMultiIcons) + result += "UpdateMultiIcons_"; + if (action & AppIdTestParam::kActionSwitchIconSize) + result += "SwitchIcon_"; + + AppIdTestParam type = std::get<1>(param_info.param); + if (type & AppIdTestParam::kTypeWebApp) + result += "WebApp_"; + if (type & AppIdTestParam::kTypeDefaultApp) + result += "DefaultApp_"; + if (type & AppIdTestParam::kTypePolicyApp) + result += "PolicyApp_"; + + AppIdTestParam flags = std::get<2>(param_info.param); + result += "Flags_"; + if (flags & AppIdTestParam::kWithFlagNone) + result += "None_"; + if (flags & AppIdTestParam::kWithFlagPolicyAppIdentity) + result += "PolicyCanUpdate_"; + if (flags & AppIdTestParam::kWithFlagAppIdDialog) + result += "WithAppIdDlg_"; + + return result; + } + + private: + base::test::ScopedFeatureList scoped_feature_list_; +}; + +IN_PROC_BROWSER_TEST_P( + ManifestUpdateManagerBrowserTest_AppIdentityParameterized, + CheckCombinations) { + constexpr char kManifestTemplate[] = R"( + { + "name": "$1", + "start_url": "manifest_test_page.html", + "scope": "/", + "display": "standalone", + "icons": $2 + } + )"; + + // Starting icon set always uses solid green icons. + constexpr SkColor kOriginalIconTopLeftColor = SkColorSetRGB(0x00, 0xFF, 0x00); + // The icons that get updated are all solid red. + constexpr SkColor kUpdatedIconTopLeftColor = SkColorSetRGB(0xFF, 0x00, 0x00); + + // This is always the starting set of icons. Please note that some sizes will + // be auto-generated (see SizesToGenerate()), so the starting state when + // debugging will also consist of sizes 32, 48, 64, 96, 128. Size 256 would be + // autogenerated also, if it were not provided. + constexpr char kIconList[] = R"( + [ + { "src": "256x256-green.png", "sizes": "256x256", "type": "image/png" }, + { "src": "512x512-green.png", "sizes": "512x512", "type": "image/png" } + ] + )"; + + // If we are supposed to remove one icon, this is the end state (512 removed), + // plus auto-generated sizes (see comment in kIconList). + constexpr char kRemovedSingleIconList[] = R"( + [ + { "src": "256x256-green.png", "sizes": "256x256", "type": "image/png" }, + ] + )"; + // If we are supposed to add one icon, this is the end state (128 added), + // plus auto-generated sizes (see comment in kIconList). + constexpr char kAddedSingleIconList[] = R"( + [ + { "src": "128x128-red.png", "sizes": "256x256", "type": "image/png" }, + { "src": "256x256-green.png", "sizes": "256x256", "type": "image/png" }, + { "src": "512x512-green.png", "sizes": "512x512", "type": "image/png" } + ] + )"; + // Updating one icon only changes the bits of size 256 to red. + constexpr char kUpdatedSingleIconList[] = R"( + [ + { "src": "256x256-red.png", "sizes": "256x256", "type": "image/png" }, + { "src": "512x512-green.png", "sizes": "512x512", "type": "image/png" } + ] + )"; + // Updating multiple icons changes size 256 and size 512 to red. + constexpr char kUpdatedMultiIconList[] = R"( + [ + { "src": "256x256-red.png", "sizes": "256x256", "type": "image/png" }, + { "src": "512x512-red.png", "sizes": "512x512", "type": "image/png" } + ] + )"; + // Icon switch involves removing a size and replacing it with another. Here, + // size 256 has been removed and size 128 added. Note that size 256 will still + // be found in the end state because it gets auto-generated. + constexpr char kIconSwitchList[] = R"( + [ + { "src": "128x128-red.png", "sizes": "128x128", "type": "image/png" }, + { "src": "512x512-green.png", "sizes": "512x512", "type": "image/png" } + ] + )"; + + testing::TestParamInfo< + std::tuple<AppIdTestParam, AppIdTestParam, AppIdTestParam>> + param(GetParam(), 0); + + if (IsAppIdentityUpdateDialogEnabled()) + chrome::SetAutoAcceptAppIdentityUpdateForTesting(true); + + std::string app_name = "Test app name"; + OverrideManifest(kManifestTemplate, {app_name, kIconList}); + + AppId app_id; + if (IsDefaultApp()) { + app_id = InstallDefaultApp(); + } else if (IsPolicyApp()) { + app_id = InstallPolicyApp(); + } else if (IsWebApp()) { + app_id = InstallWebApp(); + } else { + NOTREACHED(); + } + + const WebApp* web_app = GetProvider().registrar().GetAppById(app_id); + ASSERT_TRUE(web_app); + + if (TitleUpdateRequested()) + app_name = "Different app name"; + + if (SingleIconUpdateRequested()) { + OverrideManifest(kManifestTemplate, {app_name, kUpdatedSingleIconList}); + } else if (SingleIconAddRequested()) { + OverrideManifest(kManifestTemplate, {app_name, kAddedSingleIconList}); + } else if (SingleIconRemoveRequested()) { + OverrideManifest(kManifestTemplate, {app_name, kRemovedSingleIconList}); + } else if (MultiIconUpdateRequested()) { + OverrideManifest(kManifestTemplate, {app_name, kUpdatedMultiIconList}); + } else if (IconSwitchUpdateRequested()) { + OverrideManifest(kManifestTemplate, {app_name, kIconSwitchList}); + } else { + OverrideManifest(kManifestTemplate, {app_name, kIconList}); + } + + bool expectations_match = (TitleUpdateRequested() == ExpectTitleUpdate()) && + (AnyIconUpdateRequested() == ExpectIconUpdate()); + if ((TitleUpdateRequested() || AnyIconUpdateRequested()) && + expectations_match) { + ASSERT_EQ(ManifestUpdateResult::kAppUpdated, + GetResultAfterPageLoad(GetAppURL())); + histogram_tester_.ExpectBucketCount(kUpdateHistogramName, + ManifestUpdateResult::kAppUpdated, 1); + } else { + ASSERT_EQ(ExpectedResultWhenNoUpdate(), + GetResultAfterPageLoad(GetAppURL())); + histogram_tester_.ExpectBucketCount(kUpdateHistogramName, + ManifestUpdateResult::kAppUpdated, 0); + } + + EXPECT_EQ(ExpectTitleUpdate() && expectations_match ? "Different app name" + : "Test app name", + GetProvider().registrar().GetAppShortName(app_id)); + + CheckShortcutInfoUpdated(app_id, ExpectIconUpdate() && expectations_match + ? kUpdatedIconTopLeftColor + : kOriginalIconTopLeftColor); +} + +INSTANTIATE_TEST_SUITE_P( + All, + ManifestUpdateManagerBrowserTest_AppIdentityParameterized, + testing::Combine( + testing::Values(AppIdTestParam::kActionUpdateTitle, + AppIdTestParam::kActionUpdateSingleIcon, + AppIdTestParam::kActionUpdateTitleAndSingleIcon, + AppIdTestParam::kActionUpdateMultiIcons, + AppIdTestParam::kActionAddSingleIcon, + AppIdTestParam::kActionRemoveSingleIcon, + AppIdTestParam::kActionSwitchIconSize), + testing::Values(AppIdTestParam::kTypeDefaultApp, + AppIdTestParam::kTypePolicyApp, + AppIdTestParam::kTypeWebApp), + testing::Values(AppIdTestParam::kWithFlagNone, + AppIdTestParam::kWithFlagPolicyAppIdentity, + AppIdTestParam::kWithFlagAppIdDialog, + AppIdTestParam::kWithFlagPolicyAppIdentity | + AppIdTestParam::kWithFlagAppIdDialog)), + ManifestUpdateManagerBrowserTest_AppIdentityParameterized::ParamToString); + } // namespace web_app
diff --git a/chrome/browser/web_applications/manifest_update_task.cc b/chrome/browser/web_applications/manifest_update_task.cc index fa37150e..4662494 100644 --- a/chrome/browser/web_applications/manifest_update_task.cc +++ b/chrome/browser/web_applications/manifest_update_task.cc
@@ -34,27 +34,26 @@ namespace web_app { -struct IconDiff { - public: - IconDiff() = default; - explicit IconDiff(bool changes) { changes_detected = changes; } - IconDiff(const SkBitmap& before_icon, const SkBitmap& after_icon) { - changes_detected = true; - before = before_icon; - after = after_icon; - } - bool changes_detected = false; - SkBitmap before; - SkBitmap after; -}; - namespace { -IconDiff HaveIconContentsChanged( +void HaveIconContentsChanged( const std::map<SquareSizePx, SkBitmap>& disk_icon_bitmaps, - const std::map<SquareSizePx, SkBitmap>& downloaded_icon_bitmaps) { - if (downloaded_icon_bitmaps.size() != disk_icon_bitmaps.size()) - return IconDiff(true); + const std::map<SquareSizePx, SkBitmap>& downloaded_icon_bitmaps, + IconDiff* icon_diff, + const std::vector<SquareSizePx>& on_disk_sizes, + const std::vector<SquareSizePx>& downloaded_sizes, + bool end_when_mismatch_detected) { + if (downloaded_icon_bitmaps.size() != disk_icon_bitmaps.size()) { + icon_diff->diff_results |= MISMATCHED_IMAGE_SIZES; + if (end_when_mismatch_detected) + return; + } + + if (on_disk_sizes != downloaded_sizes) { + icon_diff->diff_results |= MISMATCHED_IMAGE_SIZES; + if (end_when_mismatch_detected) + return; + } for (const std::pair<const SquareSizePx, SkBitmap>& entry : downloaded_icon_bitmaps) { @@ -62,35 +61,42 @@ const SkBitmap& downloaded_bitmap = entry.second; auto it = disk_icon_bitmaps.find(size); - if (it == disk_icon_bitmaps.end()) - return IconDiff(true); + if (it == disk_icon_bitmaps.end()) { + icon_diff->diff_results |= MISMATCHED_IMAGE_SIZES; + if (end_when_mismatch_detected) + return; + continue; + } const SkBitmap& disk_bitmap = it->second; - if (!gfx::BitmapsAreEqual(downloaded_bitmap, disk_bitmap)) - return IconDiff(disk_bitmap, downloaded_bitmap); + if (!gfx::BitmapsAreEqual(downloaded_bitmap, disk_bitmap)) { + if (end_when_mismatch_detected) { + icon_diff->diff_results |= ONE_OR_MORE_ICONS_CHANGED; + return; + } else { + // Icons that are specified in new manifest are of special interest, the + // rest is auto-generated. + bool important_icon = + std::find(downloaded_sizes.begin(), downloaded_sizes.end(), size) != + downloaded_sizes.end(); + if (!important_icon) { + icon_diff->diff_results |= GENERATED_ICON_CHANGED; + } else if ((icon_diff->diff_results & SINGLE_ICON_CHANGED) == 0 && + (icon_diff->diff_results & MULTIPLE_ICONS_CHANGED) == 0) { + icon_diff->diff_results |= SINGLE_ICON_CHANGED; + icon_diff->before = disk_bitmap; + icon_diff->after = downloaded_bitmap; + } else if (icon_diff->diff_results & SINGLE_ICON_CHANGED) { + icon_diff->diff_results &= ~SINGLE_ICON_CHANGED; + icon_diff->diff_results |= MULTIPLE_ICONS_CHANGED; + // The UI can only handle showing one image at a time, at the moment. + icon_diff->before = SkBitmap(); + icon_diff->after = SkBitmap(); + return; + } + } + } } - - return IconDiff(false); -} - -IconDiff HaveIconBitmapsChanged(const IconBitmaps& disk_icon_bitmaps, - const IconBitmaps& downloaded_icon_bitmaps) { - IconDiff icon_diff = HaveIconContentsChanged(disk_icon_bitmaps.any, - downloaded_icon_bitmaps.any); - if (icon_diff.changes_detected) - return icon_diff; - - icon_diff = HaveIconContentsChanged(disk_icon_bitmaps.maskable, - downloaded_icon_bitmaps.maskable); - if (icon_diff.changes_detected) - return icon_diff; - - icon_diff = HaveIconContentsChanged(disk_icon_bitmaps.monochrome, - downloaded_icon_bitmaps.monochrome); - if (icon_diff.changes_detected) - return icon_diff; - - return IconDiff(false); } // Some apps, such as pre-installed apps, have been vetted and are therefore @@ -115,8 +121,74 @@ base::FeatureList::IsEnabled(features::kWebAppManifestIconUpdating); } +bool NeedsAppIdentityUpdateDialog(bool title_changing, + bool icons_changing, + const AppId& app_id, + const WebAppRegistrar& registrar) { + if (title_changing && !AllowUnpromptedNameUpdate(app_id, registrar)) + return true; + if (icons_changing && !AllowUnpromptedIconUpdate(app_id, registrar)) + return true; + return false; +} + } // namespace +IconDiff HaveIconBitmapsChanged( + const IconBitmaps& disk_icon_bitmaps, + const IconBitmaps& downloaded_icon_bitmaps, + const std::vector<apps::IconInfo>& disk_icon_info, + const std::vector<apps::IconInfo>& downloaded_icon_info, + bool end_when_mismatch_detected) { + // The manifest information associated with the icons is a flat vector of + // IconInfo types. This needs to be split into vectors and keyed by purpose + // (any, masked, monochrome) so that it can be read by the icon diff. + std::map<apps::IconInfo::Purpose, std::vector<SquareSizePx>> on_disk_sizes; + std::map<apps::IconInfo::Purpose, std::vector<SquareSizePx>> downloaded_sizes; + on_disk_sizes[apps::IconInfo::Purpose::kAny] = std::vector<SquareSizePx>(); + downloaded_sizes[apps::IconInfo::Purpose::kAny] = std::vector<SquareSizePx>(); + on_disk_sizes[apps::IconInfo::Purpose::kMaskable] = + std::vector<SquareSizePx>(); + downloaded_sizes[apps::IconInfo::Purpose::kMaskable] = + std::vector<SquareSizePx>(); + on_disk_sizes[apps::IconInfo::Purpose::kMonochrome] = + std::vector<SquareSizePx>(); + downloaded_sizes[apps::IconInfo::Purpose::kMonochrome] = + std::vector<SquareSizePx>(); + // Put each entry found into the right map (sort by purpose). + for (auto entry : disk_icon_info) { + on_disk_sizes[entry.purpose].push_back(entry.square_size_px.value_or(-1)); + } + for (auto entry : downloaded_icon_info) { + downloaded_sizes[entry.purpose].push_back( + entry.square_size_px.value_or(-1)); + } + + IconDiff icon_diff; + HaveIconContentsChanged(disk_icon_bitmaps.any, downloaded_icon_bitmaps.any, + &icon_diff, + on_disk_sizes[apps::IconInfo::Purpose::kAny], + downloaded_sizes[apps::IconInfo::Purpose::kAny], + end_when_mismatch_detected); + if (icon_diff.mismatch() && end_when_mismatch_detected) + return icon_diff; + + HaveIconContentsChanged(disk_icon_bitmaps.maskable, + downloaded_icon_bitmaps.maskable, &icon_diff, + on_disk_sizes[apps::IconInfo::Purpose::kMaskable], + downloaded_sizes[apps::IconInfo::Purpose::kMaskable], + end_when_mismatch_detected); + if (icon_diff.mismatch() && end_when_mismatch_detected) + return icon_diff; + + HaveIconContentsChanged( + disk_icon_bitmaps.monochrome, downloaded_icon_bitmaps.monochrome, + &icon_diff, on_disk_sizes[apps::IconInfo::Purpose::kMonochrome], + downloaded_sizes[apps::IconInfo::Purpose::kMonochrome], + end_when_mismatch_detected); + return icon_diff; +} + ManifestUpdateTask::ManifestUpdateTask( const GURL& url, const AppId& app_id, @@ -181,9 +253,9 @@ case Stage::kPendingInstallableData: case Stage::kPendingIconDownload: case Stage::kPendingIconReadFromDisk: + case Stage::kPendingAppIdentityCheck: DestroySelf(ManifestUpdateResult::kWebContentsDestroyed); return; - case Stage::kPendingAppIdentityCheck: case Stage::kPendingWindowsClosed: case Stage::kPendingMaybeReadExistingIcons: case Stage::kPendingInstallation: @@ -234,6 +306,20 @@ const WebApp* app = registrar_.GetAppById(app_id_); DCHECK(app); + bool title_changing = + web_application_info_->title != base::UTF8ToUTF16(app->name()); + bool icons_changing = + web_application_info_->manifest_icons != app->manifest_icons(); + if (!NeedsAppIdentityUpdateDialog(title_changing, icons_changing, app_id_, + registrar_)) { + if (title_changing && AllowUnpromptedNameUpdate(app_id_, registrar_)) { + return true; + } + if (icons_changing && AllowUnpromptedIconUpdate(app_id_, registrar_)) { + return true; + } + } + // Allows updating start_url and manifest_id when kWebAppEnableManifestId is // enabled. Both fields are allowed to change as long as the app_id generated // from them doesn't change. @@ -256,13 +342,6 @@ if (web_application_info_->display_override != app->display_mode_override()) return true; - // Allow app icon updating for certain apps, if the existing icons are - // empty - this means the app icon download during install failed. - if (AllowUnpromptedIconUpdate(app_id_, registrar_) && - web_application_info_->manifest_icons != app->manifest_icons()) { - return true; - } - if (web_application_info_->shortcuts_menu_item_infos != app->shortcuts_menu_item_infos()) { return true; @@ -301,11 +380,6 @@ if (web_application_info_->manifest_url != app->manifest_url()) return true; - if (AllowUnpromptedNameUpdate(app_id_, registrar_) && - web_application_info_->title != base::UTF8ToUTF16(app->name())) { - return true; - } - if (web_application_info_->launch_handler != app->launch_handler()) return true; @@ -371,81 +445,88 @@ } DCHECK(web_application_info_.has_value()); - content::WebContents* web_contents = WebContentsObserver::web_contents(); stage_ = Stage::kPendingAppIdentityCheck; - Observe(nullptr); - PopulateOtherIcons(&web_application_info_.value(), downloaded_icons_map); - - // This call populates the |web_application_info_| with all icon bitmap + // These calls populate the |web_application_info_| with all icon bitmap // data. // If this data does not match what we already have on disk, then an update // is necessary. // TODO(https://crbug.com/1184911): Reuse this data in the web app install // task. + PopulateOtherIcons(&web_application_info_.value(), downloaded_icons_map); PopulateProductIcons(&web_application_info_.value(), &downloaded_icons_map); + if (!base::FeatureList::IsEnabled(features::kPwaUpdateDialogForNameAndIcon)) { + OnPostAppIdentityUpdateCheck(AppIdentityUpdate::kSkipped); + return; + } + IconDiff icon_diff = IsUpdateNeededForIconContents(disk_icon_bitmaps); std::u16string old_title = base::UTF8ToUTF16(registrar_.GetAppShortName(app_id_)); std::u16string new_title = web_application_info_->title; - bool title_change = old_title != new_title; - bool show_dialog_for_name_update = - title_change & !AllowUnpromptedNameUpdate(app_id_, registrar_); - bool show_dialog_for_icon_update = - icon_diff.changes_detected & - !AllowUnpromptedIconUpdate(app_id_, registrar_); + bool title_change = old_title != new_title; + bool icon_change = icon_diff.mismatch(); + + if (!title_change && !icon_change) { + OnPostAppIdentityUpdateCheck(AppIdentityUpdate::kSkipped); + return; + } + + if (!NeedsAppIdentityUpdateDialog(title_change, icon_change, app_id_, + registrar_)) { + // The app identity update can be skipped, because any update not requiring + // the AppIdentityUpdate dialog should have been triggered already by + // running IsUpdateNeededForManifest. It doesn't matter a great deal whether + // kSkipped or kAllowed is used here, except that updating should also work + // without approval here. So to be safe we return kSkipped. + OnPostAppIdentityUpdateCheck(AppIdentityUpdate::kSkipped); + return; + } + + if (icon_change && !icon_diff.supported_for_app_identity_check()) { + OnPostAppIdentityUpdateCheck(AppIdentityUpdate::kSkipped); + return; + } // Note: If icon and name changes are to be actually used later and not // overridden, then OnPostAppIdentityUpdateCheck must be called with // |AppIdentityUpdate::kAllowed| so |app_identity_update_allowed_| is true. - if (show_dialog_for_name_update || show_dialog_for_icon_update) { - // An identity update with a confirmation dialog is needed. See if it is - // available and show it -- or if not, abort the update. - if (!base::FeatureList::IsEnabled( - features::kPwaUpdateDialogForNameAndIcon)) { - OnPostAppIdentityUpdateCheck(AppIdentityUpdate::kSkipped); - return; + SkBitmap* before_icon = nullptr; + SkBitmap* after_icon = nullptr; + if (icon_diff.mismatch()) { + before_icon = &icon_diff.before; + after_icon = &icon_diff.after; + } else { + auto it = disk_icon_bitmaps.any.find(web_app::kWebAppIconSmall); + if (it != disk_icon_bitmaps.any.end()) { + before_icon = &it->second; + after_icon = &it->second; } + } - SkBitmap* before_icon = nullptr; - SkBitmap* after_icon = nullptr; - if (icon_diff.changes_detected) { - before_icon = &icon_diff.before; - after_icon = &icon_diff.after; - } else { - auto it = disk_icon_bitmaps.any.find(web_app::kWebAppIconSmall); - if (it != disk_icon_bitmaps.any.end()) { - before_icon = &it->second; - after_icon = &it->second; - } - } - - if (before_icon != nullptr && after_icon != nullptr && - !before_icon->drawsNothing() && !after_icon->drawsNothing()) { - ui_manager_.ShowWebAppIdentityUpdateDialog( - app_id_, title_change, icon_diff.changes_detected, old_title, - new_title, *before_icon, *after_icon, web_contents, - base::BindOnce(&ManifestUpdateTask::OnPostAppIdentityUpdateCheck, - AsWeakPtr())); - return; - } - } else if (title_change || icon_diff.changes_detected) { - // An identity update has been detected, but we've already determined it - // doesn't require the confirmation dialog, so the change can be allowed. - OnPostAppIdentityUpdateCheck(AppIdentityUpdate::kAllowed); + if (before_icon == nullptr || after_icon == nullptr || + before_icon->drawsNothing() || after_icon->drawsNothing()) { + OnPostAppIdentityUpdateCheck(AppIdentityUpdate::kSkipped); return; } - // No identity change is happening (or we couldn't get the image diffs), so - // skip the check. - OnPostAppIdentityUpdateCheck(AppIdentityUpdate::kSkipped); + content::WebContents* web_contents = WebContentsObserver::web_contents(); + ui_manager_.ShowWebAppIdentityUpdateDialog( + app_id_, title_change, icon_diff.mismatch(), old_title, new_title, + *before_icon, *after_icon, web_contents, + base::BindOnce(&ManifestUpdateTask::OnPostAppIdentityUpdateCheck, + AsWeakPtr())); + + // Flow continues in OnPostAppIdentityUpdateCheck, once an action has been + // taken in the dialog. } void ManifestUpdateTask::OnPostAppIdentityUpdateCheck( AppIdentityUpdate app_identity_update_allowed) { DCHECK_EQ(stage_, Stage::kPendingAppIdentityCheck); + Observe(nullptr); app_identity_update_allowed_ = app_identity_update_allowed == AppIdentityUpdate::kAllowed; if (app_identity_update_allowed_) { @@ -461,8 +542,13 @@ IconDiff ManifestUpdateTask::IsUpdateNeededForIconContents( const IconBitmaps& disk_icon_bitmaps) const { DCHECK(web_application_info_.has_value()); - return HaveIconBitmapsChanged(disk_icon_bitmaps, - web_application_info_->icon_bitmaps); + const WebApp* app = registrar_.GetAppById(app_id_); + DCHECK(app); + + return HaveIconBitmapsChanged( + disk_icon_bitmaps, web_application_info_->icon_bitmaps, + web_application_info_->manifest_icons, app->manifest_icons(), + /* end_when_mismatch_detected= */ false); } void ManifestUpdateTask::OnAllShortcutsMenuIconsRead( @@ -490,12 +576,17 @@ return true; } + const WebApp* app = registrar_.GetAppById(app_id_); + DCHECK(app); for (size_t i = 0; i < downloaded_shortcuts_menu_icon_bitmaps.size(); ++i) { const IconBitmaps& downloaded_icon_bitmaps = downloaded_shortcuts_menu_icon_bitmaps[i]; const IconBitmaps& disk_icon_bitmaps = disk_shortcuts_menu_icon_bitmaps[i]; - if (HaveIconBitmapsChanged(disk_icon_bitmaps, downloaded_icon_bitmaps) - .changes_detected) + if (HaveIconBitmapsChanged(disk_icon_bitmaps, downloaded_icon_bitmaps, + web_application_info_->manifest_icons, + app->manifest_icons(), + /* end_when_mismatch_detected= */ true) + .mismatch()) return true; }
diff --git a/chrome/browser/web_applications/manifest_update_task.h b/chrome/browser/web_applications/manifest_update_task.h index 17ed559..53c85e97 100644 --- a/chrome/browser/web_applications/manifest_update_task.h +++ b/chrome/browser/web_applications/manifest_update_task.h
@@ -58,6 +58,84 @@ kMaxValue = kAppAssociationsUpdated, }; +enum IconDiffResult : uint32_t { + NO_CHANGE_DETECTED = 0, + + // A mismatch was detected between what was downloaded and what is on disk. + // This might mean that a size has been removed or added, and it could mean + // both. + MISMATCHED_IMAGE_SIZES = 1 << 1, + + // At least one icon was found to have changed. Note: Used only if the diff + // process stops when it encounters the first mismatch. If, instead, it is + // allowed to continue, a more detailed results will be returned (see flags + // below). + ONE_OR_MORE_ICONS_CHANGED = 1 << 2, + + // Only one icon is changing. This flag is only set if the diff process is + // allowed to continue to the end (doesn't stop as soon as it finds a change). + SINGLE_ICON_CHANGED = 1 << 3, + + // Two or more icons are changing. This flag is only set if the diff process + // is allowed to continue to the end (doesn't stop as soon as it finds a + // change). + MULTIPLE_ICONS_CHANGED = 1 << 4, + + // And icon has changed, but it was a generated icon that changed. This flag + // is only set if the diff process is allowed to continue to the end (doesn't + // stop as soon as it finds a change). + GENERATED_ICON_CHANGED = 1 << 5, +}; + +// A structure to keep track of the differences found while comparing icons +// on disk to what has been downloaded. +struct IconDiff { + public: + IconDiff() = default; + explicit IconDiff(uint32_t results) { diff_results = results; } + IconDiff(const SkBitmap& before_icon, + const SkBitmap& after_icon, + uint32_t results) { + before = before_icon; + after = after_icon; + diff_results = results; + } + + // Returns true iff an icon change was detected (not matter how + // insignificant). + bool mismatch() { return diff_results != NO_CHANGE_DETECTED; } + + // Returns true iff the mismatch should result in app identity dlg being + // shown. + bool supported_for_app_identity_check() { + return diff_results == SINGLE_ICON_CHANGED || + diff_results == (SINGLE_ICON_CHANGED | GENERATED_ICON_CHANGED); + } + + // Keeps track of all the differences discovered in the icon set. + uint32_t diff_results = NO_CHANGE_DETECTED; + + // The original image. Only valid if a single icon is changing. + SkBitmap before; + + // The changed image. Only valid if a single icon is changing. + SkBitmap after; +}; + +// Returns whether any differences were found in the images on disk and what has +// been downloaded. The |disk_icon_bitmaps| and |disk_icon_info| parameters +// represent the bits on disk and the associated size info (respectively). Same +// with |downloaded_icon_bitmaps| and |downloaded_icon_info|, which covers the +// downloaded icon set. If |end_when_mismatch_detected| is true, the diff +// process will stop when it encounters the first mismatch. Otherwise, it the +// IconDiff returned will cover all the differences found. +IconDiff HaveIconBitmapsChanged( + const IconBitmaps& disk_icon_bitmaps, + const IconBitmaps& downloaded_icon_bitmaps, + const std::vector<apps::IconInfo>& disk_icon_info, + const std::vector<apps::IconInfo>& downloaded_icon_info, + bool end_when_mismatch_detected); + // Checks whether the installed web app associated with a given WebContents has // out of date manifest data and triggers an update if so. // Owned and managed by |ManifestUpdateManager|.
diff --git a/chrome/browser/web_applications/manifest_update_task_unittest.cc b/chrome/browser/web_applications/manifest_update_task_unittest.cc index eff1a6c..b088ba0 100644 --- a/chrome/browser/web_applications/manifest_update_task_unittest.cc +++ b/chrome/browser/web_applications/manifest_update_task_unittest.cc
@@ -5,6 +5,8 @@ #include "chrome/browser/web_applications/manifest_update_task.h" #include "base/strings/utf_string_conversions.h" +#include "chrome/browser/web_applications/test/web_app_icon_test_utils.h" +#include "chrome/browser/web_applications/web_app_icon_generator.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/public/mojom/manifest/manifest.mojom.h" @@ -126,4 +128,359 @@ EXPECT_NE(old_handlers, new_handlers); } +std::vector<apps::IconInfo> GenerateIconInfosFrom( + const IconBitmaps& downloaded) { + std::vector<apps::IconInfo> result; + for (auto entry : downloaded.any) { + apps::IconInfo icon_info(GURL(), entry.first); + icon_info.purpose = apps::IconInfo::Purpose::kAny; + result.push_back(icon_info); + } + for (auto entry : downloaded.maskable) { + apps::IconInfo icon_info(GURL(), entry.first); + icon_info.purpose = apps::IconInfo::Purpose::kMaskable; + result.push_back(icon_info); + } + for (auto entry : downloaded.monochrome) { + apps::IconInfo icon_info(GURL(), entry.first); + icon_info.purpose = apps::IconInfo::Purpose::kMonochrome; + result.push_back(icon_info); + } + return result; +} + +TEST_F(ManifestUpdateTaskTest, TestImageComparison) { + { + // Test case: Find first difference with two empty IconBitmaps as input + // should report no differences. + IconBitmaps on_disk; + IconBitmaps downloaded; + IconDiff diff = HaveIconBitmapsChanged( + on_disk, downloaded, GenerateIconInfosFrom(on_disk), + GenerateIconInfosFrom(downloaded), + /* end_when_mismatch_detected= */ true); + EXPECT_EQ(NO_CHANGE_DETECTED, diff.diff_results); + EXPECT_TRUE(diff.before.drawsNothing()); + EXPECT_TRUE(diff.after.drawsNothing()); + } + { + // Test case: Find all differences with two empty IconBitmaps as input + // should report no differences. + IconBitmaps on_disk; + IconBitmaps downloaded; + + IconDiff diff = HaveIconBitmapsChanged( + on_disk, downloaded, GenerateIconInfosFrom(on_disk), + GenerateIconInfosFrom(downloaded), + /* end_when_mismatch_detected= */ false); + EXPECT_EQ(NO_CHANGE_DETECTED, diff.diff_results); + EXPECT_TRUE(diff.before.drawsNothing()); + EXPECT_TRUE(diff.after.drawsNothing()); + } + + { + // Test case: Find first difference when one new image has been downloaded + // should report size mismatch. + IconBitmaps on_disk; + IconBitmaps downloaded; + AddGeneratedIcon(&downloaded.any, icon_size::k512, SK_ColorYELLOW); + + IconDiff diff = HaveIconBitmapsChanged( + on_disk, downloaded, GenerateIconInfosFrom(on_disk), + GenerateIconInfosFrom(downloaded), + /* end_when_mismatch_detected= */ true); + EXPECT_EQ(MISMATCHED_IMAGE_SIZES, diff.diff_results); + EXPECT_TRUE(diff.before.drawsNothing()); + EXPECT_TRUE(diff.after.drawsNothing()); + } + { + // Test case: Find all differences when one new image has been downloaded + // should report size mismatch. + IconBitmaps on_disk; + IconBitmaps downloaded; + AddGeneratedIcon(&downloaded.any, icon_size::k512, SK_ColorYELLOW); + + IconDiff diff = HaveIconBitmapsChanged( + on_disk, downloaded, GenerateIconInfosFrom(on_disk), + GenerateIconInfosFrom(downloaded), + /* end_when_mismatch_detected= */ false); + EXPECT_EQ(MISMATCHED_IMAGE_SIZES, diff.diff_results); + EXPECT_TRUE(diff.before.drawsNothing()); + EXPECT_TRUE(diff.after.drawsNothing()); + } + + { + // Test case: Find first difference when one image has been removed + // should report size mismatch. + IconBitmaps on_disk; + IconBitmaps downloaded; + AddGeneratedIcon(&on_disk.any, icon_size::k512, SK_ColorYELLOW); + + IconDiff diff = HaveIconBitmapsChanged( + on_disk, downloaded, GenerateIconInfosFrom(on_disk), + GenerateIconInfosFrom(downloaded), + /* end_when_mismatch_detected= */ true); + EXPECT_EQ(MISMATCHED_IMAGE_SIZES, diff.diff_results); + EXPECT_TRUE(diff.before.drawsNothing()); + EXPECT_TRUE(diff.after.drawsNothing()); + } + { + // Test case: Find all differences when one new image has been removed + // should report size mismatch. + IconBitmaps on_disk; + IconBitmaps downloaded; + AddGeneratedIcon(&on_disk.any, icon_size::k512, SK_ColorYELLOW); + + IconDiff diff = HaveIconBitmapsChanged( + on_disk, downloaded, GenerateIconInfosFrom(on_disk), + GenerateIconInfosFrom(downloaded), + /* end_when_mismatch_detected= */ false); + EXPECT_EQ(MISMATCHED_IMAGE_SIZES, diff.diff_results); + EXPECT_TRUE(diff.before.drawsNothing()); + EXPECT_TRUE(diff.after.drawsNothing()); + } + + { + // Test case: Find first difference, when one image has been removed and one + // added, should report size mismatch. + IconBitmaps on_disk; + IconBitmaps downloaded; + AddGeneratedIcon(&on_disk.any, icon_size::k256, SK_ColorRED); + AddGeneratedIcon(&downloaded.any, icon_size::k512, SK_ColorYELLOW); + + IconDiff diff = HaveIconBitmapsChanged(on_disk, downloaded, + GenerateIconInfosFrom(on_disk), + GenerateIconInfosFrom(downloaded), + /* end_when_mismatch_detected= */ + true); + // First mismatch found will be the added image, then it will stop. + EXPECT_EQ(MISMATCHED_IMAGE_SIZES, diff.diff_results); + EXPECT_TRUE(diff.before.drawsNothing()); + EXPECT_TRUE(diff.after.drawsNothing()); + } + { + // Test case: Find all differences, when one image has been removed and one + // added, should report size mismatch. + IconBitmaps on_disk; + IconBitmaps downloaded; + AddGeneratedIcon(&on_disk.any, icon_size::k256, SK_ColorRED); + AddGeneratedIcon(&downloaded.any, icon_size::k512, SK_ColorYELLOW); + + IconDiff diff = HaveIconBitmapsChanged(on_disk, downloaded, + GenerateIconInfosFrom(on_disk), + GenerateIconInfosFrom(downloaded), + /* end_when_mismatch_detected= + */ + false); + EXPECT_EQ(MISMATCHED_IMAGE_SIZES, diff.diff_results); + EXPECT_TRUE(diff.before.drawsNothing()); + EXPECT_TRUE(diff.after.drawsNothing()); + } + + { + // Test case: Find first difference, when one image has been removed and one + // added (but across maps), should report size mismatch. + IconBitmaps on_disk; + IconBitmaps downloaded; + AddGeneratedIcon(&on_disk.maskable, icon_size::k256, SK_ColorRED); + AddGeneratedIcon(&downloaded.monochrome, icon_size::k512, SK_ColorYELLOW); + + IconDiff diff = HaveIconBitmapsChanged(on_disk, downloaded, + GenerateIconInfosFrom(on_disk), + GenerateIconInfosFrom(downloaded), + /* end_when_mismatch_detected= + */ + true); + // First mismatch found will be the fact that one of the maps has changed + // size. + EXPECT_EQ(MISMATCHED_IMAGE_SIZES, diff.diff_results); + EXPECT_TRUE(diff.before.drawsNothing()); + EXPECT_TRUE(diff.after.drawsNothing()); + } + { + // Test case: Find all differences, when one image has been removed and one + // added (but across maps), should report size mismatch. + IconBitmaps on_disk; + IconBitmaps downloaded; + AddGeneratedIcon(&on_disk.maskable, icon_size::k256, SK_ColorRED); + AddGeneratedIcon(&downloaded.monochrome, icon_size::k512, SK_ColorYELLOW); + + IconDiff diff = HaveIconBitmapsChanged(on_disk, downloaded, + GenerateIconInfosFrom(on_disk), + GenerateIconInfosFrom(downloaded), + /* end_when_mismatch_detected= */ + false); + EXPECT_EQ(MISMATCHED_IMAGE_SIZES, diff.diff_results); + EXPECT_TRUE(diff.before.drawsNothing()); + EXPECT_TRUE(diff.after.drawsNothing()); + } + + { + // Test case: Find first difference, when one image has had its bits + // updated, should return ONE_OR_MORE_ICONS_CHANGED. + IconBitmaps on_disk; + IconBitmaps downloaded; + AddGeneratedIcon(&on_disk.any, icon_size::k256, SK_ColorRED); + AddGeneratedIcon(&downloaded.any, icon_size::k256, SK_ColorYELLOW); + + IconDiff diff = HaveIconBitmapsChanged(on_disk, downloaded, + GenerateIconInfosFrom(on_disk), + GenerateIconInfosFrom(downloaded), + /* end_when_mismatch_detected= */ + true); + EXPECT_EQ(ONE_OR_MORE_ICONS_CHANGED, diff.diff_results); + // The expectation here might, at a glance, seem unusual because there *has* + // been a change in only a single icon. However, this was detected via the + // short pass, which does not provide |before| and |after| images (only the + // longer pass will know whether more images changed). + EXPECT_TRUE(diff.before.drawsNothing()); + EXPECT_TRUE(diff.after.drawsNothing()); + } + { + // Test case: Find all differences, when one image has had its bits + // updated, should return SINGLE_ICON_CHANGED. + IconBitmaps on_disk; + IconBitmaps downloaded; + AddGeneratedIcon(&on_disk.any, icon_size::k256, SK_ColorRED); + AddGeneratedIcon(&downloaded.any, icon_size::k256, SK_ColorYELLOW); + + IconDiff diff = HaveIconBitmapsChanged( + on_disk, downloaded, GenerateIconInfosFrom(on_disk), + GenerateIconInfosFrom(downloaded), + /* end_when_mismatch_detected= */ false); + EXPECT_EQ(SINGLE_ICON_CHANGED, diff.diff_results); + // The function has checked all possibilities and is able to provide before + // and after images, because it knows only a single image changed. + EXPECT_FALSE(diff.before.drawsNothing()); + EXPECT_FALSE(diff.after.drawsNothing()); + } + + { + // Test case: Find first difference, when two images have had their bits + // updated, should return ONE_OR_MORE_ICONS_CHANGED. + IconBitmaps on_disk; + IconBitmaps downloaded; + AddGeneratedIcon(&on_disk.any, icon_size::k256, SK_ColorRED); + AddGeneratedIcon(&on_disk.any, icon_size::k512, SK_ColorRED); + AddGeneratedIcon(&downloaded.any, icon_size::k256, SK_ColorYELLOW); + AddGeneratedIcon(&downloaded.any, icon_size::k512, SK_ColorYELLOW); + + IconDiff diff = HaveIconBitmapsChanged(on_disk, downloaded, + GenerateIconInfosFrom(on_disk), + GenerateIconInfosFrom(downloaded), + /* end_when_mismatch_detected= */ + true); + EXPECT_EQ(ONE_OR_MORE_ICONS_CHANGED, diff.diff_results); + // Since more than two images changed, the |before| and |after| isn't + // provided. + EXPECT_TRUE(diff.before.drawsNothing()); + EXPECT_TRUE(diff.after.drawsNothing()); + } + { + // Test case: Find all differences, when two images have had their bits + // updated, should return MULTIPLE_ICONS_CHANGED. + IconBitmaps on_disk; + IconBitmaps downloaded; + AddGeneratedIcon(&on_disk.any, icon_size::k256, SK_ColorRED); + AddGeneratedIcon(&on_disk.any, icon_size::k512, SK_ColorRED); + AddGeneratedIcon(&downloaded.any, icon_size::k256, SK_ColorYELLOW); + AddGeneratedIcon(&downloaded.any, icon_size::k512, SK_ColorYELLOW); + + IconDiff diff = HaveIconBitmapsChanged(on_disk, downloaded, + GenerateIconInfosFrom(on_disk), + GenerateIconInfosFrom(downloaded), + /* end_when_mismatch_detected= */ + false); + EXPECT_EQ(MULTIPLE_ICONS_CHANGED, diff.diff_results); + EXPECT_TRUE(diff.before.drawsNothing()); + EXPECT_TRUE(diff.after.drawsNothing()); + } + + { + // Test case: Find first difference, when two images have had their bits + // updated (across |any| and |maskable|), should return + // ONE_OR_MORE_ICONS_CHANGED. + IconBitmaps on_disk; + IconBitmaps downloaded; + AddGeneratedIcon(&on_disk.any, icon_size::k256, SK_ColorRED); + AddGeneratedIcon(&on_disk.maskable, icon_size::k512, SK_ColorRED); + AddGeneratedIcon(&downloaded.any, icon_size::k256, SK_ColorYELLOW); + AddGeneratedIcon(&downloaded.maskable, icon_size::k512, SK_ColorYELLOW); + + IconDiff diff = HaveIconBitmapsChanged(on_disk, downloaded, + GenerateIconInfosFrom(on_disk), + GenerateIconInfosFrom(downloaded), + /* end_when_mismatch_detected= */ + true); + EXPECT_EQ(ONE_OR_MORE_ICONS_CHANGED, diff.diff_results); + // Since more than two images changed, the |before| and |after| isn't + // provided. + EXPECT_TRUE(diff.before.drawsNothing()); + EXPECT_TRUE(diff.after.drawsNothing()); + } + { + // Test case: Find all differences, when two images have had their bits + // updated (across |any| and |maskable|), should return + // MULTIPLE_ICONS_CHANGED. + IconBitmaps on_disk; + IconBitmaps downloaded; + AddGeneratedIcon(&on_disk.any, icon_size::k256, SK_ColorRED); + AddGeneratedIcon(&on_disk.maskable, icon_size::k512, SK_ColorRED); + AddGeneratedIcon(&downloaded.any, icon_size::k256, SK_ColorYELLOW); + AddGeneratedIcon(&downloaded.maskable, icon_size::k512, SK_ColorYELLOW); + + IconDiff diff = HaveIconBitmapsChanged(on_disk, downloaded, + GenerateIconInfosFrom(on_disk), + GenerateIconInfosFrom(downloaded), + /* end_when_mismatch_detected= */ + false); + EXPECT_EQ(MULTIPLE_ICONS_CHANGED, diff.diff_results); + EXPECT_TRUE(diff.before.drawsNothing()); + EXPECT_TRUE(diff.after.drawsNothing()); + } + + { + // Test case: Find first difference, when two images have had their bits + // updated (across |maskable| and |monochrome|), should return + // ONE_OR_MORE_ICON_CHANGED. + IconBitmaps on_disk; + IconBitmaps downloaded; + AddGeneratedIcon(&on_disk.maskable, icon_size::k256, SK_ColorRED); + AddGeneratedIcon(&on_disk.monochrome, icon_size::k512, SK_ColorRED); + AddGeneratedIcon(&downloaded.maskable, icon_size::k256, SK_ColorYELLOW); + AddGeneratedIcon(&downloaded.monochrome, icon_size::k512, SK_ColorYELLOW); + + IconDiff diff = HaveIconBitmapsChanged(on_disk, downloaded, + GenerateIconInfosFrom(on_disk), + GenerateIconInfosFrom(downloaded), + /* end_when_mismatch_detected= */ + true); + EXPECT_EQ(ONE_OR_MORE_ICONS_CHANGED, diff.diff_results); + // Since more than two images changed, the |before| and |after| isn't + // provided. + EXPECT_TRUE(diff.before.drawsNothing()); + EXPECT_TRUE(diff.after.drawsNothing()); + } + { + // Test case: Find all differences, when two images have had their bits + // updated (across |maskable| and |monochrome|), should return + // MULTIPLE_ICONS_CHANGED. + IconBitmaps on_disk; + IconBitmaps downloaded; + AddGeneratedIcon(&on_disk.maskable, icon_size::k256, SK_ColorRED); + AddGeneratedIcon(&on_disk.monochrome, icon_size::k512, SK_ColorRED); + AddGeneratedIcon(&downloaded.maskable, icon_size::k256, SK_ColorYELLOW); + AddGeneratedIcon(&downloaded.monochrome, icon_size::k512, SK_ColorYELLOW); + + IconDiff diff = HaveIconBitmapsChanged(on_disk, downloaded, + GenerateIconInfosFrom(on_disk), + GenerateIconInfosFrom(downloaded), + /* end_when_mismatch_detected= */ + false); + EXPECT_EQ(MULTIPLE_ICONS_CHANGED, diff.diff_results); + EXPECT_TRUE(diff.before.drawsNothing()); + EXPECT_TRUE(diff.after.drawsNothing()); + } +} + } // namespace web_app
diff --git a/chrome/browser/xsurface/BUILD.gn b/chrome/browser/xsurface/BUILD.gn index a2a5b13..15304463 100644 --- a/chrome/browser/xsurface/BUILD.gn +++ b/chrome/browser/xsurface/BUILD.gn
@@ -12,7 +12,6 @@ "android/java/src/org/chromium/chrome/browser/xsurface/HybridListRenderer.java", "android/java/src/org/chromium/chrome/browser/xsurface/ImageCacheHelper.java", "android/java/src/org/chromium/chrome/browser/xsurface/ImageFetchClient.java", - "android/java/src/org/chromium/chrome/browser/xsurface/ImagePrefetcher.java", "android/java/src/org/chromium/chrome/browser/xsurface/ListContentManager.java", "android/java/src/org/chromium/chrome/browser/xsurface/ListContentManagerObserver.java", "android/java/src/org/chromium/chrome/browser/xsurface/PersistentKeyValueCache.java",
diff --git a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/FeedActionsHandler.java b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/FeedActionsHandler.java index 1aa05e9..6dc75fa 100644 --- a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/FeedActionsHandler.java +++ b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/FeedActionsHandler.java
@@ -4,10 +4,6 @@ package org.chromium.chrome.browser.xsurface; -import android.view.View; - -import androidx.annotation.Nullable; - import java.util.Map; /** @@ -28,22 +24,6 @@ default void processThereAndBackAgainData(byte[] data) {} /** - * Sends data back to the server when content is clicked and provides the corresponding view - * through |actionSourceView| which can be null. - */ - @Deprecated - default void processThereAndBackAgainData(byte[] data, @Nullable View actionSourceView) {} - - /** - * Stores a view FeedAction for eventual upload. 'data' is a serialized FeedAction protobuf - * message. - * - * This is in the process of being removed, replaced by FeedLoggingDependencyProvider. - */ - @Deprecated - default void processViewAction(byte[] data) {} - - /** * Triggers Chrome to send user feedback for this card. */ default void sendFeedback(Map<String, String> productSpecificDataMap) {}
diff --git a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/ImagePrefetcher.java b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/ImagePrefetcher.java deleted file mode 100644 index ba891d3a..0000000 --- a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/ImagePrefetcher.java +++ /dev/null
@@ -1,16 +0,0 @@ -// Copyright 2020 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -package org.chromium.chrome.browser.xsurface; - -// TODO(freedjm): Remove ImagePrefetcher after internal changes -// land for ImageCacheHelper. - -/** - * Interface to prefetch an image and cache it on disk. This - * allows native code to call to the image loader across the - * xsurface. - */ -@Deprecated -public interface ImagePrefetcher extends ImageCacheHelper {}
diff --git a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/ProcessScope.java b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/ProcessScope.java index 88602d08..965d5a7 100644 --- a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/ProcessScope.java +++ b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/ProcessScope.java
@@ -4,7 +4,6 @@ package org.chromium.chrome.browser.xsurface; -import android.content.Context; import androidx.annotation.Nullable; /** @@ -26,23 +25,12 @@ **/ @Nullable default SurfaceScope obtainSurfaceScope(SurfaceScopeDependencyProvider dependencyProvider) { - return obtainSurfaceScope(dependencyProvider.getActivityContext()); - } - - @Nullable - @Deprecated - default SurfaceScope obtainSurfaceScope(Context activityContext) { - return null; - } - - @Nullable - default ImagePrefetcher provideImagePrefetcher() { return null; } @Nullable default ImageCacheHelper provideImageCacheHelper() { - return provideImagePrefetcher(); + return null; } @Nullable
diff --git a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/SurfaceActionsHandler.java b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/SurfaceActionsHandler.java index 02fe7d2..c776472 100644 --- a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/SurfaceActionsHandler.java +++ b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/SurfaceActionsHandler.java
@@ -18,10 +18,6 @@ * @param actionSourceView The View from which the user tap originated. May be null. */ default void navigateTab(String url, View actionSourceView) {} - @Deprecated - default void navigateTab(String url) { - navigateTab(url, null); - } /** * Navigates a new tab to a particular URL. @@ -29,10 +25,6 @@ * @param actionSourceView The View from which the user tap originated. May be null. */ default void navigateNewTab(String url, View actionSourceView) {} - @Deprecated - default void navigateNewTab(String url) { - navigateNewTab(url, null); - } /** * Navigate a new incognito tab to a URL. @@ -53,10 +45,6 @@ * @param actionSourceView The View from which the user tap originated. May be null. */ default void showBottomSheet(View view, View actionSourceView) {} - @Deprecated - default void showBottomSheet(View view) { - showBottomSheet(view, null); - } /** * Dismiss the open bottom sheet (or do nothing if there isn't one).
diff --git a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/SurfaceScopeDependencyProvider.java b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/SurfaceScopeDependencyProvider.java index c376d35..57116018 100644 --- a/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/SurfaceScopeDependencyProvider.java +++ b/chrome/browser/xsurface/android/java/src/org/chromium/chrome/browser/xsurface/SurfaceScopeDependencyProvider.java
@@ -48,31 +48,6 @@ return AutoplayPreference.AUTOPLAY_DISABLED; } - /** Events that are triggered during the video auto-play. */ - @Deprecated - public enum AutoplayEvent { - /** - * Auto-play is triggered, but not started yet. This occurs when the video card becomes - * fully visible. - */ - AUTOPLAY_REQUESTED, - /** The player starts to auto-play the video. */ - AUTOPLAY_STARTED, - /** - * Auto-play stops before reaching the end. This occurs when the video card becomes - * partially visible or invisible. - */ - AUTOPLAY_STOPPED, - /** Auto-play reaches the end. */ - AUTOPLAY_ENDED, - /** User clicks on the auto-play video. */ - AUTOPLAY_CLICKED, - } - - /** Reports the event related to video auto-play. */ - @Deprecated - default void reportAutoplayEvent(AutoplayEvent event) {} - /** Events that are triggered during the video playing. */ public @interface VideoPlayEvent { // Events applying muted autoplay only.
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt index 3399956c..24e33fa 100644 --- a/chrome/build/win32.pgo.txt +++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@ -chrome-win32-main-1634039987-c14b3cf6766e27af9b66f7fb02d8bd017252919c.profdata +chrome-win32-main-1634050758-81ac571898085b700004c0e280809306718f9da2.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt index f8b0d084..0bd63ad 100644 --- a/chrome/build/win64.pgo.txt +++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@ -chrome-win64-main-1634039987-cd0af9f9b0d85eae30a1fb4a0ddd84ccd1a74ee5.profdata +chrome-win64-main-1634050758-7b5caff70f9b52b0f1ba9a90b5545e65e5dac729.profdata
diff --git a/chrome/chrome_paks.gni b/chrome/chrome_paks.gni index 0d34dbed..317cb0e2 100644 --- a/chrome/chrome_paks.gni +++ b/chrome/chrome_paks.gni
@@ -138,6 +138,7 @@ "$root_gen_dir/chrome/dev_ui_resources.pak", "$root_gen_dir/chrome/download_shelf_resources.pak", "$root_gen_dir/chrome/downloads_resources.pak", + "$root_gen_dir/chrome/enterprise_casting_resources.pak", "$root_gen_dir/chrome/feedback_resources.pak", "$root_gen_dir/chrome/gaia_auth_host_resources.pak", "$root_gen_dir/chrome/history_resources.pak", @@ -165,6 +166,7 @@ "//chrome/browser/resources/commander:resources", "//chrome/browser/resources/download_shelf:resources", "//chrome/browser/resources/downloads:resources", + "//chrome/browser/resources/enterprise_casting:resources", "//chrome/browser/resources/feedback_webui:resources", "//chrome/browser/resources/gaia_auth_host:resources", "//chrome/browser/resources/history:resources", @@ -211,7 +213,6 @@ "$root_gen_dir/chrome/browser/supervised_user/supervised_user_unscaled_resources.pak", "$root_gen_dir/chrome/common/chromeos/extensions/chromeos_system_extensions_resources.pak", "$root_gen_dir/chrome/emoji_picker_resources.pak", - "$root_gen_dir/chrome/enterprise_casting_resources.pak", "$root_gen_dir/chrome/internet_config_dialog_resources.pak", "$root_gen_dir/chrome/internet_detail_dialog_resources.pak", "$root_gen_dir/chrome/launcher_internals_resources.pak", @@ -260,7 +261,6 @@ "//chrome/browser/resources/chromeos:multidevice_setup_resources", "//chrome/browser/resources/chromeos/audio:resources", "//chrome/browser/resources/chromeos/emoji_picker:resources", - "//chrome/browser/resources/chromeos/enterprise_casting:resources", "//chrome/browser/resources/chromeos/launcher_internals:resources", "//chrome/browser/resources/chromeos/login:conditional_resources", "//chrome/browser/resources/chromeos/login:unconditional_resources",
diff --git a/chrome/common/webui_url_constants.cc b/chrome/common/webui_url_constants.cc index 0b9030b..464ec62 100644 --- a/chrome/common/webui_url_constants.cc +++ b/chrome/common/webui_url_constants.cc
@@ -560,8 +560,8 @@ kChromeUIWebAppInternalsHost, #endif content::kChromeUIAppCacheInternalsHost, + content::kChromeUIAttributionInternalsHost, content::kChromeUIBlobInternalsHost, - content::kChromeUIConversionInternalsHost, content::kChromeUIDinoHost, content::kChromeUIGpuHost, content::kChromeUIHistogramHost,
diff --git a/chrome/installer/gcapi_mac/gcapi.mm b/chrome/installer/gcapi_mac/gcapi.mm index 0d6cc4e..d67b1fa 100644 --- a/chrome/installer/gcapi_mac/gcapi.mm +++ b/chrome/installer/gcapi_mac/gcapi.mm
@@ -429,9 +429,8 @@ isbrandchar(brand_code[1]) && isbrandchar(brand_code[2]) && isbrandchar(brand_code[3]); - NSString* brand_path = nil; if (valid_brand_code) - brand_path = WriteBrandCode(brand_code, user); + WriteBrandCode(brand_code, user); // Write master prefs. if (master_prefs_contents)
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index ea47e3e..d10eabea 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -7606,10 +7606,8 @@ "../browser/ui/views/frame/test_with_browser_view.cc", "../browser/ui/views/frame/test_with_browser_view.h", "../browser/ui/views/frame/web_contents_close_handler_unittest.cc", - "../browser/ui/views/global_media_controls/media_notification_container_impl_view_unittest.cc", - "../browser/ui/views/global_media_controls/media_notification_device_selector_view_unittest.cc", - "../browser/ui/views/global_media_controls/media_notification_footer_view_unittest.cc", - "../browser/ui/views/global_media_controls/media_notification_list_view_unittest.cc", + "../browser/ui/views/global_media_controls/media_item_ui_device_selector_view_unittest.cc", + "../browser/ui/views/global_media_controls/media_item_ui_footer_view_unittest.cc", "../browser/ui/views/hover_button_unittest.cc", "../browser/ui/views/infobars/infobar_view_unittest.cc", "../browser/ui/views/intent_picker_bubble_view_unittest.cc",
diff --git a/chrome/test/DEPS b/chrome/test/DEPS index 3c43330..2ad359a 100644 --- a/chrome/test/DEPS +++ b/chrome/test/DEPS
@@ -23,6 +23,7 @@ "+components/feature_engagement", "+components/find_in_page", "+components/gcm_driver/instance_id", + "+components/global_media_controls", "+components/google/core/common", "+components/guest_view/browser", "+components/history/content",
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/WPRArchiveDirectory.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/WPRArchiveDirectory.java index d82e6f0..540a7481e 100644 --- a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/WPRArchiveDirectory.java +++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/WPRArchiveDirectory.java
@@ -34,10 +34,35 @@ * During gClient runhooks, the files in /path_of_file_foo and /path_of_file_bar * are downloaded from GCS. Once the files are downloaded, it will be used in * tests as isolated. + * + * Optionally, a test may additionally be annotated with ArchiveName. This allows multiple tests + * to share the same archive. This is possible when a single test exercises the same network + * requests needed by other tests. + * + * For example, these two tests use the same WPR file. You can record running testA, and then replay + * on both testA and testB. + * + * @Feature("WPRRecordReplayTest") + * @WPRArchiveDirectory("/path_of_file_foo") + * @WPRArchiveDirectory.ArchiveName("shared.wprgo") + * public void test_A() { + * ... + * } + * + * @Feature("WPRRecordReplayTest") + * @WPRArchiveDirectory("/path_of_file_foo") + * @WPRArchiveDirectory.ArchiveName("shared.wprgo") + * public void test_B() { + * } */ @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface WPRArchiveDirectory { + @Retention(RetentionPolicy.RUNTIME) + public @interface ArchiveName { + String[] value(); + } + /** * @return one WPRArchiveDirectory. */
diff --git a/chrome/test/data/banners/128x128-green.png b/chrome/test/data/banners/128x128-green.png new file mode 100644 index 0000000..5349063 --- /dev/null +++ b/chrome/test/data/banners/128x128-green.png Binary files differ
diff --git a/chrome/test/data/banners/128x128-red.png b/chrome/test/data/banners/128x128-red.png new file mode 100644 index 0000000..485144e9 --- /dev/null +++ b/chrome/test/data/banners/128x128-red.png Binary files differ
diff --git a/chrome/test/data/banners/256x256-green.png b/chrome/test/data/banners/256x256-green.png new file mode 100644 index 0000000..b644451 --- /dev/null +++ b/chrome/test/data/banners/256x256-green.png Binary files differ
diff --git a/chrome/test/data/banners/256x256-red.png b/chrome/test/data/banners/256x256-red.png new file mode 100644 index 0000000..db9c0c2 --- /dev/null +++ b/chrome/test/data/banners/256x256-red.png Binary files differ
diff --git a/chrome/test/data/banners/512x512-green.png b/chrome/test/data/banners/512x512-green.png new file mode 100644 index 0000000..5ebfbe0 --- /dev/null +++ b/chrome/test/data/banners/512x512-green.png Binary files differ
diff --git a/chrome/test/data/banners/512x512-red.png b/chrome/test/data/banners/512x512-red.png new file mode 100644 index 0000000..4f000b3 --- /dev/null +++ b/chrome/test/data/banners/512x512-red.png Binary files differ
diff --git a/chrome/test/data/webui/chromeos/personalization_app/test_mojo_interface_provider.js b/chrome/test/data/webui/chromeos/personalization_app/test_mojo_interface_provider.js index 39372ae..ee75634 100644 --- a/chrome/test/data/webui/chromeos/personalization_app/test_mojo_interface_provider.js +++ b/chrome/test/data/webui/chromeos/personalization_app/test_mojo_interface_provider.js
@@ -22,6 +22,9 @@ 'setDailyRefreshCollectionId', 'getDailyRefreshCollectionId', 'updateDailyRefreshWallpaper', + 'isInTabletMode', + 'confirmPreviewWallpaper', + 'cancelPreviewWallpaper', ]); /** @@ -91,6 +94,9 @@ this.updateDailyRefreshWallpaperResponse = true; /** @public */ + this.isInTabletModeResponse = true; + + /** @public */ this.wallpaperObserverUpdateTimeout = 0; /** @@ -185,6 +191,21 @@ return Promise.resolve({success: this.updateDailyRefreshWallpaperResponse}); } + isInTabletMode() { + this.methodCalled('isInTabletMode'); + return Promise.resolve({tabletMode: this.isInTabletModeResponse}); + } + + /** @override */ + confirmPreviewWallpaper() { + this.methodCalled('confirmPreviewWallpaper'); + } + + /** @override */ + cancelPreviewWallpaper() { + this.methodCalled('cancelPreviewWallpaper'); + } + /** * @param {!Array<!chromeos.personalizationApp.mojom.WallpaperCollection>} * collections
diff --git a/chrome/test/data/webui/chromeos/personalization_app/wallpaper_fullscreen_element_test.js b/chrome/test/data/webui/chromeos/personalization_app/wallpaper_fullscreen_element_test.js index 6738d63..54e55d7 100644 --- a/chrome/test/data/webui/chromeos/personalization_app/wallpaper_fullscreen_element_test.js +++ b/chrome/test/data/webui/chromeos/personalization_app/wallpaper_fullscreen_element_test.js
@@ -230,4 +230,28 @@ await wallpaperProvider.whenCalled('updateDailyRefreshWallpaper'); }); + + test('clicking set as wallpaper confirms wallpaper', async () => { + wallpaperFullscreenElement = initElement(WallpaperFullscreen.is); + const {requestFullscreenPromise} = mockFullscreenApis(); + await waitAfterNextRender(wallpaperFullscreenElement); + + personalizationStore.data.fullscreen = true; + personalizationStore.data.currentSelected = { + ...personalizationStore.data.currentSelected, + type: chromeos.personalizationApp.mojom.WallpaperType.kDaily, + }; + personalizationStore.data.dailyRefresh.collectionId = + wallpaperProvider.collections[0].id; + personalizationStore.data.pendingSelected = wallpaperProvider.images[1]; + personalizationStore.notifyObservers(); + + await waitAfterNextRender(wallpaperFullscreenElement); + + const setAsWallpaperButton = + wallpaperFullscreenElement.shadowRoot.getElementById('confirm'); + setAsWallpaperButton.click(); + + await wallpaperProvider.whenCalled('confirmPreviewWallpaper'); + }); }
diff --git a/chrome/test/data/webui/chromeos/scanning/scan_preview_test.js b/chrome/test/data/webui/chromeos/scanning/scan_preview_test.js index 11261ad..a2941f9 100644 --- a/chrome/test/data/webui/chromeos/scanning/scan_preview_test.js +++ b/chrome/test/data/webui/chromeos/scanning/scan_preview_test.js
@@ -319,7 +319,7 @@ .then(() => { imageHeight = scanPreview.$$('#scannedImages') .getElementsByClassName('scanned-image')[0] - .height; + .offsetHeight; // With two scanned images the viewport should be scrolled so the // second image is at the top.
diff --git a/chrome/test/data/webui/print_preview/destination_search_test.js b/chrome/test/data/webui/print_preview/destination_search_test.js index 5abb246..6a7205a 100644 --- a/chrome/test/data/webui/print_preview/destination_search_test.js +++ b/chrome/test/data/webui/print_preview/destination_search_test.js
@@ -78,7 +78,8 @@ // Get print list and fire event. const list = dialog.shadowRoot.querySelector('print-preview-destination-list'); - list.fire('destination-selected', item); + list.dispatchEvent(new CustomEvent( + 'destination-selected', {bubbles: true, composed: true, detail: item})); } /**
diff --git a/chrome/test/data/webui/print_preview/destination_search_test_chromeos.js b/chrome/test/data/webui/print_preview/destination_search_test_chromeos.js index ae73beb..0dc34f9 100644 --- a/chrome/test/data/webui/print_preview/destination_search_test_chromeos.js +++ b/chrome/test/data/webui/print_preview/destination_search_test_chromeos.js
@@ -87,7 +87,8 @@ // Get print list and fire event. const list = dialog.shadowRoot.querySelector('print-preview-destination-list'); - list.fire('destination-selected', item); + list.dispatchEvent(new CustomEvent( + 'destination-selected', {bubbles: true, composed: true, detail: item})); } /**
diff --git a/chrome/test/data/webui/print_preview/destination_settings_test.js b/chrome/test/data/webui/print_preview/destination_settings_test.js index b4d5bc1..1189ec7 100644 --- a/chrome/test/data/webui/print_preview/destination_settings_test.js +++ b/chrome/test/data/webui/print_preview/destination_settings_test.js
@@ -511,7 +511,9 @@ const whenDestinationSelect = eventToPromise( DestinationStoreEventType.DESTINATION_SELECT, destinationSettings.getDestinationStoreForTest()); - dropdown.fire('selected-option-change', 'Save as PDF/local/'); + dropdown.dispatchEvent(new CustomEvent( + 'selected-option-change', + {bubbles: true, composed: true, detail: 'Save as PDF/local/'})); // Ensure this fires the destination select event. return whenDestinationSelect; @@ -573,7 +575,11 @@ const whenDestinationSelect = eventToPromise( DestinationStoreEventType.DESTINATION_SELECT, destinationSettings.getDestinationStoreForTest()); - dropdown.fire('selected-option-change', driveDestinationKey); + dropdown.dispatchEvent(new CustomEvent('selected-option-change', { + bubbles: true, + composed: true, + detail: driveDestinationKey, + })); return whenDestinationSelect; }) .then(() => { @@ -623,8 +629,11 @@ const whenDestinationSelect = eventToPromise( DestinationStoreEventType.DESTINATION_SELECT, destinationSettings.getDestinationStoreForTest()); - dropdown.fire( - 'selected-option-change', makeLocalDestinationKey('ID2')); + dropdown.dispatchEvent(new CustomEvent('selected-option-change', { + bubbles: true, + composed: true, + detail: makeLocalDestinationKey('ID2'), + })); return whenDestinationSelect; }) .then(() => { @@ -662,7 +671,9 @@ } assertDropdownItems(dropdownItems); - dropdown.fire('selected-option-change', 'seeMore'); + dropdown.dispatchEvent(new CustomEvent( + 'selected-option-change', + {bubbles: true, composed: true, detail: 'seeMore'})); return waitBeforeNextRender(destinationSettings); }) .then(() => { @@ -732,7 +743,9 @@ } assertDropdownItems(dropdownItems); - dropdown.fire('selected-option-change', 'seeMore'); + dropdown.dispatchEvent(new CustomEvent( + 'selected-option-change', + {bubbles: true, composed: true, detail: 'seeMore'})); return waitBeforeNextRender(destinationSettings); }) .then(() => { @@ -746,7 +759,9 @@ DestinationStoreEventType.DESTINATIONS_INSERTED, destinationSettings.getDestinationStoreForTest()); // Simulate setting a new account. - dialog.fire('account-change', account2); + dialog.dispatchEvent(new CustomEvent( + 'account-change', + {bubbles: true, composed: true, detail: account2})); flush(); return whenAdded; }) @@ -825,6 +840,8 @@ nativeLayer.resetResolver('getPrinterCapabilities'); destinationSettings.shadowRoot.querySelector('#destinationSelect') .dispatchEvent(new CustomEvent('selected-option-change', { + bubbles: true, + composed: true, detail: 'Save as PDF/local/', })); flush();
diff --git a/chrome/test/data/webui/print_preview/destination_settings_test_cros.js b/chrome/test/data/webui/print_preview/destination_settings_test_cros.js index 3b751f9a..ad8a40f 100644 --- a/chrome/test/data/webui/print_preview/destination_settings_test_cros.js +++ b/chrome/test/data/webui/print_preview/destination_settings_test_cros.js
@@ -174,7 +174,11 @@ // we don't try to fetch the license again. nativeLayer.resetResolver('getPrinterCapabilities'); destinationSettings.shadowRoot.querySelector('#destinationSelect') - .fire('selected-option-change', 'ID1/chrome_os/'); + .dispatchEvent(new CustomEvent('selected-option-change', { + bubbles: true, + composed: true, + detail: 'ID1/chrome_os/', + })); }) .then(() => { assertEquals(
diff --git a/chrome/test/enterprise/e2e/policy/password_manager_enabled/password_manager_enabled_webdriver_test.py b/chrome/test/enterprise/e2e/policy/password_manager_enabled/password_manager_enabled_webdriver_test.py index e595467..0f35055 100644 --- a/chrome/test/enterprise/e2e/policy/password_manager_enabled/password_manager_enabled_webdriver_test.py +++ b/chrome/test/enterprise/e2e/policy/password_manager_enabled/password_manager_enabled_webdriver_test.py
@@ -6,16 +6,13 @@ from absl import app -def getShadowDom(driver, root, selector): - el = root.find_element_by_css_selector(selector) - return driver.execute_script("return arguments[0].shadowRoot", el) - - -def getNestedShadowDom(driver, selectors): - el = driver - for selector in selectors: - el = getShadowDom(driver, el, selector) - return el +def getElementFromShadowRoot(driver, element, selector): + if element is None: + return None + else: + return driver.execute_script( + "return arguments[0].shadowRoot.querySelector(arguments[1])", element, + selector) def main(argv): @@ -23,12 +20,16 @@ driver.get("chrome://settings/passwords") # The settings is nested within multiple shadow doms - extract it. - el = getNestedShadowDom(driver, [ - "settings-ui", "settings-main", "settings-basic-page", - "settings-autofill-page", "passwords-section", "#passwordToggle" - ]) + selectors = [ + "settings-main", "settings-basic-page", "settings-autofill-page", + "passwords-section", "#passwordToggle", "cr-toggle" + ] - if el.find_element_by_css_selector("cr-toggle").get_attribute("checked"): + el = driver.find_element_by_css_selector("settings-ui") + for selector in selectors: + el = getElementFromShadowRoot(driver, el, selector) + + if el.get_attribute("checked"): print("TRUE") else: print("FALSE")
diff --git a/chrome/test/media_router/BUILD.gn b/chrome/test/media_router/BUILD.gn index acca219..4f958ed 100644 --- a/chrome/test/media_router/BUILD.gn +++ b/chrome/test/media_router/BUILD.gn
@@ -36,6 +36,7 @@ "//chrome/common", "//chrome/test:test_support", "//chrome/test:test_support_ui", + "//components/global_media_controls", "//components/media_router/common", "//components/policy/core/browser", "//components/policy/core/common:test_support",
diff --git a/chrome/test/media_router/media_router_ui_for_test.cc b/chrome/test/media_router/media_router_ui_for_test.cc index 2dfd051..703412f 100644 --- a/chrome/test/media_router/media_router_ui_for_test.cc +++ b/chrome/test/media_router/media_router_ui_for_test.cc
@@ -11,11 +11,11 @@ #include "chrome/browser/ui/media_router/media_router_file_dialog.h" #include "chrome/browser/ui/media_router/media_router_ui.h" #include "chrome/browser/ui/views/global_media_controls/media_dialog_view.h" -#include "chrome/browser/ui/views/global_media_controls/media_notification_container_impl_view.h" -#include "chrome/browser/ui/views/global_media_controls/media_notification_device_selector_view.h" +#include "chrome/browser/ui/views/global_media_controls/media_item_ui_device_selector_view.h" #include "chrome/browser/ui/views/media_router/cast_dialog_sink_button.h" #include "chrome/browser/ui/views/media_router/cast_dialog_view.h" #include "chrome/browser/ui/views/media_router/media_router_dialog_controller_views.h" +#include "components/global_media_controls/public/views/media_item_ui_view.h" #include "components/media_router/browser/media_router_factory.h" #include "components/media_router/browser/media_routes_observer.h" #include "ui/events/base_event_utils.h" @@ -398,11 +398,11 @@ CastDialogSinkButton* MediaRouterUiForTest::GetSinkButtonFromGMCDialog( const std::string& sink_name) const { - auto notifications = - MediaDialogView::GetDialogViewForTesting()->GetNotificationsForTesting(); - MediaNotificationContainerImplView* view = notifications.begin()->second; - auto sink_buttons = - view->device_selector_view_for_testing()->GetCastSinkButtonsForTesting(); + auto items = MediaDialogView::GetDialogViewForTesting()->GetItemsForTesting(); + global_media_controls::MediaItemUIView* view = items.begin()->second; + auto* device_selector = static_cast<MediaItemUIDeviceSelectorView*>( + view->device_selector_view_for_testing()); + auto sink_buttons = device_selector->GetCastSinkButtonsForTesting(); return GetSinkButtonWithName(sink_buttons, sink_name); }
diff --git a/chrome/updater/win/ui/owner_draw_controls.h b/chrome/updater/win/ui/owner_draw_controls.h index b0f58b1..cd36992 100644 --- a/chrome/updater/win/ui/owner_draw_controls.h +++ b/chrome/updater/win/ui/owner_draw_controls.h
@@ -12,9 +12,13 @@ // These headers must be included after base/win/atl.h. #include "./atlapp.h" +#include "./atltypes.h" + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-but-set-variable" #include "./atlctrls.h" #include "./atlframe.h" -#include "./atltypes.h" +#pragma clang diagnostic pop namespace updater { namespace ui {
diff --git a/chromeos/chromeos_strings.grd b/chromeos/chromeos_strings.grd index 6da82220..5500cf9 100644 --- a/chromeos/chromeos_strings.grd +++ b/chromeos/chromeos_strings.grd
@@ -1023,46 +1023,46 @@ Internet Connectivity </message> <message name="IDS_DIAGNOSTICS_LAN_CONNECTIVITY_FAILED_TEXT" desc="The text that displays when the `Lan Connectivity` test fails."> - Unable to contact gateway + Can't contact gateway </message> <message name="IDS_DIAGNOSTICS_GATEWAY_CAN_BE_PINGED_FAILED_TEXT" desc="The text that displays when the `Gateway can be pinged` test fails."> - Unable to contact gateway + Can't contact gateway </message> <message name="IDS_DIAGNOSTICS_DNS_RESOLVER_PRESENT_FAILED_TEXT" desc="The text that displays when the `DNS resolver present` test fails."> - No DNS servers are configured + No DNS servers are set up </message> <message name="IDS_DIAGNOSTICS_DNS_RESOLUTION_FAILED_TEXT" desc="The text that displays when the `DNS resolution` test fails."> - Unable to resolve DNS + Can't resolve DNS </message> <message name="IDS_DIAGNOSTICS_DNS_LATENCY_FAILED_TEXT" desc="The text that displays when the `DNS latency` test fails."> DNS resolution has high latency </message> <message name="IDS_DIAGNOSTICS_SIGNAL_STRENGTH_FAILED_TEXT" desc="The text that displays when the `Signal strength` test fails."> - Low signal strength, try to move closer to the access point + Weak signal strength. Try moving closer to the Wi-Fi signal source. </message> <message name="IDS_DIAGNOSTICS_CAPTIVE_PORTAL_FAILED_TEXT" desc="The text that displays when the `Captive portal` test fails."> This network may have a captive portal </message> <message name="IDS_DIAGNOSTICS_HAS_SECURE_WIFI_CONNECTION_FAILED_TEXT" desc="The text that displays when the `Has secure Wi-Fi connection` test fails."> - You are using an open network + You are using an open and unsecure network </message> <message name="IDS_DIAGNOSTICS_HTTPS_FIREWALL_FAILED_TEXT" desc="The text that displays when the `HTTPS firewall` test fails."> - Unable to connect through firewall to HTTPS (port 443) websites + Can't connect through firewall to HTTPS websites </message> <message name="IDS_DIAGNOSTICS_HTTP_FIREWALL_FAILED_TEXT" desc="The text that displays when the `HTTP firewall` test fails."> - Unable to connect through firewall to HTTP (port 80) websites + Can't connect through firewall to HTTP websites </message> <message name="IDS_DIAGNOSTICS_HTTPS_LATENCY_FAILED_TEXT" desc="The text that displays when the `HTTPS latency` test fails."> - High latency to HTTPS (port 443) websites + High latency to HTTPS websites </message> <message name="IDS_DIAGNOSTICS_ARC_PING_FAILED_TEXT" desc="The text that displays when the `ARC ping` test fails."> - Unable to contact the gateway from Android + Can't contact the gateway from Android apps </message> <message name="IDS_DIAGNOSTICS_ARC_HTTP_FAILED_TEXT" desc="The text that displays when the `ARC HTTP` test fails."> - Unable to connect through firewall to HTTP (port 80) websites from Android + Can't connect through firewall to HTTP websites from Android apps </message> <message name="IDS_DIAGNOSTICS_ARC_DNS_RESOLUTION_FAILED_TEXT" desc="The text that displays when the `ARC DNS resolution` test fails."> - Unable to resolve DNS from Android + Can't resolve DNS from Android apps </message> <message name="IDS_NETWORK_DIAGNOSTICS_NO_IP_ADDRESS_TEXT" desc="The text shown when a network's IP Address is missing."> Unable to obtain IP address @@ -1923,6 +1923,9 @@ <message name="IDS_PERSONALIZATION_APP_EXIT_FULL_SCREEN" desc="Label for the button to exit full screen wallpaper viewing mode"> Exit full screen </message> + <message name="IDS_PERSONALIZATION_APP_SET_AS_WALLPAPER" desc="Label for the button to confirm preview wallpaper"> + Set as wallpaper + </message> <!-- Traffic Counters UI --> <message name="IDS_TRAFFIC_COUNTERS_UNKNOWN" desc="Traffic counters related to an unknown source">
diff --git a/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_ARC_DNS_RESOLUTION_FAILED_TEXT.png.sha1 b/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_ARC_DNS_RESOLUTION_FAILED_TEXT.png.sha1 index 8b9d67b..ac8b3a3 100644 --- a/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_ARC_DNS_RESOLUTION_FAILED_TEXT.png.sha1 +++ b/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_ARC_DNS_RESOLUTION_FAILED_TEXT.png.sha1
@@ -1 +1 @@ -7bb65eaa8ea38ba6131d9d3980e06fa0bf4e0eb4 \ No newline at end of file +1ada6db43c4aecf4aba3f65941f0b6fc5901f720 \ No newline at end of file
diff --git a/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_ARC_HTTP_FAILED_TEXT.png.sha1 b/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_ARC_HTTP_FAILED_TEXT.png.sha1 index 40ba73d..bd33642 100644 --- a/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_ARC_HTTP_FAILED_TEXT.png.sha1 +++ b/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_ARC_HTTP_FAILED_TEXT.png.sha1
@@ -1 +1 @@ -2bbefb9d8b033575bb8a84982733383631bbbd57 \ No newline at end of file +3b303bd73c9e382cea22ab08d1c185ef08e47d75 \ No newline at end of file
diff --git a/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_ARC_PING_FAILED_TEXT.png.sha1 b/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_ARC_PING_FAILED_TEXT.png.sha1 index 61e6d8b..731eda72 100644 --- a/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_ARC_PING_FAILED_TEXT.png.sha1 +++ b/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_ARC_PING_FAILED_TEXT.png.sha1
@@ -1 +1 @@ -6c5019b0529347c90e9ace3649ad86bc3510b843 \ No newline at end of file +884d0a78e4c2e20fb206934be7b307877b224551 \ No newline at end of file
diff --git a/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_DNS_RESOLUTION_FAILED_TEXT.png.sha1 b/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_DNS_RESOLUTION_FAILED_TEXT.png.sha1 index c4ef45a..83966c2 100644 --- a/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_DNS_RESOLUTION_FAILED_TEXT.png.sha1 +++ b/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_DNS_RESOLUTION_FAILED_TEXT.png.sha1
@@ -1 +1 @@ -eb6ffd35cb8be983c9231b7e062b8b7139fad2ee \ No newline at end of file +9172ee5aa0bd6a0f5300042e3ab75e6e34d92b18 \ No newline at end of file
diff --git a/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_DNS_RESOLVER_PRESENT_FAILED_TEXT.png.sha1 b/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_DNS_RESOLVER_PRESENT_FAILED_TEXT.png.sha1 index cb8dfde..e698a109 100644 --- a/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_DNS_RESOLVER_PRESENT_FAILED_TEXT.png.sha1 +++ b/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_DNS_RESOLVER_PRESENT_FAILED_TEXT.png.sha1
@@ -1 +1 @@ -79fdcc6c2315e3394c8d8b147ba6e82e77227c1b \ No newline at end of file +a2fa3d77bf1b6e08329b183b769cf9135eb8f7b2 \ No newline at end of file
diff --git a/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_GATEWAY_CAN_BE_PINGED_FAILED_TEXT.png.sha1 b/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_GATEWAY_CAN_BE_PINGED_FAILED_TEXT.png.sha1 index c0d4134..24d30a1 100644 --- a/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_GATEWAY_CAN_BE_PINGED_FAILED_TEXT.png.sha1 +++ b/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_GATEWAY_CAN_BE_PINGED_FAILED_TEXT.png.sha1
@@ -1 +1 @@ -f4fef44d10afa66d7214d9a286ddcd72c15e13eb \ No newline at end of file +d9985f2073af286e4ba1b451c682ada6a70dfd21 \ No newline at end of file
diff --git a/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_HAS_SECURE_WIFI_CONNECTION_FAILED_TEXT.png.sha1 b/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_HAS_SECURE_WIFI_CONNECTION_FAILED_TEXT.png.sha1 index 2600092..110d5a5 100644 --- a/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_HAS_SECURE_WIFI_CONNECTION_FAILED_TEXT.png.sha1 +++ b/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_HAS_SECURE_WIFI_CONNECTION_FAILED_TEXT.png.sha1
@@ -1 +1 @@ -55c3da60ed0cb81633c84ee1f6a0047364a6093d \ No newline at end of file +3fdc8a66d978f69072b870bc44df20c8ce68051c \ No newline at end of file
diff --git a/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_HTTPS_FIREWALL_FAILED_TEXT.png.sha1 b/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_HTTPS_FIREWALL_FAILED_TEXT.png.sha1 index 9fe9526..49f5ad7 100644 --- a/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_HTTPS_FIREWALL_FAILED_TEXT.png.sha1 +++ b/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_HTTPS_FIREWALL_FAILED_TEXT.png.sha1
@@ -1 +1 @@ -47532716b423ffec66dee80be5205957d0d403a5 \ No newline at end of file +8b6a850c70374699c92bda21faaad5677b641927 \ No newline at end of file
diff --git a/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_HTTPS_LATENCY_FAILED_TEXT.png.sha1 b/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_HTTPS_LATENCY_FAILED_TEXT.png.sha1 index ce378b02..53f13e5a 100644 --- a/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_HTTPS_LATENCY_FAILED_TEXT.png.sha1 +++ b/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_HTTPS_LATENCY_FAILED_TEXT.png.sha1
@@ -1 +1 @@ -232487eb4c41b74daab53fde68d7f7b25c2c0b96 \ No newline at end of file +1124ef4e42d694cb0387c35c35f8c68637e7607c \ No newline at end of file
diff --git a/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_HTTP_FIREWALL_FAILED_TEXT.png.sha1 b/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_HTTP_FIREWALL_FAILED_TEXT.png.sha1 index a858c14..75e1a4d 100644 --- a/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_HTTP_FIREWALL_FAILED_TEXT.png.sha1 +++ b/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_HTTP_FIREWALL_FAILED_TEXT.png.sha1
@@ -1 +1 @@ -42611eb90005186fd943a8da6e8be4784c863397 \ No newline at end of file +002b0142bf4bd29d7ecefd23b7ad94c83331955a \ No newline at end of file
diff --git a/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_LAN_CONNECTIVITY_FAILED_TEXT.png.sha1 b/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_LAN_CONNECTIVITY_FAILED_TEXT.png.sha1 index c0d4134..572615ee 100644 --- a/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_LAN_CONNECTIVITY_FAILED_TEXT.png.sha1 +++ b/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_LAN_CONNECTIVITY_FAILED_TEXT.png.sha1
@@ -1 +1 @@ -f4fef44d10afa66d7214d9a286ddcd72c15e13eb \ No newline at end of file +837f0728b7ceb3202a96238bb770cbcfae6550ba \ No newline at end of file
diff --git a/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_SIGNAL_STRENGTH_FAILED_TEXT.png.sha1 b/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_SIGNAL_STRENGTH_FAILED_TEXT.png.sha1 index 3ef3dac..086a44c4 100644 --- a/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_SIGNAL_STRENGTH_FAILED_TEXT.png.sha1 +++ b/chromeos/chromeos_strings_grd/IDS_DIAGNOSTICS_SIGNAL_STRENGTH_FAILED_TEXT.png.sha1
@@ -1 +1 @@ -cd9e258baa0f8860254f0afedbc322604108f412 \ No newline at end of file +f387549e63e6a1e9801fa51933a42aebf4da878e \ No newline at end of file
diff --git a/chromeos/chromeos_strings_grd/IDS_PERSONALIZATION_APP_SET_AS_WALLPAPER.png.sha1 b/chromeos/chromeos_strings_grd/IDS_PERSONALIZATION_APP_SET_AS_WALLPAPER.png.sha1 new file mode 100644 index 0000000..ab1c389 --- /dev/null +++ b/chromeos/chromeos_strings_grd/IDS_PERSONALIZATION_APP_SET_AS_WALLPAPER.png.sha1
@@ -0,0 +1 @@ +ffdbe04ef88d7a80b2048700d752077c1af387e8 \ No newline at end of file
diff --git a/chromeos/components/personalization_app/mojom/personalization_app.mojom b/chromeos/components/personalization_app/mojom/personalization_app.mojom index 6820688..d704975 100644 --- a/chromeos/components/personalization_app/mojom/personalization_app.mojom +++ b/chromeos/components/personalization_app/mojom/personalization_app.mojom
@@ -121,11 +121,13 @@ SetWallpaperObserver(pending_remote<WallpaperObserver> observer); // Sets the given backdrop wallpaper as the user's background. - SelectWallpaper(uint64 image_asset_id) => (bool success); + SelectWallpaper(uint64 image_asset_id, bool preview_mode) => + (bool success); // Sets the given local wallpaper as the user's background. Validated // against list of file paths returned by |GetLocalImages|. - SelectLocalImage(mojo_base.mojom.FilePath path) => (bool success); + SelectLocalImage(mojo_base.mojom.FilePath path, bool preview_mode) => + (bool success); // Sets the custom layout for current wallpaper SetCustomWallpaperLayout(WallpaperLayout layout); @@ -139,4 +141,15 @@ // Refresh the wallpaper. Noop if daily refresh is not enabled. UpdateDailyRefreshWallpaper() => (bool success); + + // Indicates whether the device is in tablet mode. + IsInTabletMode() => (bool tablet_mode); + + // Confirms the wallpaper being previewed to be set as the actual user + // wallpaper. Must be called in preview mode. + ConfirmPreviewWallpaper(); + + // Cancels the wallpaper preview and reverts to the user wallpaper. Must be + // called in preview mode. + CancelPreviewWallpaper(); };
diff --git a/chromeos/components/personalization_app/personalization_app_ui.cc b/chromeos/components/personalization_app/personalization_app_ui.cc index 0fa8936e..d8e96225 100644 --- a/chromeos/components/personalization_app/personalization_app_ui.cc +++ b/chromeos/components/personalization_app/personalization_app_ui.cc
@@ -81,7 +81,8 @@ {"dismiss", IDS_PERSONALIZATION_APP_DISMISS}, {"ariaLabelViewFullScreen", IDS_PERSONALIZATION_APP_ARIA_LABEL_VIEW_FULL_SCREEN}, - {"exitFullscreen", IDS_PERSONALIZATION_APP_EXIT_FULL_SCREEN}}; + {"exitFullscreen", IDS_PERSONALIZATION_APP_EXIT_FULL_SCREEN}, + {"setAsWallpaper", IDS_PERSONALIZATION_APP_SET_AS_WALLPAPER}}; source->AddLocalizedStrings(kLocalizedStrings); source->UseStringsJs(); }
diff --git a/chromeos/components/personalization_app/resources/trusted/personalization_controller.js b/chromeos/components/personalization_app/resources/trusted/personalization_controller.js index 62b014a..d0a5cd9 100644 --- a/chromeos/components/personalization_app/resources/trusted/personalization_controller.js +++ b/chromeos/components/personalization_app/resources/trusted/personalization_controller.js
@@ -4,7 +4,7 @@ import {assert} from 'chrome://resources/js/assert.m.js' import {isNonEmptyArray} from '../common/utils.js'; -import {beginLoadImagesForCollectionsAction, beginLoadLocalImageDataAction, beginLoadLocalImagesAction, beginLoadSelectedImageAction, beginSelectImageAction, beginUpdateDailyRefreshImageAction, endSelectImageAction, setCollectionsAction, setDailyRefreshCollectionIdAction, setImagesForCollectionAction, setLocalImageDataAction, setLocalImagesAction, setSelectedImageAction, setUpdatedDailyRefreshImageAction} from './personalization_actions.js'; +import * as action from './personalization_actions.js'; import {WallpaperLayout, WallpaperType} from './personalization_reducers.js'; import {PersonalizationStore} from './personalization_store.js'; @@ -27,7 +27,7 @@ console.warn('Failed to fetch wallpaper collections'); collections = null; } - store.dispatch(setCollectionsAction(collections)); + store.dispatch(action.setCollectionsAction(collections)); } /** @@ -43,14 +43,14 @@ 'Cannot fetch data for collections when it is not initialized'); return; } - store.dispatch(beginLoadImagesForCollectionsAction(collections)); + store.dispatch(action.beginLoadImagesForCollectionsAction(collections)); for (const {id} of /** @type {!Array<{id: string}>} */ (collections)) { let {images} = await provider.fetchImagesForCollection(id); if (!isNonEmptyArray(images)) { console.warn('Failed to fetch images for collection id', id); images = null; } - store.dispatch(setImagesForCollectionAction(id, images)); + store.dispatch(action.setImagesForCollectionAction(id, images)); } } @@ -61,12 +61,12 @@ * @param {!PersonalizationStore} store */ async function getLocalImages(provider, store) { - store.dispatch(beginLoadLocalImagesAction()); + store.dispatch(action.beginLoadLocalImagesAction()); const {images} = await provider.getLocalImages(); if (images == null) { console.warn('Failed to fetch local images'); } - store.dispatch(setLocalImagesAction(images)); + store.dispatch(action.setLocalImagesAction(images)); } /** @@ -101,7 +101,7 @@ continue; } imageThumbnailsToFetch.add(filePath.path); - store.dispatch(beginLoadLocalImageDataAction(filePath)); + store.dispatch(action.beginLoadLocalImageDataAction(filePath)); } store.endBatchUpdate(); @@ -113,7 +113,7 @@ if (!data) { console.warn('Failed to fetch local image data', path); } - store.dispatch(setLocalImageDataAction({path}, data)); + store.dispatch(action.setLocalImageDataAction({path}, data)); } } @@ -128,30 +128,33 @@ // Batch these changes together to reduce polymer churn as multiple state // fields change quickly. store.beginBatchUpdate(); - store.dispatch(beginSelectImageAction(image)); - store.dispatch(beginLoadSelectedImageAction()); + store.dispatch(action.beginSelectImageAction(image)); + store.dispatch(action.beginLoadSelectedImageAction()); + const {tabletMode} = await provider.isInTabletMode(); + if (tabletMode) { + store.dispatch(action.setFullscreenEnabledAction(/*enabled=*/ true)) + } store.endBatchUpdate(); const {success} = await (() => { if (image.assetId) { - return provider.selectWallpaper(image.assetId); + return provider.selectWallpaper( + image.assetId, /*preview_mode=*/ tabletMode); } else if (image.path) { return provider.selectLocalImage( - /** @type {!mojoBase.mojom.FilePath} */ (image)); + /** @type {!mojoBase.mojom.FilePath} */ (image), + /*preview_mode=*/ tabletMode); } else { console.warn('Image must be a local image or a WallpaperImage'); return {success: false}; } })(); store.beginBatchUpdate(); - store.dispatch(endSelectImageAction(image, success)); + store.dispatch(action.endSelectImageAction(image, success)); if (!success) { console.warn('Error setting wallpaper'); - store.dispatch(setSelectedImageAction(store.data.currentSelected)); + store.dispatch(action.setSelectedImageAction(store.data.currentSelected)); } store.endBatchUpdate(); - - // Cleared Daily Refresh state should be reflected in UI. - getDailyRefreshCollectionId(provider, store); } /** @@ -170,7 +173,7 @@ if (image.layout === layout) return; - store.dispatch(beginLoadSelectedImageAction()); + store.dispatch(action.beginLoadSelectedImageAction()); await provider.setCustomWallpaperLayout(layout); } @@ -196,7 +199,7 @@ */ export async function getDailyRefreshCollectionId(provider, store) { const {collectionId} = await provider.getDailyRefreshCollectionId(); - store.dispatch(setDailyRefreshCollectionIdAction(collectionId)); + store.dispatch(action.setDailyRefreshCollectionIdAction(collectionId)); } /** @@ -206,15 +209,33 @@ * @param {!PersonalizationStore} store */ export async function updateDailyRefreshWallpaper(provider, store) { - store.dispatch(beginUpdateDailyRefreshImageAction()); - store.dispatch(beginLoadSelectedImageAction()); + store.dispatch(action.beginUpdateDailyRefreshImageAction()); + store.dispatch(action.beginLoadSelectedImageAction()); const {success} = await provider.updateDailyRefreshWallpaper(); if (success) { - store.dispatch(setUpdatedDailyRefreshImageAction()); + store.dispatch(action.setUpdatedDailyRefreshImageAction()); } } /** + * Confirm and set preview wallpaper as actual wallpaper. + * @param {!chromeos.personalizationApp.mojom.WallpaperProviderInterface} + * provider + */ +export async function confirmPreviewWallpaper(provider) { + await provider.confirmPreviewWallpaper(); +} + +/** + * Cancel preview wallpaper and show the previous wallpaper. + * @param {!chromeos.personalizationApp.mojom.WallpaperProviderInterface} + * provider + */ +export async function cancelPreviewWallpaper(provider) { + await provider.cancelPreviewWallpaper(); +} + +/** * Fetches list of collections, then fetches list of images for each collection. * @param {!chromeos.personalizationApp.mojom.WallpaperProviderInterface} * provider
diff --git a/chromeos/components/personalization_app/resources/trusted/personalization_reducers.js b/chromeos/components/personalization_app/resources/trusted/personalization_reducers.js index eef5870..9519352 100644 --- a/chromeos/components/personalization_app/resources/trusted/personalization_reducers.js +++ b/chromeos/components/personalization_app/resources/trusted/personalization_reducers.js
@@ -342,6 +342,12 @@ return null; } return state; + case ActionName.SET_FULLSCREEN_ENABLED: + if (!(/** @type {{enabled: boolean}} */ (action)).enabled) { + // Clear the pending selected state after full screen is dismissed. + return null; + } + return state; default: return state; }
diff --git a/chromeos/components/personalization_app/resources/trusted/wallpaper_fullscreen_element.html b/chromeos/components/personalization_app/resources/trusted/wallpaper_fullscreen_element.html index 89e30c0..91d5bba 100644 --- a/chromeos/components/personalization_app/resources/trusted/wallpaper_fullscreen_element.html +++ b/chromeos/components/personalization_app/resources/trusted/wallpaper_fullscreen_element.html
@@ -8,6 +8,10 @@ </style> <div id="container" hidden> <button on-click="onClickExit_" id="exit">[[i18n('exitFullscreen')]]</button> + <template is="dom-if" if="[[showConfirm_]]"> + <button on-click="onClickConfirm_" id="confirm">[[i18n('setAsWallpaper')]] + </button> + </template> <template is="dom-if" if="[[showLayoutOptions_]]"> <div id="layoutButtons"> <button on-click="onClickLayout_"
diff --git a/chromeos/components/personalization_app/resources/trusted/wallpaper_fullscreen_element.js b/chromeos/components/personalization_app/resources/trusted/wallpaper_fullscreen_element.js index a12f396..96bce2e2 100644 --- a/chromeos/components/personalization_app/resources/trusted/wallpaper_fullscreen_element.js +++ b/chromeos/components/personalization_app/resources/trusted/wallpaper_fullscreen_element.js
@@ -12,7 +12,7 @@ import {getWallpaperLayoutEnum} from '../common/utils.js'; import {getWallpaperProvider} from './mojo_interface_provider.js'; import {setFullscreenEnabledAction} from './personalization_actions.js'; -import {setCustomWallpaperLayout} from './personalization_controller.js'; +import {cancelPreviewWallpaper, confirmPreviewWallpaper, setCustomWallpaperLayout} from './personalization_controller.js'; import {updateDailyRefreshWallpaper} from './personalization_controller.js'; import {WithPersonalizationStore} from './personalization_store.js'; @@ -78,7 +78,8 @@ 'showDailyRefresh_', state => state.currentSelected?.type === chromeos.personalizationApp.mojom.WallpaperType.kDaily && - state.dailyRefresh.collectionId); + state.dailyRefresh.collectionId && !state.pendingSelected); + this.watch('showConfirm_', state => !!state.pendingSelected); this.watch('image_', state => state.currentSelected); } @@ -116,12 +117,25 @@ const hidden = !this.getFullscreenElement(); this.shadowRoot.getElementById('container').hidden = hidden; if (hidden) { + // SWA also supports exiting fullscreen when users press ESC. In this + // case, the preview mode may be still on so we have to call cancel + // preview. + // This call is no-op when the user clicks on exit button or set as + // wallpaper button. + cancelPreviewWallpaper(this.wallpaperProvider_); this.dispatch(setFullscreenEnabledAction(/*enabled=*/false)); } } /** @private */ onClickExit_() { + cancelPreviewWallpaper(this.wallpaperProvider_); + this.exitFullscreen(); + } + + /** @private */ + onClickConfirm_() { + confirmPreviewWallpaper(this.wallpaperProvider_); this.exitFullscreen(); }
diff --git a/chromeos/components/personalization_app/resources/trusted/wallpaper_selected_element.js b/chromeos/components/personalization_app/resources/trusted/wallpaper_selected_element.js index a9332ab..86fe6b0 100644 --- a/chromeos/components/personalization_app/resources/trusted/wallpaper_selected_element.js +++ b/chromeos/components/personalization_app/resources/trusted/wallpaper_selected_element.js
@@ -263,6 +263,9 @@ this.initialLoadTimeout_ = null; } this.dispatch(setSelectedImageAction(currentWallpaper)); + + // Daily Refresh state should also get updated when wallpaper changes. + getDailyRefreshCollectionId(this.wallpaperProvider_, this.getStore()); } /**
diff --git a/chromeos/components/personalization_app/test/fake_personalization_app_ui_delegate.cc b/chromeos/components/personalization_app/test/fake_personalization_app_ui_delegate.cc index dd1dde3..eef3783b 100644 --- a/chromeos/components/personalization_app/test/fake_personalization_app_ui_delegate.cc +++ b/chromeos/components/personalization_app/test/fake_personalization_app_ui_delegate.cc
@@ -75,12 +75,14 @@ void FakePersonalizationAppUiDelegate::SelectWallpaper( uint64_t image_asset_id, + bool preview_mode, SelectWallpaperCallback callback) { std::move(callback).Run(/*success=*/true); } void FakePersonalizationAppUiDelegate::SelectLocalImage( const base::FilePath& path, + bool preview_mode, SelectLocalImageCallback callback) { std::move(callback).Run(/*success=*/true); } @@ -104,3 +106,16 @@ UpdateDailyRefreshWallpaperCallback callback) { std::move(callback).Run(/*success=*/true); } + +void FakePersonalizationAppUiDelegate::IsInTabletMode( + IsInTabletModeCallback callback) { + std::move(callback).Run(/*tablet_mode=*/false); +} + +void FakePersonalizationAppUiDelegate::ConfirmPreviewWallpaper() { + return; +} + +void FakePersonalizationAppUiDelegate::CancelPreviewWallpaper() { + return; +}
diff --git a/chromeos/components/personalization_app/test/fake_personalization_app_ui_delegate.h b/chromeos/components/personalization_app/test/fake_personalization_app_ui_delegate.h index fcaadc7..c88eafe 100644 --- a/chromeos/components/personalization_app/test/fake_personalization_app_ui_delegate.h +++ b/chromeos/components/personalization_app/test/fake_personalization_app_ui_delegate.h
@@ -51,9 +51,11 @@ override; void SelectWallpaper(uint64_t image_asset_id, + bool preview_mode, SelectWallpaperCallback callback) override; void SelectLocalImage(const base::FilePath& path, + bool preview_mode, SelectLocalImageCallback callback) override; void SetCustomWallpaperLayout(ash::WallpaperLayout layout) override; @@ -66,6 +68,12 @@ void UpdateDailyRefreshWallpaper( UpdateDailyRefreshWallpaperCallback callback) override; + void IsInTabletMode(IsInTabletModeCallback callback) override; + + void ConfirmPreviewWallpaper() override; + + void CancelPreviewWallpaper() override; + private: mojo::Receiver<chromeos::personalization_app::mojom::WallpaperProvider> wallpaper_receiver_{this};
diff --git a/chromeos/components/projector_app/BUILD.gn b/chromeos/components/projector_app/BUILD.gn index ca4202f..f41727d 100644 --- a/chromeos/components/projector_app/BUILD.gn +++ b/chromeos/components/projector_app/BUILD.gn
@@ -18,6 +18,8 @@ "projector_message_handler.h", "projector_oauth_token_fetcher.cc", "projector_oauth_token_fetcher.h", + "projector_xhr_sender.cc", + "projector_xhr_sender.h", "trusted_projector_ui.cc", "trusted_projector_ui.h", "untrusted_projector_ui_config.cc", @@ -52,6 +54,7 @@ "//base/test:test_support", "//components/signin/public/identity_manager", "//components/signin/public/identity_manager:test_support", + "//services/network:test_support", "//testing/gmock", ] } @@ -62,6 +65,7 @@ "test/annotator_message_handler_unittest.cc", "test/projector_message_handler_unittest.cc", "test/projector_oauth_token_fetcher_unittest.cc", + "test/projector_xhr_sender_unittest.cc", ] deps = [
diff --git a/chromeos/components/projector_app/DEPS b/chromeos/components/projector_app/DEPS index 3c09912c..8bc6a58 100644 --- a/chromeos/components/projector_app/DEPS +++ b/chromeos/components/projector_app/DEPS
@@ -6,6 +6,8 @@ "+content/public/browser", "+content/public/common", "+content/public/test", + "+services/network/public", + "+services/network/test", "+third_party/skia", "+ui/resources", "+ui/webui",
diff --git a/chromeos/components/projector_app/projector_app_client.h b/chromeos/components/projector_app/projector_app_client.h index 50e6fbfb..d011c0ef 100644 --- a/chromeos/components/projector_app/projector_app_client.h +++ b/chromeos/components/projector_app/projector_app_client.h
@@ -7,6 +7,12 @@ #include "base/observer_list_types.h" +namespace network { +namespace mojom { +class URLLoaderFactory; +} // namespace mojom +} // namespace network + namespace signin { class IdentityManager; } // namespace signin @@ -35,6 +41,9 @@ virtual void AddObserver(Observer* observer) = 0; virtual void RemoveObserver(Observer* observer) = 0; + // Returns the URLLoaderFactory for the primary user profile. + virtual network::mojom::URLLoaderFactory* GetUrlLoaderFactory() = 0; + protected: ProjectorAppClient(); virtual ~ProjectorAppClient();
diff --git a/chromeos/components/projector_app/projector_xhr_sender.cc b/chromeos/components/projector_app/projector_xhr_sender.cc new file mode 100644 index 0000000..5be4617 --- /dev/null +++ b/chromeos/components/projector_app/projector_xhr_sender.cc
@@ -0,0 +1,167 @@ +// Copyright 2021 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/components/projector_app/projector_xhr_sender.h" + +#include <string> + +#include "base/bind.h" +#include "base/strings/string_util.h" +#include "chromeos/components/projector_app/projector_app_client.h" +#include "components/signin/public/identity_manager/access_token_info.h" +#include "components/signin/public/identity_manager/identity_manager.h" +#include "net/base/url_util.h" +#include "services/network/public/cpp/resource_request.h" +#include "services/network/public/cpp/simple_url_loader.h" +#include "services/network/public/mojom/url_loader_factory.mojom.h" +#include "services/network/public/mojom/url_response_head.mojom.h" +#include "url/gurl.h" + +namespace chromeos { + +namespace { +// Projector network traffic annotation tags. +constexpr net::NetworkTrafficAnnotationTag kNetworkTrafficAnnotationTag = + net::DefineNetworkTrafficAnnotation("projector_xhr_loader", R"( + semantics: { + sender: "ChromeOS Projector" + description: "ChromeOS send Projector XHR requests" + destination: GOOGLE_OWNED_SERVICE + } + policy: { + cookies_allowed: YES + })"); + +constexpr char kAuthorizationHeaderPrefix[] = "Bearer "; + +// List of URL prefix supported by `ProjectorXhrSender`. +const char* kUrlAllowlist[] = { + "https://www.googleapis.com/drive/v3/files/", + "https://drive.google.com/get_video_info", + "https://translation.googleapis.com/language/translate/v2"}; + +// Return true if the url matches the allowed URL prefix. +bool IsUrlAllowlisted(const std::string& url) { + for (auto* urlPrefix : kUrlAllowlist) { + if (base::StartsWith(url, urlPrefix, base::CompareCase::SENSITIVE)) + return true; + } + return false; +} +} // namespace + +ProjectorXhrSender::ProjectorXhrSender( + network::mojom::URLLoaderFactory* url_loader_factory) + : url_loader_factory_(url_loader_factory) {} +ProjectorXhrSender::~ProjectorXhrSender() = default; + +void ProjectorXhrSender::Send(const GURL& url, + const std::string& method, + const std::string& request_body, + bool use_credentials, + SendRequestCallback callback) { + if (!IsUrlAllowlisted(url.spec())) { + std::move(callback).Run( + /*success=*/false, + /*response_body=*/std::string(), + /*error=*/"UNSUPPORTED_URL"); + return; + } + + if (use_credentials) { + // Use end user credentials to authorize the request. Doesn't need to fetch + // OAuth token. + SendRequest(url, method, request_body, /*token=*/std::string(), + std::move(callback)); + return; + } + + // Fetch OAuth token for authorizing the request. + // TODO(b/197366265): add support for secondary account. + auto primary_account = + chromeos::ProjectorAppClient::Get() + ->GetIdentityManager() + ->GetPrimaryAccountInfo(signin::ConsentLevel::kSignin); + oauth_token_fetcher_.GetAccessTokenFor( + primary_account.email, + base::BindOnce(&ProjectorXhrSender::OnAccessTokenRequestCompleted, + weak_factory_.GetWeakPtr(), url, method, request_body, + std::move(callback))); +} + +void ProjectorXhrSender::OnAccessTokenRequestCompleted( + const GURL& url, + const std::string& method, + const std::string& request_body, + SendRequestCallback callback, + const std::string& email, + GoogleServiceAuthError error, + const signin::AccessTokenInfo& info) { + if (error.state() != GoogleServiceAuthError::State::NONE) { + std::move(callback).Run( + /*success=*/false, + /*response_body=*/std::string(), + /*error=*/"TOKEN_FETCH_FAILURE"); + return; + } + + SendRequest(url, method, request_body, info.token, std::move(callback)); +} + +void ProjectorXhrSender::SendRequest(const GURL& url, + const std::string& method, + const std::string& request_body, + const std::string& token, + SendRequestCallback callback) { + // Build resource request. + auto resource_request = std::make_unique<network::ResourceRequest>(); + resource_request->url = url; + resource_request->method = method; + // The OAuth token will be empty if the request is using end user credentials + // for authorization. + if (!token.empty()) { + resource_request->headers.SetHeader(net::HttpRequestHeaders::kAuthorization, + kAuthorizationHeaderPrefix + token); + } + resource_request->headers.SetHeader(net::HttpRequestHeaders::kAccept, + "application/json"); + + // Send resource request. + auto loader = network::SimpleURLLoader::Create(std::move(resource_request), + kNetworkTrafficAnnotationTag); + + if (!request_body.empty()) + loader->AttachStringForUpload(request_body, "application/json"); + + loader->DownloadToStringOfUnboundedSizeUntilCrashAndDie( + url_loader_factory_, + base::BindOnce(&ProjectorXhrSender::OnSimpleURLLoaderComplete, + weak_factory_.GetWeakPtr(), next_request_id_, + std::move(callback))); + + loader_map_.emplace(next_request_id_++, std::move(loader)); +} + +void ProjectorXhrSender::OnSimpleURLLoaderComplete( + int request_id, + SendRequestCallback callback, + std::unique_ptr<std::string> response_body) { + auto& loader = loader_map_[request_id]; + if (!response_body || loader->NetError() != net::OK || + !loader->ResponseInfo() || !loader->ResponseInfo()->headers) { + std::move(callback).Run( + /*success=*/false, + /*response_body=*/std::string(), + /*error=*/"XHR_FETCH_FAILURE"); + } else { + std::move(callback).Run( + /*success=*/true, + /*response_body=*/*response_body, + /*error=*/std::string()); + } + + loader_map_.erase(request_id); +} + +} // namespace chromeos
diff --git a/chromeos/components/projector_app/projector_xhr_sender.h b/chromeos/components/projector_app/projector_xhr_sender.h new file mode 100644 index 0000000..88f427cf --- /dev/null +++ b/chromeos/components/projector_app/projector_xhr_sender.h
@@ -0,0 +1,90 @@ +// Copyright 2021 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_COMPONENTS_PROJECTOR_APP_PROJECTOR_XHR_SENDER_H_ +#define CHROMEOS_COMPONENTS_PROJECTOR_APP_PROJECTOR_XHR_SENDER_H_ + +#include <map> +#include <string> + +#include "base/callback.h" +#include "base/memory/weak_ptr.h" +#include "chromeos/components/projector_app/projector_oauth_token_fetcher.h" +#include "google_apis/gaia/google_service_auth_error.h" + +namespace base { +class GURL; +} // namespace base + +namespace network { +class SimpleURLLoader; + +namespace mojom { +class URLLoaderFactory; +} // namespace mojom +} // namespace network + +namespace chromeos { + +/** + * Projector XHR sender. Used by Projector App to send XHR requests. + */ +class ProjectorXhrSender { + public: + // Callback triggered when a XHR request is completed. `response_body` + // contains the response text if success, empty otherwise. `error` contains + // error message if not success, empty otherwise. + using SendRequestCallback = + base::OnceCallback<void(bool success, + const std::string& response_body, + const std::string& error)>; + + explicit ProjectorXhrSender( + network::mojom::URLLoaderFactory* url_loader_factory); + ProjectorXhrSender(const ProjectorXhrSender&) = delete; + ProjectorXhrSender& operator=(const ProjectorXhrSender&) = delete; + ~ProjectorXhrSender(); + + // Send XHR request and trigger the callback when complete. + void Send(const GURL& url, + const std::string& method, + const std::string& request_body, + bool use_credentials, + SendRequestCallback callback); + + private: + // Triggered when an OAuth token fetch completed. + void OnAccessTokenRequestCompleted(const GURL& url, + const std::string& method, + const std::string& request_body, + SendRequestCallback callback, + const std::string& email, + GoogleServiceAuthError error, + const signin::AccessTokenInfo& info); + + void SendRequest(const GURL& url, + const std::string& method, + const std::string& request_body, + const std::string& token, + SendRequestCallback callback); + + // Triggered when an XHR request completed. + void OnSimpleURLLoaderComplete(int request_id, + SendRequestCallback callback, + std::unique_ptr<std::string> response_body); + + ProjectorOAuthTokenFetcher oauth_token_fetcher_; + network::mojom::URLLoaderFactory* url_loader_factory_ = nullptr; + + // Next request ID. + int next_request_id_ = 0; + // The map to hold the SimpleURLLoader for each request. The key is a unique + // request ID associated with each request. + std::map<int, std::unique_ptr<network::SimpleURLLoader>> loader_map_; + + base::WeakPtrFactory<ProjectorXhrSender> weak_factory_{this}; +}; + +} // namespace chromeos +#endif // CHROMEOS_COMPONENTS_PROJECTOR_APP_PROJECTOR_XHR_SENDER_H_
diff --git a/chromeos/components/projector_app/test/mock_app_client.cc b/chromeos/components/projector_app/test/mock_app_client.cc index b51fed3..45b0097 100644 --- a/chromeos/components/projector_app/test/mock_app_client.cc +++ b/chromeos/components/projector_app/test/mock_app_client.cc
@@ -26,6 +26,10 @@ return identity_test_environment_.identity_manager(); } +network::mojom::URLLoaderFactory* MockAppClient::GetUrlLoaderFactory() { + return &test_url_loader_factory_; +} + void MockAppClient::SetAutomaticIssueOfAccessTokens(bool success) { identity_test_environment_.SetAutomaticIssueOfAccessTokens(success); }
diff --git a/chromeos/components/projector_app/test/mock_app_client.h b/chromeos/components/projector_app/test/mock_app_client.h index 78f1209..c514ca0 100644 --- a/chromeos/components/projector_app/test/mock_app_client.h +++ b/chromeos/components/projector_app/test/mock_app_client.h
@@ -10,8 +10,15 @@ #include "base/time/time.h" #include "chromeos/components/projector_app/projector_app_client.h" #include "components/signin/public/identity_manager/identity_test_environment.h" +#include "services/network/test/test_url_loader_factory.h" #include "testing/gmock/include/gmock/gmock.h" +namespace network { +namespace mojom { +class URLLoaderFactory; +} // namespace mojom +} // namespace network + namespace signin { class IdentityManager; } // namespace signin @@ -25,8 +32,13 @@ MockAppClient& operator=(const MockAppClient&) = delete; ~MockAppClient() override; + network::TestURLLoaderFactory& test_url_loader_factory() { + return test_url_loader_factory_; + } + // ProjectorAppClient: signin::IdentityManager* GetIdentityManager() override; + network::mojom::URLLoaderFactory* GetUrlLoaderFactory() override; MOCK_METHOD1(AddObserver, void(Observer*)); MOCK_METHOD1(RemoveObserver, void(Observer*)); @@ -38,6 +50,7 @@ private: signin::IdentityTestEnvironment identity_test_environment_; + network::TestURLLoaderFactory test_url_loader_factory_; }; } // namespace chromeos
diff --git a/chromeos/components/projector_app/test/projector_xhr_sender_unittest.cc b/chromeos/components/projector_app/test/projector_xhr_sender_unittest.cc new file mode 100644 index 0000000..7040ec86 --- /dev/null +++ b/chromeos/components/projector_app/test/projector_xhr_sender_unittest.cc
@@ -0,0 +1,190 @@ +// Copyright 2021 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/components/projector_app/projector_xhr_sender.h" + +#include "base/bind.h" +#include "base/callback.h" +#include "base/run_loop.h" +#include "base/test/bind.h" +#include "base/test/task_environment.h" +#include "base/time/time.h" +#include "chromeos/components/projector_app/test/mock_app_client.h" +#include "services/network/public/mojom/url_response_head.mojom.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "url/gurl.h" + +namespace { + +const char kTestUserEmail[] = "testuser1@gmail.com"; +const base::TimeDelta kExpiryTimeFromNow = base::Minutes(10); +constexpr char kValidUrl[] = "https://www.googleapis.com/drive/v3/files/fileID"; +constexpr char kValidUrl2[] = + "https://translation.googleapis.com/language/translate/v2"; + +} // namespace + +namespace chromeos { + +class ProjectorXhrSenderTest : public testing::Test { + public: + ProjectorXhrSenderTest() = default; + ProjectorXhrSenderTest(const ProjectorXhrSenderTest&) = delete; + ProjectorXhrSenderTest& operator=(const ProjectorXhrSenderTest&) = delete; + ~ProjectorXhrSenderTest() override = default; + + // testing::Test: + void SetUp() override { + sender_ = std::make_unique<ProjectorXhrSender>( + mock_app_client_.GetUrlLoaderFactory()); + } + + ProjectorXhrSender* sender() { return sender_.get(); } + MockAppClient& mock_app_client() { return mock_app_client_; } + + private: + base::test::SingleThreadTaskEnvironment task_environment_; + std::unique_ptr<ProjectorXhrSender> sender_; + MockAppClient mock_app_client_; +}; + +TEST_F(ProjectorXhrSenderTest, Success) { + base::RunLoop run_loop; + + const std::string& test_response_body = "{}"; + sender()->Send( + GURL(kValidUrl), "GET", /*request_body=*/"", /*useCredential=*/false, + base::BindOnce( + [](const std::string& expected_response_body, + base::RepeatingClosure quit_closure, bool success, + const std::string& response_body, const std::string& error) { + EXPECT_TRUE(success); + EXPECT_EQ(expected_response_body, response_body); + EXPECT_EQ("", error); + quit_closure.Run(); + }, + test_response_body, run_loop.QuitClosure())); + + mock_app_client().test_url_loader_factory().AddResponse(kValidUrl, + test_response_body); + + mock_app_client().GrantOAuthTokenFor( + kTestUserEmail, + /* expiry_time = */ base::Time::Now() + kExpiryTimeFromNow); + run_loop.Run(); +} + +TEST_F(ProjectorXhrSenderTest, TwoRequests) { + base::RunLoop run_loop; + const std::string& test_response_body = "{}"; + sender()->Send( + GURL(kValidUrl), "GET", /*request_body=*/"", /*useCredential=*/false, + base::BindOnce( + [](const std::string& expected_response_body, + base::RepeatingClosure quit_closure, bool success, + const std::string& response_body, const std::string& error) { + EXPECT_TRUE(success); + EXPECT_EQ(expected_response_body, response_body); + EXPECT_EQ("", error); + quit_closure.Run(); + }, + test_response_body, run_loop.QuitClosure())); + + base::RunLoop run_loop2; + const std::string& test_response_body2 = "{data: {}}"; + sender()->Send( + GURL(kValidUrl2), "GET", /*request_body=*/"", /*useCredential=*/false, + base::BindOnce( + [](const std::string& expected_response_body, + base::RepeatingClosure quit_closure, bool success, + const std::string& response_body, const std::string& error) { + EXPECT_TRUE(success); + EXPECT_EQ(expected_response_body, response_body); + EXPECT_EQ("", error); + quit_closure.Run(); + }, + test_response_body2, run_loop2.QuitClosure())); + + mock_app_client().test_url_loader_factory().AddResponse(kValidUrl, + test_response_body); + + mock_app_client().test_url_loader_factory().AddResponse(kValidUrl2, + test_response_body2); + + mock_app_client().GrantOAuthTokenFor( + kTestUserEmail, + /* expiry_time = */ base::Time::Now() + kExpiryTimeFromNow); + run_loop.Run(); + run_loop2.Run(); +} + +TEST_F(ProjectorXhrSenderTest, UseCredentials) { + base::RunLoop run_loop; + + const std::string& test_response_body = "{}"; + sender()->Send( + GURL(kValidUrl), "GET", /*request_body=*/"", /*useCredential=*/true, + base::BindOnce( + [](const std::string& expected_response_body, + base::RepeatingClosure quit_closure, bool success, + const std::string& response_body, const std::string& error) { + EXPECT_TRUE(success); + EXPECT_EQ(expected_response_body, response_body); + EXPECT_EQ("", error); + quit_closure.Run(); + }, + test_response_body, run_loop.QuitClosure())); + + // Verify that http request is sent without granting OAuth token. + mock_app_client().test_url_loader_factory().AddResponse(kValidUrl, + test_response_body); + + run_loop.Run(); +} + +TEST_F(ProjectorXhrSenderTest, NetworkError) { + base::RunLoop run_loop; + + sender()->Send( + GURL(kValidUrl), /*method=*/"GET", /*request_body=*/"", + /*use_credentials=*/false, + base::BindOnce( + [](base::RepeatingClosure quit_closure, bool success, + const std::string& response_body, const std::string& error) { + EXPECT_FALSE(success); + EXPECT_EQ("", response_body); + EXPECT_EQ("XHR_FETCH_FAILURE", error); + quit_closure.Run(); + }, + run_loop.QuitClosure())); + + mock_app_client().test_url_loader_factory().AddResponse( + GURL(kValidUrl), network::mojom::URLResponseHead::New(), std::string(), + network::URLLoaderCompletionStatus(net::HTTP_NOT_FOUND)); + + mock_app_client().GrantOAuthTokenFor( + kTestUserEmail, + /* expiry_time = */ base::Time::Now() + kExpiryTimeFromNow); + run_loop.Run(); +} + +TEST_F(ProjectorXhrSenderTest, UnsupportedUrl) { + base::RunLoop run_loop; + + sender()->Send( + GURL("https://example.com"), /*method=*/"GET", /*request_body=*/"", + /*use_credentials=*/false, + base::BindOnce( + [](base::RepeatingClosure quit_closure, bool success, + const std::string& response_body, const std::string& error) { + EXPECT_FALSE(success); + EXPECT_EQ("", response_body); + EXPECT_EQ("UNSUPPORTED_URL", error); + quit_closure.Run(); + }, + run_loop.QuitClosure())); + + run_loop.Run(); +} +} // namespace chromeos
diff --git a/chromeos/crosapi/mojom/BUILD.gn b/chromeos/crosapi/mojom/BUILD.gn index 426aee0..2c19b86 100644 --- a/chromeos/crosapi/mojom/BUILD.gn +++ b/chromeos/crosapi/mojom/BUILD.gn
@@ -21,6 +21,7 @@ "content_protection.mojom", "crosapi.mojom", "device_attributes.mojom", + "device_settings_service.mojom", "download_controller.mojom", "drive_integration_service.mojom", "feedback.mojom",
diff --git a/chromeos/crosapi/mojom/crosapi.mojom b/chromeos/crosapi/mojom/crosapi.mojom index 92efef9..a40b2fdb 100644 --- a/chromeos/crosapi/mojom/crosapi.mojom +++ b/chromeos/crosapi/mojom/crosapi.mojom
@@ -16,6 +16,7 @@ import "chromeos/crosapi/mojom/clipboard_history.mojom"; import "chromeos/crosapi/mojom/content_protection.mojom"; import "chromeos/crosapi/mojom/device_attributes.mojom"; +import "chromeos/crosapi/mojom/device_settings_service.mojom"; import "chromeos/crosapi/mojom/download_controller.mojom"; import "chromeos/crosapi/mojom/drive_integration_service.mojom"; import "chromeos/crosapi/mojom/feedback.mojom"; @@ -79,8 +80,8 @@ // please note the milestone when you added it, to help us reason about // compatibility between the client applications and older ash-chrome binaries. // -// Next version: 55 -// Next method id: 59 +// Next version: 56 +// Next method id: 60 [Stable, Uuid="8b79c34f-2bf8-4499-979a-b17cac522c1e", RenamedFrom="crosapi.mojom.AshChromeService"] interface Crosapi { @@ -172,6 +173,12 @@ [MinVersion=12] BindDeviceAttributes@17( pending_receiver<DeviceAttributes> receiver); + // Binds the DeviceSettingsService interface for initializing device settings + // in Lacros-Chrome. + // Added in 96. + [MinVersion=55] BindDeviceSettingsService@59( + pending_receiver<DeviceSettingsService> receiver); + // Binds the DownloadController interface, which allows Lacros download // information to be passed into Ash Chrome. // Added in M92. @@ -469,44 +476,6 @@ [MinVersion=1] array<string>? device_affiliation_ids@1; }; -// Copy of UsbDetachableAllowlistProto from chrome_device_policy.proto. -[Stable, Extensible] -struct UsbDetachableAllowlist { - array<UsbDeviceId> usb_device_ids@0; -}; - -// Copy of UsbDeviceIdInclusiveProto from chrome_device_policy.proto. -[Stable, Extensible] -struct UsbDeviceId { - // USB Vendor Identifier (aka idVendor). - bool has_vendor_id@0; - int32 vendor_id@1; - // USB Product Identifier (aka idProduct). - bool has_product_id@2; - int32 product_id@3; -}; - -// All the device settings data that are needed in Lacros should be here. -[Stable, Extensible] -struct DeviceSettings { - // The value of AttestationForContentProtectionEnabled device setting. - OptionalBool attestation_for_content_protection_enabled@0; - - // The value of DeviceSystemWideTracingEnabled device policy. - OptionalBool device_system_wide_tracing_enabled@1; - - // The value of UsbDetachableAllowlist device policy. - UsbDetachableAllowlist? usb_detachable_allow_list@2; - - [Stable] - enum OptionalBool { - kUnset, - kFalse, - kTrue, - }; -}; - - [Stable, Extensible] enum ExoImeSupport { kUnsupported = 0, @@ -757,7 +726,8 @@ [MinVersion=24] array<url.mojom.Url>? startup_urls@24; - // The set of device settings Lacros needs to know about. + // The set of device settings for Lacros. Lacros should *NOT* use this data, + // but rely on DeviceSettingsLacros::GetDeviceSettings instead. [MinVersion=25] DeviceSettings? device_settings@25;
diff --git a/chromeos/crosapi/mojom/device_settings_service.mojom b/chromeos/crosapi/mojom/device_settings_service.mojom new file mode 100644 index 0000000..80894dc --- /dev/null +++ b/chromeos/crosapi/mojom/device_settings_service.mojom
@@ -0,0 +1,59 @@ +// Copyright 2021 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 crosapi.mojom; + +// Copy of UsbDetachableAllowlistProto from chrome_device_policy.proto. +[Stable, Extensible] +struct UsbDetachableAllowlist { + array<UsbDeviceId> usb_device_ids@0; +}; + +// Copy of UsbDeviceIdInclusiveProto from chrome_device_policy.proto. +[Stable, Extensible] +struct UsbDeviceId { + // USB Vendor Identifier (aka idVendor). + bool has_vendor_id@0; + int32 vendor_id@1; + // USB Product Identifier (aka idProduct). + bool has_product_id@2; + int32 product_id@3; +}; + +// All the device settings data that are needed in Lacros should be here. +[Stable, Extensible] +struct DeviceSettings { + // The value of AttestationForContentProtectionEnabled device setting. + OptionalBool attestation_for_content_protection_enabled@0; + + // The value of DeviceSystemWideTracingEnabled device policy. + OptionalBool device_system_wide_tracing_enabled@1; + + // The value of UsbDetachableAllowlist device policy. + UsbDetachableAllowlist? usb_detachable_allow_list@2; + + [Stable] + enum OptionalBool { + kUnset, + kFalse, + kTrue, + }; +}; + +// Interface for device settings observers. Implemented by lacros-chrome. Used +// by ash-chrome to send device settings updates. +[Stable, Uuid="c2d2367e-1179-42ca-97ab-426a0c3cd265"] +interface DeviceSettingsObserver { + // Called when device settings have changed. + UpdateDeviceSettings@0(DeviceSettings device_settings); +}; + +// This interface is implemented by Ash-Chrome. +// It includes the device policy and other device settings configurable by the +// user that are needed in Lacros. +[Stable, Uuid="7ce66db5-5d91-4b45-b7aa-4fcfd8a53985"] +interface DeviceSettingsService { + // Adds an observer for device settings updates. + AddDeviceSettingsObserver@0(pending_remote<DeviceSettingsObserver> observer); +};
diff --git a/chromeos/dbus/BUILD.gn b/chromeos/dbus/BUILD.gn index 72ea43f..91b8965 100644 --- a/chromeos/dbus/BUILD.gn +++ b/chromeos/dbus/BUILD.gn
@@ -40,6 +40,7 @@ "//chromeos/dbus/chunneld:proto", "//chromeos/dbus/cros_disks", "//chromeos/dbus/easy_unlock", + "//chromeos/dbus/fwupd", "//chromeos/dbus/gnubby", "//chromeos/dbus/image_burner", "//chromeos/dbus/image_loader", @@ -137,6 +138,7 @@ "//chromeos/dbus/cryptohome:attestation_proto", "//chromeos/dbus/dlcservice:test_support", "//chromeos/dbus/easy_unlock:unit_tests", + "//chromeos/dbus/fwupd:test_support", "//chromeos/dbus/gnubby:unit_tests", "//chromeos/dbus/hermes:test_support", "//chromeos/dbus/ip_peripheral:test_support",
diff --git a/chromeos/dbus/dbus_clients_browser.cc b/chromeos/dbus/dbus_clients_browser.cc index 429de40..9f87828 100644 --- a/chromeos/dbus/dbus_clients_browser.cc +++ b/chromeos/dbus/dbus_clients_browser.cc
@@ -29,6 +29,8 @@ #include "chromeos/dbus/debug_daemon/fake_debug_daemon_client.h" #include "chromeos/dbus/easy_unlock/easy_unlock_client.h" #include "chromeos/dbus/easy_unlock/fake_easy_unlock_client.h" +#include "chromeos/dbus/fwupd/fake_fwupd_client.h" +#include "chromeos/dbus/fwupd/fwupd_client.h" #include "chromeos/dbus/gnubby/fake_gnubby_client.h" #include "chromeos/dbus/gnubby/gnubby_client.h" #include "chromeos/dbus/image_burner/fake_image_burner_client.h" @@ -88,6 +90,7 @@ debug_daemon_client_ = CREATE_DBUS_CLIENT(DebugDaemonClient, use_real_clients); easy_unlock_client_ = CREATE_DBUS_CLIENT(EasyUnlockClient, use_real_clients); + fwupd_client_ = CREATE_DBUS_CLIENT(FwupdClient, use_real_clients); gnubby_client_ = CREATE_DBUS_CLIENT(GnubbyClient, use_real_clients); image_burner_client_ = CREATE_DBUS_CLIENT(ImageBurnerClient, use_real_clients); @@ -129,6 +132,7 @@ cros_disks_client_->Init(system_bus); debug_daemon_client_->Init(system_bus); easy_unlock_client_->Init(system_bus); + fwupd_client_->Init(system_bus); gnubby_client_->Init(system_bus); image_burner_client_->Init(system_bus); image_loader_client_->Init(system_bus);
diff --git a/chromeos/dbus/dbus_clients_browser.h b/chromeos/dbus/dbus_clients_browser.h index 5c4e055c..ebcea907 100644 --- a/chromeos/dbus/dbus_clients_browser.h +++ b/chromeos/dbus/dbus_clients_browser.h
@@ -27,6 +27,7 @@ class CrosDisksClient; class DebugDaemonClient; class EasyUnlockClient; +class FwupdClient; class GnubbyClient; class ImageBurnerClient; class ImageLoaderClient; @@ -70,6 +71,7 @@ std::unique_ptr<CrosDisksClient> cros_disks_client_; std::unique_ptr<DebugDaemonClient> debug_daemon_client_; std::unique_ptr<EasyUnlockClient> easy_unlock_client_; + std::unique_ptr<FwupdClient> fwupd_client_; std::unique_ptr<GnubbyClient> gnubby_client_; std::unique_ptr<ImageBurnerClient> image_burner_client_; std::unique_ptr<ImageLoaderClient> image_loader_client_;
diff --git a/chromeos/dbus/fwupd/BUILD.gn b/chromeos/dbus/fwupd/BUILD.gn new file mode 100644 index 0000000..0f7b7331 --- /dev/null +++ b/chromeos/dbus/fwupd/BUILD.gn
@@ -0,0 +1,38 @@ +# Copyright 2021 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. + +assert(is_chromeos, "Non-ChromeOS builds cannot depend on //chromeos") + +component("fwupd") { + output_name = "chromeos_fwupd" + defines = [ "IS_CHROMEOS_DBUS_FUWPD_IMPL" ] + + deps = [ + "//ash/constants", + "//chromeos/dbus:common", + "//dbus", + ] + + sources = [ + "fake_fwupd_client.cc", + "fake_fwupd_client.h", + "fwupd_client.cc", + "fwupd_client.h", + ] +} + +source_set("test_support") { + testonly = true + + deps = [ + ":fwupd", + "//ash/constants", + "//base/test:test_support", + "//dbus:test_support", + "//testing/gmock", + "//testing/gtest", + ] + + sources = [ "fwupd_client_unittest.cc" ] +}
diff --git a/chromeos/dbus/fwupd/DEPS b/chromeos/dbus/fwupd/DEPS new file mode 100644 index 0000000..5aa4ceb6 --- /dev/null +++ b/chromeos/dbus/fwupd/DEPS
@@ -0,0 +1,3 @@ +include_rules = [ + "+ash/constants", +] \ No newline at end of file
diff --git a/chromeos/dbus/fwupd/OWNERS b/chromeos/dbus/fwupd/OWNERS new file mode 100644 index 0000000..cbaa826 --- /dev/null +++ b/chromeos/dbus/fwupd/OWNERS
@@ -0,0 +1,2 @@ +jimmyxgong@chromium.org +zentaro@chromium.org \ No newline at end of file
diff --git a/chromeos/dbus/fwupd/fake_fwupd_client.cc b/chromeos/dbus/fwupd/fake_fwupd_client.cc new file mode 100644 index 0000000..e33049e --- /dev/null +++ b/chromeos/dbus/fwupd/fake_fwupd_client.cc
@@ -0,0 +1,13 @@ +// Copyright 2021 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/dbus/fwupd/fake_fwupd_client.h" + +namespace chromeos { + +FakeFwupdClient::FakeFwupdClient() = default; +FakeFwupdClient::~FakeFwupdClient() = default; +void FakeFwupdClient::Init(dbus::Bus* bus) {} + +} // namespace chromeos \ No newline at end of file
diff --git a/chromeos/dbus/fwupd/fake_fwupd_client.h b/chromeos/dbus/fwupd/fake_fwupd_client.h new file mode 100644 index 0000000..9eed98c --- /dev/null +++ b/chromeos/dbus/fwupd/fake_fwupd_client.h
@@ -0,0 +1,27 @@ +// Copyright 2021 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_DBUS_FWUPD_FAKE_FWUPD_CLIENT_H_ +#define CHROMEOS_DBUS_FWUPD_FAKE_FWUPD_CLIENT_H_ + +#include "base/component_export.h" +#include "base/macros.h" +#include "chromeos/dbus/fwupd/fwupd_client.h" + +namespace chromeos { + +class COMPONENT_EXPORT(CHROMEOS_DBUS_FUWPD) FakeFwupdClient + : public FwupdClient { + public: + FakeFwupdClient(); + FakeFwupdClient(const FakeFwupdClient&) = delete; + FakeFwupdClient& operator=(const FakeFwupdClient&) = delete; + ~FakeFwupdClient() override; + + void Init(dbus::Bus* bus) override; +}; + +} // namespace chromeos + +#endif // CHROMEOS_DBUS_FWUPD_FAKE_FWUPD_CLIENT_H_
diff --git a/chromeos/dbus/fwupd/fwupd_client.cc b/chromeos/dbus/fwupd/fwupd_client.cc new file mode 100644 index 0000000..504b579 --- /dev/null +++ b/chromeos/dbus/fwupd/fwupd_client.cc
@@ -0,0 +1,94 @@ +// Copyright 2021 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/dbus/fwupd/fwupd_client.h" + +#include <memory> + +#include "ash/constants/ash_features.h" +#include "base/bind.h" +#include "dbus/bus.h" +#include "dbus/message.h" +#include "dbus/object_proxy.h" + +namespace chromeos { + +namespace { + +FwupdClient* g_instance = nullptr; + +const char kFwupdServiceName[] = "org.freedesktop.fwupd"; +const char kFwupdServicePath[] = "/"; +const char kFwupdServiceInterface[] = "org.freedesktop.fwupd"; +const char kFwupdDeviceAddedSignalName[] = "DeviceAdded"; +} // namespace + +class FwupdClientImpl : public FwupdClient { + public: + FwupdClientImpl(); + FwupdClientImpl(const FwupdClientImpl&) = delete; + FwupdClientImpl& operator=(const FwupdClientImpl&) = delete; + ~FwupdClientImpl() override; + + protected: + void Init(dbus::Bus* bus) override { + if (!features::IsFirmwareUpdaterAppEnabled()) + return; + + proxy_ = bus->GetObjectProxy(kFwupdServiceName, + dbus::ObjectPath(kFwupdServicePath)); + + proxy_->ConnectToSignal( + kFwupdServiceInterface, kFwupdDeviceAddedSignalName, + base::BindRepeating(&FwupdClientImpl::OnDeviceAddedReceived, + weak_ptr_factory_.GetWeakPtr()), + base::BindOnce(&FwupdClientImpl::OnSignalConnected, + weak_ptr_factory_.GetWeakPtr())); + } + + private: + void OnSignalConnected(const std::string& interface_name, + const std::string& signal_name, + bool is_connected) { + if (!is_connected) { + LOG(ERROR) << "Failed to connect to signal " << signal_name; + } + DCHECK_EQ(kFwupdServiceInterface, interface_name); + } + + // TODO(swifton): This is a stub implementation. + void OnDeviceAddedReceived(dbus::Signal* signal) { + if (client_is_in_testing_mode_) { + ++device_signal_call_count_for_testing_; + } + } + + dbus::ObjectProxy* proxy_ = nullptr; + + // Note: This should remain the last member so it'll be destroyed and + // invalidate its weak pointers before any other members are destroyed. + base::WeakPtrFactory<FwupdClientImpl> weak_ptr_factory_{this}; +}; + +FwupdClientImpl::FwupdClientImpl() { + DCHECK(!g_instance); + g_instance = this; +} + +FwupdClientImpl::~FwupdClientImpl() { + DCHECK_EQ(g_instance, this); + g_instance = nullptr; +} + +// static +std::unique_ptr<FwupdClient> FwupdClient::Create() { + return std::make_unique<FwupdClientImpl>(); +} + +// static +FwupdClient* FwupdClient::Get() { + return g_instance; +} + +} // namespace chromeos
diff --git a/chromeos/dbus/fwupd/fwupd_client.h b/chromeos/dbus/fwupd/fwupd_client.h new file mode 100644 index 0000000..1a0bff0 --- /dev/null +++ b/chromeos/dbus/fwupd/fwupd_client.h
@@ -0,0 +1,39 @@ +// Copyright 2021 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_DBUS_FWUPD_FWUPD_CLIENT_H_ +#define CHROMEOS_DBUS_FWUPD_FWUPD_CLIENT_H_ + +#include <memory> + +#include "base/component_export.h" +#include "chromeos/dbus/dbus_client.h" + +namespace chromeos { +// FwupdClient is used for handling signals from the fwupd daemon. +class COMPONENT_EXPORT(CHROMEOS_DBUS_FUWPD) FwupdClient : public DBusClient { + public: + // Create() should be used instead. + FwupdClient() = default; + FwupdClient(const FwupdClient&) = delete; + FwupdClient& operator=(const FwupdClient&) = delete; + ~FwupdClient() override = default; + + // Factory function. + static std::unique_ptr<FwupdClient> Create(); + + // Returns the global instance if initialized. May return null. + static FwupdClient* Get(); + + protected: + friend class FwupdClientTest; + + // Auxiliary variables for testing. + // TODO(swifton): Replace this with an observer. + bool client_is_in_testing_mode_ = false; + int device_signal_call_count_for_testing_ = 0; +}; +} // namespace chromeos + +#endif // CHROMEOS_DBUS_FWUPD_FWUPD_CLIENT_H_
diff --git a/chromeos/dbus/fwupd/fwupd_client_unittest.cc b/chromeos/dbus/fwupd/fwupd_client_unittest.cc new file mode 100644 index 0000000..e1e7d83b --- /dev/null +++ b/chromeos/dbus/fwupd/fwupd_client_unittest.cc
@@ -0,0 +1,107 @@ +// Copyright 2021 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/dbus/fwupd/fwupd_client.h" + +#include "ash/constants/ash_features.h" +#include "base/memory/scoped_refptr.h" +#include "base/test/scoped_feature_list.h" +#include "base/test/task_environment.h" +#include "dbus/mock_bus.h" +#include "dbus/mock_object_proxy.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +using ::testing::_; + +namespace { +const char kFwupdServiceName[] = "org.freedesktop.fwupd"; +const char kFwupdServicePath[] = "/"; +const char kFwupdDeviceAddedSignalName[] = "DeviceAdded"; +} // namespace + +namespace chromeos { + +class FwupdClientTest : public testing::Test { + public: + FwupdClientTest() { + scoped_feature_list_.InitAndEnableFeature( + ::ash::features::kFirmwareUpdaterApp); + + dbus::Bus::Options options; + options.bus_type = dbus::Bus::SYSTEM; + bus_ = base::MakeRefCounted<dbus::MockBus>(options); + + dbus::ObjectPath fwupd_service_path(kFwupdServicePath); + proxy_ = base::MakeRefCounted<dbus::MockObjectProxy>( + bus_.get(), kFwupdServiceName, fwupd_service_path); + + EXPECT_CALL(*bus_.get(), + GetObjectProxy(kFwupdServiceName, fwupd_service_path)) + .WillRepeatedly(testing::Return(proxy_.get())); + + EXPECT_CALL(*proxy_, DoConnectToSignal(kFwupdServiceName, _, _, _)) + .WillRepeatedly(Invoke(this, &FwupdClientTest::ConnectToSignal)); + + fwupd_client_ = FwupdClient::Create(); + fwupd_client_->Init(bus_.get()); + fwupd_client_->client_is_in_testing_mode_ = true; + } + + FwupdClientTest(const FwupdClientTest&) = delete; + FwupdClientTest& operator=(const FwupdClientTest&) = delete; + ~FwupdClientTest() override = default; + + int GetDeviceSignalCallCount() { + return fwupd_client_->device_signal_call_count_for_testing_; + } + + protected: + // Synchronously passes |signal| to |client_|'s handler, simulating the signal + // being emitted by fwupd. + void EmitSignal(const std::string& signal_name) { + dbus::Signal signal(kFwupdServiceName, signal_name); + const auto callback = signal_callbacks_.find(signal_name); + ASSERT_TRUE(callback != signal_callbacks_.end()) + << "Client didn't register for signal " << signal_name; + callback->second.Run(&signal); + } + + private: + // Handles calls to |proxy_|'s ConnectToSignal() method. + void ConnectToSignal( + const std::string& interface_name, + const std::string& signal_name, + dbus::ObjectProxy::SignalCallback signal_callback, + dbus::ObjectProxy::OnConnectedCallback* on_connected_callback) { + CHECK_EQ(interface_name, kFwupdServiceName); + signal_callbacks_[signal_name] = signal_callback; + + task_environment_.GetMainThreadTaskRunner()->PostTask( + FROM_HERE, + base::BindOnce(std::move(*on_connected_callback), interface_name, + signal_name, true /* success */)); + } + + // Maps from fwupd signal name to the corresponding callback provided by + // |client_|. + base::flat_map<std::string, dbus::ObjectProxy::SignalCallback> + signal_callbacks_; + + base::test::SingleThreadTaskEnvironment task_environment_; + + base::test::ScopedFeatureList scoped_feature_list_; + + scoped_refptr<dbus::MockBus> bus_; + scoped_refptr<dbus::MockObjectProxy> proxy_; + std::unique_ptr<FwupdClient> fwupd_client_; +}; + +// TODO (swifton): Rewrite this test with an observer when it's available. +TEST_F(FwupdClientTest, AddOneDevice) { + EmitSignal(kFwupdDeviceAddedSignalName); + EXPECT_EQ(1, GetDeviceSignalCallCount()); +} + +} // namespace chromeos
diff --git a/chromeos/dbus/rmad/fake_rmad_client.h b/chromeos/dbus/rmad/fake_rmad_client.h index c8f93d1..b6ff49b 100644 --- a/chromeos/dbus/rmad/fake_rmad_client.h +++ b/chromeos/dbus/rmad/fake_rmad_client.h
@@ -69,7 +69,8 @@ std::vector<rmad::GetStateReply> state_replies_; size_t state_index_; rmad::AbortRmaReply abort_rma_reply_; - base::ObserverList<Observer>::Unchecked observers_; + base::ObserverList<Observer, /*check_empty=*/true, /*allow_reentrancy=*/false> + observers_; }; } // namespace chromeos
diff --git a/chromeos/dbus/rmad/rmad_client.cc b/chromeos/dbus/rmad/rmad_client.cc index 588908e..f3c93544 100644 --- a/chromeos/dbus/rmad/rmad_client.cc +++ b/chromeos/dbus/rmad/rmad_client.cc
@@ -63,7 +63,8 @@ bool success); dbus::ObjectProxy* rmad_proxy_ = nullptr; - base::ObserverList<Observer, true, false>::Unchecked observers_; + base::ObserverList<Observer, /*check_empty=*/true, /*allow_reentrancy=*/false> + observers_; // Note: This should remain the last member so it'll be destroyed and // invalidate its weak pointers before any other members are destroyed.
diff --git a/chromeos/dbus/rmad/rmad_client.h b/chromeos/dbus/rmad/rmad_client.h index dda0ce9..f8f3ba9b 100644 --- a/chromeos/dbus/rmad/rmad_client.h +++ b/chromeos/dbus/rmad/rmad_client.h
@@ -6,6 +6,7 @@ #define CHROMEOS_DBUS_RMAD_RMAD_CLIENT_H_ #include "base/component_export.h" +#include "base/observer_list_types.h" #include "chromeos/dbus/dbus_method_call_status.h" #include "chromeos/dbus/rmad/rmad.pb.h" @@ -23,10 +24,8 @@ class COMPONENT_EXPORT(RMAD) RmadClient { public: // Interface for observing signals from rmad. - class Observer { + class Observer : public base::CheckedObserver { public: - virtual ~Observer() {} - // Called when an error occurs outside of state transitions. // e.g. while calibrating devices. virtual void Error(rmad::RmadErrorCode error) {}
diff --git a/chromeos/lacros/lacros_service.cc b/chromeos/lacros/lacros_service.cc index 1090a1d..8a7f7e1 100644 --- a/chromeos/lacros/lacros_service.cc +++ b/chromeos/lacros/lacros_service.cc
@@ -25,6 +25,7 @@ #include "chromeos/crosapi/mojom/clipboard_history.mojom.h" #include "chromeos/crosapi/mojom/content_protection.mojom.h" #include "chromeos/crosapi/mojom/crosapi.mojom.h" +#include "chromeos/crosapi/mojom/device_settings_service.mojom.h" #include "chromeos/crosapi/mojom/download_controller.mojom.h" #include "chromeos/crosapi/mojom/drive_integration_service.mojom.h" #include "chromeos/crosapi/mojom/feedback.mojom.h" @@ -227,6 +228,10 @@ crosapi::mojom::DeviceAttributes, &Crosapi::BindDeviceAttributes, Crosapi::MethodMinVersions::kBindDeviceAttributesMinVersion>(); ConstructRemote< + crosapi::mojom::DeviceSettingsService, + &Crosapi::BindDeviceSettingsService, + Crosapi::MethodMinVersions::kBindDeviceSettingsServiceMinVersion>(); + ConstructRemote< crosapi::mojom::DownloadController, &Crosapi::BindDownloadController, Crosapi::MethodMinVersions::kBindDownloadControllerMinVersion>(); ConstructRemote<
diff --git a/chromeos/login/auth/extended_authenticator_impl.cc b/chromeos/login/auth/extended_authenticator_impl.cc index 32c1d95..cd7c4140 100644 --- a/chromeos/login/auth/extended_authenticator_impl.cc +++ b/chromeos/login/auth/extended_authenticator_impl.cc
@@ -251,17 +251,6 @@ LOG(ERROR) << "Extended authenticator cryptohome error, code: " << return_code; - AuthState state = FAILED_MOUNT; - - if (return_code == cryptohome::MOUNT_ERROR_TPM_COMM_ERROR || - return_code == cryptohome::MOUNT_ERROR_TPM_DEFEND_LOCK || - return_code == cryptohome::MOUNT_ERROR_TPM_NEEDS_REBOOT) { - state = FAILED_TPM; - } - - if (return_code == cryptohome::MOUNT_ERROR_USER_DOES_NOT_EXIST) - state = NO_MOUNT; - if (consumer_) { AuthFailure failure(AuthFailure::UNLOCK_FAILED); consumer_->OnAuthFailure(failure);
diff --git a/chromeos/services/bluetooth_config/cros_bluetooth_config.cc b/chromeos/services/bluetooth_config/cros_bluetooth_config.cc index 852ecde..28a9633 100644 --- a/chromeos/services/bluetooth_config/cros_bluetooth_config.cc +++ b/chromeos/services/bluetooth_config/cros_bluetooth_config.cc
@@ -40,8 +40,8 @@ CrosBluetoothConfig::~CrosBluetoothConfig() = default; void CrosBluetoothConfig::SetPrefs(PrefService* logged_in_profile_prefs, - PrefService* device_prefs) { - device_name_manager_->SetPrefs(device_prefs); + PrefService* local_state) { + device_name_manager_->SetPrefs(local_state); } void CrosBluetoothConfig::BindPendingReceiver(
diff --git a/chromeos/services/bluetooth_config/cros_bluetooth_config.h b/chromeos/services/bluetooth_config/cros_bluetooth_config.h index 890bb64..5439fa0 100644 --- a/chromeos/services/bluetooth_config/cros_bluetooth_config.h +++ b/chromeos/services/bluetooth_config/cros_bluetooth_config.h
@@ -40,8 +40,7 @@ ~CrosBluetoothConfig() override; // Sets the PrefServices to be used by classes within CrosBluetoothConfig. - void SetPrefs(PrefService* logged_in_profile_prefs, - PrefService* device_prefs); + void SetPrefs(PrefService* logged_in_profile_prefs, PrefService* local_state); // Binds a PendingReceiver to this instance. Clients wishing to use the // CrosBluetoothConfig API should use this function as an entrypoint.
diff --git a/chromeos/services/bluetooth_config/cros_bluetooth_config_unittest.cc b/chromeos/services/bluetooth_config/cros_bluetooth_config_unittest.cc index 51e89f2..fd571f4 100644 --- a/chromeos/services/bluetooth_config/cros_bluetooth_config_unittest.cc +++ b/chromeos/services/bluetooth_config/cros_bluetooth_config_unittest.cc
@@ -35,7 +35,8 @@ // testing::Test: void SetUp() override { - DeviceNameManagerImpl::RegisterPrefs(test_pref_service_.registry()); + DeviceNameManagerImpl::RegisterLocalStatePrefs( + test_pref_service_.registry()); mock_adapter_ = base::MakeRefCounted<testing::NiceMock<device::MockBluetoothAdapter>>();
diff --git a/chromeos/services/bluetooth_config/device_name_manager.h b/chromeos/services/bluetooth_config/device_name_manager.h index 9d783fa..c2081376 100644 --- a/chromeos/services/bluetooth_config/device_name_manager.h +++ b/chromeos/services/bluetooth_config/device_name_manager.h
@@ -41,7 +41,7 @@ const std::string& nickname) = 0; // Sets the PrefService used to store nicknames. - virtual void SetPrefs(PrefService* pref_service) = 0; + virtual void SetPrefs(PrefService* local_state) = 0; void AddObserver(Observer* observer); void RemoveObserver(Observer* observer);
diff --git a/chromeos/services/bluetooth_config/device_name_manager_impl.cc b/chromeos/services/bluetooth_config/device_name_manager_impl.cc index f59bfe6..b4d344b3 100644 --- a/chromeos/services/bluetooth_config/device_name_manager_impl.cc +++ b/chromeos/services/bluetooth_config/device_name_manager_impl.cc
@@ -27,7 +27,8 @@ } // namespace // static -void DeviceNameManagerImpl::RegisterPrefs(PrefRegistrySimple* registry) { +void DeviceNameManagerImpl::RegisterLocalStatePrefs( + PrefRegistrySimple* registry) { registry->RegisterDictionaryPref(kDeviceIdToNicknameMapPrefName, base::Value(base::Value::Type::DICTIONARY)); } @@ -40,11 +41,11 @@ absl::optional<std::string> DeviceNameManagerImpl::GetDeviceNickname( const std::string& device_id) { - if (!pref_service_) + if (!local_state_) return absl::nullopt; const std::string* nickname = - pref_service_->GetDictionary(kDeviceIdToNicknameMapPrefName) + local_state_->GetDictionary(kDeviceIdToNicknameMapPrefName) ->FindStringKey(device_id); if (!nickname) return absl::nullopt; @@ -68,14 +69,14 @@ return; } - if (!pref_service_) { + if (!local_state_) { BLUETOOTH_LOG(ERROR) << "SetDeviceNickname for device failed because " - "no pref_service_ was set."; + "no local_state_ was set."; return; } base::DictionaryValue* device_id_to_nickname_map = - DictionaryPrefUpdate(pref_service_, kDeviceIdToNicknameMapPrefName).Get(); + DictionaryPrefUpdate(local_state_, kDeviceIdToNicknameMapPrefName).Get(); DCHECK(device_id_to_nickname_map) << "Device ID to nickname map pref is unregistered."; device_id_to_nickname_map->SetStringKey(device_id, nickname); @@ -83,8 +84,8 @@ NotifyDeviceNicknameChanged(device_id); } -void DeviceNameManagerImpl::SetPrefs(PrefService* pref_service) { - pref_service_ = pref_service; +void DeviceNameManagerImpl::SetPrefs(PrefService* local_state) { + local_state_ = local_state; } bool DeviceNameManagerImpl::DoesDeviceExist(
diff --git a/chromeos/services/bluetooth_config/device_name_manager_impl.h b/chromeos/services/bluetooth_config/device_name_manager_impl.h index 1dafd92..f94025d 100644 --- a/chromeos/services/bluetooth_config/device_name_manager_impl.h +++ b/chromeos/services/bluetooth_config/device_name_manager_impl.h
@@ -18,7 +18,7 @@ // Concrete DeviceNameManager implementation that saves entries into Prefs. class DeviceNameManagerImpl : public DeviceNameManager { public: - static void RegisterPrefs(PrefRegistrySimple* registry); + static void RegisterLocalStatePrefs(PrefRegistrySimple* registry); explicit DeviceNameManagerImpl( scoped_refptr<device::BluetoothAdapter> bluetooth_adapter); @@ -29,7 +29,7 @@ const std::string& device_id) override; void SetDeviceNickname(const std::string& device_id, const std::string& nickname) override; - void SetPrefs(PrefService* pref_service) override; + void SetPrefs(PrefService* local_state) override; private: // Returns true if a BluetoothDevice* with identifier |device_id| exists in @@ -37,7 +37,7 @@ bool DoesDeviceExist(const std::string& device_id) const; scoped_refptr<device::BluetoothAdapter> bluetooth_adapter_; - PrefService* pref_service_ = nullptr; + PrefService* local_state_ = nullptr; }; } // namespace bluetooth_config
diff --git a/chromeos/services/bluetooth_config/device_name_manager_impl_unittest.cc b/chromeos/services/bluetooth_config/device_name_manager_impl_unittest.cc index 7559967..e7d93f9 100644 --- a/chromeos/services/bluetooth_config/device_name_manager_impl_unittest.cc +++ b/chromeos/services/bluetooth_config/device_name_manager_impl_unittest.cc
@@ -58,7 +58,8 @@ // testing::Test: void SetUp() override { - DeviceNameManagerImpl::RegisterPrefs(test_pref_service_.registry()); + DeviceNameManagerImpl::RegisterLocalStatePrefs( + test_pref_service_.registry()); mock_adapter_ = base::MakeRefCounted<testing::NiceMock<device::MockBluetoothAdapter>>();
diff --git a/chromeos/services/bluetooth_config/fake_device_name_manager.h b/chromeos/services/bluetooth_config/fake_device_name_manager.h index 96bcc0d..3a2a348e 100644 --- a/chromeos/services/bluetooth_config/fake_device_name_manager.h +++ b/chromeos/services/bluetooth_config/fake_device_name_manager.h
@@ -24,7 +24,7 @@ const std::string& device_id) override; void SetDeviceNickname(const std::string& device_id, const std::string& nickname) override; - void SetPrefs(PrefService* pref_service) override {} + void SetPrefs(PrefService* local_state) override {} private: base::flat_map<std::string, std::string> device_id_to_nickname_map_;
diff --git a/chromeos/services/libassistant/display_connection.cc b/chromeos/services/libassistant/display_connection.cc index 41d5428..f11c1198 100644 --- a/chromeos/services/libassistant/display_connection.cc +++ b/chromeos/services/libassistant/display_connection.cc
@@ -96,11 +96,9 @@ ::assistant::display::DisplayRequest display_request; FillDisplayRequest(display_request); - std::string s; - display_request.SerializeToString(&s); ::assistant::api::OnDisplayRequestRequest request; - request.set_display_request_bytes(s); - assistant_client_->OnDisplayRequest(request); + request.set_display_request_bytes(display_request.SerializeAsString()); + assistant_client_->SendDisplayRequest(request); } void DisplayConnection::FillDisplayRequest(
diff --git a/chromeos/services/libassistant/grpc/assistant_client.h b/chromeos/services/libassistant/grpc/assistant_client.h index e46ffae..acfc75b 100644 --- a/chromeos/services/libassistant/grpc/assistant_client.h +++ b/chromeos/services/libassistant/grpc/assistant_client.h
@@ -127,7 +127,7 @@ virtual void ResetAllDataAndShutdown() = 0; // Display methods. - virtual void OnDisplayRequest(const OnDisplayRequestRequest& request) = 0; + virtual void SendDisplayRequest(const OnDisplayRequestRequest& request) = 0; virtual void AddDisplayEventObserver( GrpcServicesObserver<OnAssistantDisplayEventRequest>* observer) = 0;
diff --git a/chromeos/services/libassistant/grpc/assistant_client_impl.cc b/chromeos/services/libassistant/grpc/assistant_client_impl.cc index 3f3509a..890417a 100644 --- a/chromeos/services/libassistant/grpc/assistant_client_impl.cc +++ b/chromeos/services/libassistant/grpc/assistant_client_impl.cc
@@ -72,6 +72,11 @@ } } +void AssistantClientImpl::AddDeviceStateEventObserver( + GrpcServicesObserver<OnDeviceStateEventRequest>* observer) { + grpc_services_.AddObserver(observer); +} + // static std::unique_ptr<AssistantClient> AssistantClient::Create( std::unique_ptr<assistant_client::AssistantManager> assistant_manager,
diff --git a/chromeos/services/libassistant/grpc/assistant_client_impl.h b/chromeos/services/libassistant/grpc/assistant_client_impl.h index b88731d..6511b58 100644 --- a/chromeos/services/libassistant/grpc/assistant_client_impl.h +++ b/chromeos/services/libassistant/grpc/assistant_client_impl.h
@@ -40,6 +40,9 @@ // ServicesStatusObserver overrides: void OnServicesStatusChanged(ServicesStatus status) override; + void AddDeviceStateEventObserver( + GrpcServicesObserver<OnDeviceStateEventRequest>* observer) override; + private: chromeos::libassistant::GrpcServicesInitializer grpc_services_;
diff --git a/chromeos/services/libassistant/grpc/assistant_client_v1.cc b/chromeos/services/libassistant/grpc/assistant_client_v1.cc index 941c489..7f7090ad 100644 --- a/chromeos/services/libassistant/grpc/assistant_client_v1.cc +++ b/chromeos/services/libassistant/grpc/assistant_client_v1.cc
@@ -197,7 +197,7 @@ observer_ = observer; } - void OnDisplayRequest(const std::string& display_request_bytes) { + void SendDisplayRequest(const std::string& display_request_bytes) { if (!delegate_) { LOG(ERROR) << "Can't send DisplayRequest before delegate is set."; return; @@ -357,9 +357,9 @@ assistant_manager()->ResetAllDataAndShutdown(); } -void AssistantClientV1::OnDisplayRequest( +void AssistantClientV1::SendDisplayRequest( const OnDisplayRequestRequest& request) { - display_connection_->OnDisplayRequest(request.display_request_bytes()); + display_connection_->SendDisplayRequest(request.display_request_bytes()); } void AssistantClientV1::AddDisplayEventObserver(
diff --git a/chromeos/services/libassistant/grpc/assistant_client_v1.h b/chromeos/services/libassistant/grpc/assistant_client_v1.h index 9240147..fcf587c4 100644 --- a/chromeos/services/libassistant/grpc/assistant_client_v1.h +++ b/chromeos/services/libassistant/grpc/assistant_client_v1.h
@@ -52,7 +52,7 @@ const GetSpeakerIdEnrollmentInfoRequest& request, base::OnceCallback<void(bool user_model_exists)> on_done) override; void ResetAllDataAndShutdown() override; - void OnDisplayRequest(const OnDisplayRequestRequest& request) override; + void SendDisplayRequest(const OnDisplayRequestRequest& request) override; void AddDisplayEventObserver( GrpcServicesObserver<OnAssistantDisplayEventRequest>* observer) override; void ResumeCurrentStream() override;
diff --git a/chromeos/services/libassistant/grpc/external_services/BUILD.gn b/chromeos/services/libassistant/grpc/external_services/BUILD.gn index 784da3f2..956101e 100644 --- a/chromeos/services/libassistant/grpc/external_services/BUILD.gn +++ b/chromeos/services/libassistant/grpc/external_services/BUILD.gn
@@ -4,14 +4,18 @@ source_set("grpc_services_initializer") { sources = [ + "event_handler_driver.cc", + "event_handler_driver.h", "grpc_services_initializer.cc", "grpc_services_initializer.h", ] deps = [ ":customer_registration_client", + ":grpc_services_observer", ":heartbeat_event_handler_driver", "//base", + "//chromeos/assistant/internal", "//chromeos/services/libassistant/grpc:grpc_client", "//chromeos/services/libassistant/grpc:grpc_service", "//chromeos/services/libassistant/grpc:grpc_util",
diff --git a/chromeos/services/libassistant/grpc/external_services/event_handler_driver.cc b/chromeos/services/libassistant/grpc/external_services/event_handler_driver.cc new file mode 100644 index 0000000..5994341 --- /dev/null +++ b/chromeos/services/libassistant/grpc/external_services/event_handler_driver.cc
@@ -0,0 +1,32 @@ +// Copyright 2021 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/libassistant/grpc/external_services/event_handler_driver.h" + +#include "chromeos/assistant/internal/libassistant_util.h" + +namespace chromeos { +namespace libassistant { + +namespace { +constexpr char kDeviceStateEventName[] = "DeviceStateEvent"; +constexpr char kHandlerMethodName[] = "OnEventFromLibas"; +} // namespace + +template <> +::assistant::api::RegisterEventHandlerRequest +CreateRegistrationRequest<::assistant::api::DeviceStateEventHandlerInterface>( + const std::string& assistant_service_address) { + ::assistant::api::RegisterEventHandlerRequest request; + request.mutable_device_state_events_to_handle()->set_select_all(true); + auto* external_handler = request.mutable_handler(); + external_handler->set_server_address(assistant_service_address); + external_handler->set_service_name( + chromeos::assistant::GetLibassistGrpcServiceName(kDeviceStateEventName)); + external_handler->set_handler_method(kHandlerMethodName); + return request; +} + +} // namespace libassistant +} // namespace chromeos
diff --git a/chromeos/services/libassistant/grpc/external_services/event_handler_driver.h b/chromeos/services/libassistant/grpc/external_services/event_handler_driver.h new file mode 100644 index 0000000..58fe556 --- /dev/null +++ b/chromeos/services/libassistant/grpc/external_services/event_handler_driver.h
@@ -0,0 +1,157 @@ +// Copyright 2021 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_LIBASSISTANT_GRPC_EXTERNAL_SERVICES_EVENT_HANDLER_DRIVER_H_ +#define CHROMEOS_SERVICES_LIBASSISTANT_GRPC_EXTERNAL_SERVICES_EVENT_HANDLER_DRIVER_H_ + +#include <memory> +#include <string> + +#include "base/memory/weak_ptr.h" +#include "base/observer_list.h" +#include "base/sequence_checker.h" +#include "chromeos/assistant/internal/proto/shared/proto/v2/delegate/event_handler_service.grpc.pb.h" +#include "chromeos/assistant/internal/proto/shared/proto/v2/event_notification_interface.pb.h" +#include "chromeos/services/libassistant/grpc/async_service_driver.h" +#include "chromeos/services/libassistant/grpc/external_services/grpc_services_observer.h" +#include "chromeos/services/libassistant/grpc/grpc_libassistant_client.h" +#include "chromeos/services/libassistant/grpc/rpc_method_driver.h" +#include "third_party/grpc/src/include/grpcpp/grpcpp.h" + +namespace chromeos { +namespace libassistant { + +// Create request to register event handler, setting fields accordingly. It +// cannot be a virtual method because it will be used in constructor. Derived +// class should implement specialized function. +template <typename THandlerInterface> +::assistant::api::RegisterEventHandlerRequest CreateRegistrationRequest( + const std::string& assistant_service_address_); + +// EventHandlerDriver is template base class of each libassistant gRPC +// event handler. There will be one instance for each event type. Whoever wants +// to observe libassistant gRPC event should add themselves as observers. +template <typename THandlerInterface> +class EventHandlerDriver : public AsyncServiceDriver { + public: + template <typename Func> + struct UnwrapTypeFromInterface; + + template <typename TRequest, typename TResponse, typename Scope> + struct UnwrapTypeFromInterface<::grpc::Status ( // NOLINT(whitespace/parens) + Scope::*)(grpc::ServerContext*, const TRequest*, TResponse*)> { + private: + typedef TRequest RequestType; + typedef TResponse ResponseType; + + friend class EventHandlerDriver; + }; + + typedef typename UnwrapTypeFromInterface<decltype( + &THandlerInterface::AsyncService::OnEventFromLibas)>::ResponseType + ResponseType; + typedef typename UnwrapTypeFromInterface<decltype( + &THandlerInterface::AsyncService::OnEventFromLibas)>::RequestType + RequestType; + using EventObserverType = GrpcServicesObserver<RequestType>; + + EventHandlerDriver(::grpc::ServerBuilder* server_builder, + GrpcLibassistantClient* libassistant_client, + const std::string& assistant_service_address) + : AsyncServiceDriver(server_builder), + libassistant_client_(libassistant_client), + assistant_service_address_(assistant_service_address) { + DCHECK(server_builder); + DCHECK(libassistant_client_); + + server_builder_->RegisterService(&service_); + } + + ~EventHandlerDriver() override = default; + + void StartRegistration() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + // Make request to libassistant, registering handler. + ::assistant::api::RegisterEventHandlerRequest request = + CreateRegistrationRequest<THandlerInterface>( + assistant_service_address_); + StateConfig config; + config.max_retries = 5; + config.timeout_in_ms = 3000; + libassistant_client_->RegisterEventHandler( + request, + base::BindOnce(&EventHandlerDriver::OnRegisterEventHandlerDone, + weak_factory_.GetWeakPtr()), + std::move(config)); + } + + void AddObserver(EventObserverType* const observer) { + observers_.AddObserver(observer); + } + + void RemoveObserver(EventObserverType* const observer) { + observers_.RemoveObserver(observer); + } + + private: + void HandleEvent( + grpc::ServerContext* context, + const RequestType* request, + base::OnceCallback<void(const grpc::Status&, const ResponseType&)> done) { + for (auto& observer : observers_) { + observer.OnGrpcMessage(*request); + } + + ResponseType response; + std::move(done).Run(grpc::Status::OK, response); + } + + void OnRegisterEventHandlerDone( + const ::grpc::Status& status, + const ::assistant::api::RegisterEventHandlerResponse& response) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + if (!status.ok()) { + LOG(ERROR) << "Failed to register event handler. code: " + << status.error_code() << ". Msg: " << status.error_message(); + } + } + + // AsyncServiceDriver implementation: + void StartCQ(::grpc::ServerCompletionQueue* cq) override { + rpc_event_driver_ = + std::make_unique<RpcMethodDriver<RequestType, ResponseType>>( + cq, + base::BindRepeating( + &THandlerInterface::AsyncService::RequestOnEventFromLibas, + async_service_weak_factory_.GetWeakPtr()), + base::BindRepeating( + &EventHandlerDriver<THandlerInterface>::HandleEvent, + weak_factory_.GetWeakPtr())); + } + + std::unique_ptr<RpcMethodDriver<RequestType, ResponseType>> rpc_event_driver_; + + typename THandlerInterface::AsyncService service_; + + GrpcLibassistantClient* libassistant_client_; + const std::string assistant_service_address_; + + base::ObserverList<EventObserverType> observers_; + + // This sequence checker ensures that all callbacks are called on the main + // sequence. + SEQUENCE_CHECKER(sequence_checker_); + + base::WeakPtrFactory<typename THandlerInterface::AsyncService> + async_service_weak_factory_{&service_}; + base::WeakPtrFactory<EventHandlerDriver<THandlerInterface>> weak_factory_{ + this}; +}; + +} // namespace libassistant +} // namespace chromeos + +#endif // CHROMEOS_SERVICES_LIBASSISTANT_GRPC_EXTERNAL_SERVICES_EVENT_HANDLER_DRIVER_H_i
diff --git a/chromeos/services/libassistant/grpc/external_services/grpc_services_initializer.cc b/chromeos/services/libassistant/grpc/external_services/grpc_services_initializer.cc index 777c0be..dc6452d 100644 --- a/chromeos/services/libassistant/grpc/external_services/grpc_services_initializer.cc +++ b/chromeos/services/libassistant/grpc/external_services/grpc_services_initializer.cc
@@ -74,11 +74,27 @@ DVLOG(1) << "Started ChromeOS Assistant gRPC service"; + RegisterEventHandlers(); StartCQ(); customer_registration_client_->Start(); return true; } +// AddObserver and RemoveObserver for each handler driver +void GrpcServicesInitializer::AddObserver( + GrpcServicesObserver<::assistant::api::OnDeviceStateEventRequest>* + observer) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + device_state_event_handler_driver_->AddObserver(observer); +} + +void GrpcServicesInitializer::RemoveObserver( + GrpcServicesObserver<::assistant::api::OnDeviceStateEventRequest>* + observer) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + device_state_event_handler_driver_->RemoveObserver(observer); +} + GrpcLibassistantClient& GrpcServicesInitializer::GrpcLibassistantClient() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); return *libassistant_client_; @@ -86,11 +102,16 @@ void GrpcServicesInitializer::InitDrivers(grpc::ServerBuilder* server_builder) { // Inits heartbeat driver. - auto heartbeat_driver = + heartbeat_driver_ = std::make_unique<HeartbeatEventHandlerDriver>(&server_builder_); - heartbeat_event_observation_.Observe(heartbeat_driver.get()); + heartbeat_event_observation_.Observe(heartbeat_driver_.get()); + service_drivers_.emplace_back(heartbeat_driver_.get()); - service_drivers_.emplace_back(std::move(heartbeat_driver)); + // Inits other event handler drivers. + device_state_event_handler_driver_ = std::make_unique< + EventHandlerDriver<::assistant::api::DeviceStateEventHandlerInterface>>( + &server_builder_, libassistant_client_.get(), assistant_service_address_); + service_drivers_.emplace_back(device_state_event_handler_driver_.get()); } void GrpcServicesInitializer::InitLibassistGrpcClient() { @@ -120,5 +141,9 @@ RegisterServicesAndInitCQ(&server_builder_); } +void GrpcServicesInitializer::RegisterEventHandlers() { + device_state_event_handler_driver_->StartRegistration(); +} + } // namespace libassistant } // namespace chromeos
diff --git a/chromeos/services/libassistant/grpc/external_services/grpc_services_initializer.h b/chromeos/services/libassistant/grpc/external_services/grpc_services_initializer.h index b0403a9..f20d579 100644 --- a/chromeos/services/libassistant/grpc/external_services/grpc_services_initializer.h +++ b/chromeos/services/libassistant/grpc/external_services/grpc_services_initializer.h
@@ -12,12 +12,21 @@ #include "base/scoped_observation.h" #include "base/sequence_checker.h" #include "chromeos/services/libassistant/grpc/external_services/customer_registration_client.h" +#include "chromeos/services/libassistant/grpc/external_services/event_handler_driver.h" +#include "chromeos/services/libassistant/grpc/external_services/grpc_services_observer.h" #include "chromeos/services/libassistant/grpc/external_services/heartbeat_event_handler_driver.h" #include "chromeos/services/libassistant/grpc/grpc_client_thread.h" #include "chromeos/services/libassistant/grpc/services_initializer_base.h" #include "chromeos/services/libassistant/grpc/services_status_provider.h" #include "third_party/grpc/src/include/grpcpp/server_builder.h" +namespace assistant { +namespace api { +class DeviceStateEventHandlerInterface; +class OnDeviceStateEventRequest; +} // namespace api +} // namespace assistant + namespace chromeos { namespace libassistant { @@ -40,6 +49,14 @@ // call. Returns false if the attempt to start a gRPC server failed. bool Start(); + // Add/Remove observer for each handler driver. + void AddObserver( + GrpcServicesObserver<::assistant::api::OnDeviceStateEventRequest>* + observer); + void RemoveObserver( + GrpcServicesObserver<::assistant::api::OnDeviceStateEventRequest>* + observer); + // Expose a reference to |GrpcLibassistantClient|. GrpcLibassistantClient& GrpcLibassistantClient(); @@ -65,6 +82,8 @@ // This should be called before Start(). void InitAssistantGrpcServer(); + void RegisterEventHandlers(); + // Address of assistant gRPC server. const std::string assistant_service_address_; // Address of Libassistant gRPC server. @@ -88,6 +107,12 @@ std::unique_ptr<chromeos::libassistant::CustomerRegistrationClient> customer_registration_client_; + std::unique_ptr<HeartbeatEventHandlerDriver> heartbeat_driver_; + + std::unique_ptr< + EventHandlerDriver<::assistant::api::DeviceStateEventHandlerInterface>> + device_state_event_handler_driver_; + base::WeakPtrFactory<GrpcServicesInitializer> weak_factory_{this}; };
diff --git a/chromeos/services/libassistant/grpc/grpc_libassistant_client.cc b/chromeos/services/libassistant/grpc/grpc_libassistant_client.cc index 81a76a8..4ad2a08 100644 --- a/chromeos/services/libassistant/grpc/grpc_libassistant_client.cc +++ b/chromeos/services/libassistant/grpc/grpc_libassistant_client.cc
@@ -45,6 +45,7 @@ GrpcLibassistantClient::~GrpcLibassistantClient() = default; LIBAS_GRPC_CLIENT_METHOD("CustomerRegistrationService", RegisterCustomer) +LIBAS_GRPC_CLIENT_METHOD("EventNotificationService", RegisterEventHandler) } // namespace libassistant } // namespace chromeos
diff --git a/chromeos/services/libassistant/grpc/grpc_libassistant_client.h b/chromeos/services/libassistant/grpc/grpc_libassistant_client.h index 81828fe9..58828e6b 100644 --- a/chromeos/services/libassistant/grpc/grpc_libassistant_client.h +++ b/chromeos/services/libassistant/grpc/grpc_libassistant_client.h
@@ -8,6 +8,7 @@ #include <memory> #include "chromeos/assistant/internal/proto/shared/proto/v2/customer_registration_interface.pb.h" +#include "chromeos/assistant/internal/proto/shared/proto/v2/event_notification_interface.pb.h" #include "chromeos/services/libassistant/grpc/grpc_client_thread.h" #include "chromeos/services/libassistant/grpc/grpc_state.h" #include "chromeos/services/libassistant/grpc/grpc_util.h" @@ -43,6 +44,9 @@ // register themselves before allowing to use libassistant services. LIBAS_GRPC_CLIENT_INTERFACE(RegisterCustomer) + // EventNotificationService: + LIBAS_GRPC_CLIENT_INTERFACE(RegisterEventHandler) + private: // This channel will be shared between all stubs used to communicate with // multiple services. All channels are reference counted and will be freed
diff --git a/chromeos/services/libassistant/grpc/services_initializer_base.cc b/chromeos/services/libassistant/grpc/services_initializer_base.cc index e9f6cc4..d41e645 100644 --- a/chromeos/services/libassistant/grpc/services_initializer_base.cc +++ b/chromeos/services/libassistant/grpc/services_initializer_base.cc
@@ -36,7 +36,7 @@ void ServicesInitializerBase::StartCQ() { // Initialize completion queues for each service. - for (auto& driver : service_drivers_) { + for (auto* const driver : service_drivers_) { driver->StartCQ(cq_.get()); } cq_thread_.task_runner()->PostTask(
diff --git a/chromeos/services/libassistant/grpc/services_initializer_base.h b/chromeos/services/libassistant/grpc/services_initializer_base.h index 2da3964..160ea8d9 100644 --- a/chromeos/services/libassistant/grpc/services_initializer_base.h +++ b/chromeos/services/libassistant/grpc/services_initializer_base.h
@@ -46,7 +46,10 @@ void ScanCQInternal(); std::unique_ptr<grpc::ServerCompletionQueue> cq_; - std::vector<std::unique_ptr<AsyncServiceDriver>> service_drivers_; + + // Drivers are owned by the subclass that creates them, e.g. + // `GrpcServicesInitializer`. + std::vector<AsyncServiceDriver*> service_drivers_; // Use a dedicated thread to poll completion queue. Will also responsible // for cleaning up the tags returned by calling cq_->Next() after they are
diff --git a/chromeos/services/libassistant/test_support/fake_assistant_client.cc b/chromeos/services/libassistant/test_support/fake_assistant_client.cc index b1dec15..b27a4b5f 100644 --- a/chromeos/services/libassistant/test_support/fake_assistant_client.cc +++ b/chromeos/services/libassistant/test_support/fake_assistant_client.cc
@@ -58,7 +58,7 @@ void FakeAssistantClient::ResetAllDataAndShutdown() {} -void FakeAssistantClient::OnDisplayRequest( +void FakeAssistantClient::SendDisplayRequest( const OnDisplayRequestRequest& request) {} void FakeAssistantClient::AddDisplayEventObserver(
diff --git a/chromeos/services/libassistant/test_support/fake_assistant_client.h b/chromeos/services/libassistant/test_support/fake_assistant_client.h index 8866728..b683d32 100644 --- a/chromeos/services/libassistant/test_support/fake_assistant_client.h +++ b/chromeos/services/libassistant/test_support/fake_assistant_client.h
@@ -53,7 +53,7 @@ const GetSpeakerIdEnrollmentInfoRequest& request, base::OnceCallback<void(bool user_model_exists)> on_done) override; void ResetAllDataAndShutdown() override; - void OnDisplayRequest(const OnDisplayRequestRequest& request) override; + void SendDisplayRequest(const OnDisplayRequestRequest& request) override; void AddDisplayEventObserver( GrpcServicesObserver<OnAssistantDisplayEventRequest>* observer) override; void ResumeCurrentStream() override;
diff --git a/chromeos/services/secure_channel/ble_advertiser_impl_unittest.cc b/chromeos/services/secure_channel/ble_advertiser_impl_unittest.cc index 80216e79..9a25086 100644 --- a/chromeos/services/secure_channel/ble_advertiser_impl_unittest.cc +++ b/chromeos/services/secure_channel/ble_advertiser_impl_unittest.cc
@@ -498,7 +498,6 @@ AddAdvertisementRequest(pair_1, ConnectionPriority::kLow); FakeErrorTolerantBleAdvertisement* advertisement_1 = GetLastCreatedAdvertisement(pair_1); - FakeOneShotTimer* timer_1 = GetLastCreatedTimer(); AddAdvertisementRequest(pair_2, ConnectionPriority::kLow); FakeErrorTolerantBleAdvertisement* advertisement_2 = @@ -525,7 +524,6 @@ // stopping is asynchronous. EXPECT_EQ(2u, GetNumAdvertisementsCreated()); EXPECT_EQ(3u, GetNumTimersCreated()); - timer_1 = GetLastCreatedTimer(); VerifyDelegateNotifiedOnAdvertisingSlotEnded( pair_1, true /* expected_replaced_by_higher_priority_advertisement */, 0u /* expected_index */); @@ -639,7 +637,6 @@ EXPECT_EQ(7u, GetNumAdvertisementsCreated()); EXPECT_EQ(8u, GetNumTimersCreated()); EXPECT_EQ(4u, GetNumSlotEndedDelegateCallbacks()); - timer_1 = GetLastCreatedTimer(); advertisement_1->InvokeStopCallback(); EXPECT_EQ(8u, GetNumAdvertisementsCreated()); advertisement_1 = GetLastCreatedAdvertisement(pair_2);
diff --git a/chromeos/tast_control.gni b/chromeos/tast_control.gni index ef9a354f..b53e9c3 100644 --- a/chromeos/tast_control.gni +++ b/chromeos/tast_control.gni
@@ -47,6 +47,9 @@ # b/201197372 "crostini.AppEmacs", + + # crbug.com/1259127 + "ui.TabletOperations", ] # To disable a specific test in lacros_all_tast_tests, add it the following
diff --git a/components/app_restore/app_restore_arc_info.cc b/components/app_restore/app_restore_arc_info.cc index 4ce71cc..42e97a8 100644 --- a/components/app_restore/app_restore_arc_info.cc +++ b/components/app_restore/app_restore_arc_info.cc
@@ -43,6 +43,11 @@ observer.OnArcConnectionChanged(is_connection_ready); } +void AppRestoreArcInfo::NotifyPlayStoreEnabledChanged(bool enabled) { + for (auto& observer : observers_) + observer.OnArcPlayStoreEnabledChanged(enabled); +} + void AppRestoreArcInfo::NotifyTaskThemeColorUpdated(int32_t task_id, uint32_t primary_color, uint32_t status_bar_color) {
diff --git a/components/app_restore/app_restore_arc_info.h b/components/app_restore/app_restore_arc_info.h index a545cd58..00da9ec 100644 --- a/components/app_restore/app_restore_arc_info.h +++ b/components/app_restore/app_restore_arc_info.h
@@ -35,6 +35,9 @@ uint32_t primary_color, uint32_t status_bar_color) {} + // Invoked when Google Play Store is enabled or disabled. + virtual void OnArcPlayStoreEnabledChanged(bool enabled) {} + protected: ~Observer() override = default; }; @@ -54,6 +57,7 @@ int32_t session_id); void NotifyTaskDestroyed(int32_t task_id); void NotifyArcConnectionChanged(bool is_connection_ready); + void NotifyPlayStoreEnabledChanged(bool enabled); void NotifyTaskThemeColorUpdated(int32_t task_id, uint32_t primary_color, uint32_t status_bar_color);
diff --git a/components/app_restore/arc_save_handler.cc b/components/app_restore/arc_save_handler.cc index 4d36c37..6dd50f2 100644 --- a/components/app_restore/arc_save_handler.cc +++ b/components/app_restore/arc_save_handler.cc
@@ -217,6 +217,11 @@ task_id_to_app_id_.erase(task_id); } +void ArcSaveHandler::OnArcPlayStoreEnabledChanged(bool enabled) { + if (!enabled) + task_id_to_app_id_.clear(); +} + void ArcSaveHandler::OnTaskThemeColorUpdated(int32_t task_id, uint32_t primary_color, uint32_t status_bar_color) {
diff --git a/components/app_restore/arc_save_handler.h b/components/app_restore/arc_save_handler.h index 107a896..576c034 100644 --- a/components/app_restore/arc_save_handler.h +++ b/components/app_restore/arc_save_handler.h
@@ -20,6 +20,12 @@ struct WindowInfo; } // namespace app_restore +namespace ash { +namespace full_restore { +class FullRestoreAppLaunchHandlerArcAppBrowserTest; +} +} // namespace ash + namespace aura { class Window; } @@ -60,6 +66,9 @@ // Invoked when the task is destroyed for an ARC app. void OnTaskDestroyed(int32_t task_id); + // Invoked when Google Play Store is enabled or disabled. + void OnArcPlayStoreEnabledChanged(bool enabled); + // Invoked when the task theme color is updated for an ARC app. void OnTaskThemeColorUpdated(int32_t task_id, uint32_t primary_color, @@ -77,6 +86,7 @@ private: friend class FullRestoreSaveHandlerTestApi; + friend class ash::full_restore::FullRestoreAppLaunchHandlerArcAppBrowserTest; // Starts the timer to check whether a task is created for the app launching // (if timer isn't already running).
diff --git a/components/app_restore/full_restore_save_handler.cc b/components/app_restore/full_restore_save_handler.cc index 71a6522..f144934 100644 --- a/components/app_restore/full_restore_save_handler.cc +++ b/components/app_restore/full_restore_save_handler.cc
@@ -205,6 +205,45 @@ arc_save_handler_->set_is_connection_ready(is_connection_ready); } +void FullRestoreSaveHandler::OnArcPlayStoreEnabledChanged(bool enabled) { + if (enabled) + return; + + if (arc_save_handler_) + arc_save_handler_->OnArcPlayStoreEnabledChanged(enabled); + + auto restore_data_it = + profile_path_to_restore_data_.find(active_profile_path_); + if (restore_data_it == profile_path_to_restore_data_.end()) + return; + + auto app_registry_cache_it = + profile_path_to_app_registry_cache_.find(active_profile_path_); + if (app_registry_cache_it == profile_path_to_app_registry_cache_.end()) + return; + + // Get the ARC app list saved in the restore data. + const auto& launch_list = restore_data_it->second.app_id_to_launch_list(); + std::vector<std::string> arc_app_ids; + for (const auto& it : launch_list) { + if (app_registry_cache_it->second->GetAppType(it.first) == + apps::mojom::AppType::kArc) { + arc_app_ids.push_back(it.first); + } + } + + if (arc_app_ids.empty()) + return; + + // Remove all ARC app data from the restore data. + for (const auto& app_id : arc_app_ids) + restore_data_it->second.RemoveApp(app_id); + + pending_save_profile_paths_.insert(active_profile_path_); + + MaybeStartSaveTimer(active_profile_path_); +} + void FullRestoreSaveHandler::OnTaskThemeColorUpdated( int32_t task_id, uint32_t primary_color,
diff --git a/components/app_restore/full_restore_save_handler.h b/components/app_restore/full_restore_save_handler.h index 5b3e1db1..689706e 100644 --- a/components/app_restore/full_restore_save_handler.h +++ b/components/app_restore/full_restore_save_handler.h
@@ -36,6 +36,7 @@ namespace ash { namespace full_restore { class FullRestoreServiceTestHavingFullRestoreFile; +class FullRestoreAppLaunchHandlerArcAppBrowserTest; } } // namespace ash @@ -93,6 +94,7 @@ int32_t session_id) override; void OnTaskDestroyed(int32_t task_id) override; void OnArcConnectionChanged(bool is_connection_ready) override; + void OnArcPlayStoreEnabledChanged(bool enabled) override; void OnTaskThemeColorUpdated(int32_t task_id, uint32_t primary_color, uint32_t status_bar_color) override; @@ -178,6 +180,7 @@ private: friend class FullRestoreSaveHandlerTestApi; friend class ash::full_restore::FullRestoreServiceTestHavingFullRestoreFile; + friend class ash::full_restore::FullRestoreAppLaunchHandlerArcAppBrowserTest; // Map from a profile path to AppLaunchInfos. using AppLaunchInfos = std::map<base::FilePath, std::list<AppLaunchInfoPtr>>;
diff --git a/components/certificate_transparency/data/log_list.json b/components/certificate_transparency/data/log_list.json index 2d89c5b1..f491038 100644 --- a/components/certificate_transparency/data/log_list.json +++ b/components/certificate_transparency/data/log_list.json
@@ -1,6 +1,6 @@ { - "version": "3.58", - "log_list_timestamp": "2021-10-11T01:34:10Z", + "version": "3.59", + "log_list_timestamp": "2021-10-12T01:35:09Z", "operators": [ { "name": "Google",
diff --git a/components/components_strings.grd b/components/components_strings.grd index e414ba39..f2599de 100644 --- a/components/components_strings.grd +++ b/components/components_strings.grd
@@ -301,6 +301,7 @@ <part file="find_in_page_strings.grdp" /> <part file="flags_strings.grdp" /> <part file="fullscreen_control_strings.grdp" /> + <part file="global_media_controls_strings.grdp" /> <part file="heavy_ad_intervention_strings.grdp" /> <part file="history_strings.grdp" /> <part file="javascript_dialogs_strings.grdp" />
diff --git a/components/cronet/url_request_context_config.cc b/components/cronet/url_request_context_config.cc index 4b00c624..8e958be3 100644 --- a/components/cronet/url_request_context_config.cc +++ b/components/cronet/url_request_context_config.cc
@@ -431,7 +431,6 @@ quic_args->FindBoolKey(kQuicEnableSocketRecvOptimization) .value_or(quic_params->enable_socket_recv_optimization); - bool quic_migrate_sessions_on_network_change_v2 = false; int quic_max_time_on_non_default_network_seconds = 0; int quic_max_migrations_to_non_default_network_on_write_error = 0; int quic_max_migrations_to_non_default_network_on_path_degrading = 0; @@ -439,8 +438,6 @@ absl::optional<bool> quic_migrate_sessions_on_network_change_v2_in = quic_args->FindBoolKey(kQuicMigrateSessionsOnNetworkChangeV2); if (quic_migrate_sessions_on_network_change_v2_in.has_value()) { - quic_migrate_sessions_on_network_change_v2 = - quic_migrate_sessions_on_network_change_v2_in.value(); quic_params->migrate_sessions_on_network_change_v2 = quic_migrate_sessions_on_network_change_v2_in.value(); if (quic_args->GetInteger( @@ -463,13 +460,11 @@ } } - bool quic_migrate_idle_sessions = false; int quic_idle_session_migration_period_seconds = 0; absl::optional<bool> quic_migrate_idle_sessions_in = quic_args->FindBoolKey(kQuicMigrateIdleSessions); if (quic_migrate_idle_sessions_in.has_value()) { - quic_migrate_idle_sessions = quic_migrate_idle_sessions_in.value(); quic_params->migrate_idle_sessions = quic_migrate_idle_sessions_in.value(); if (quic_args->GetInteger( @@ -480,12 +475,9 @@ } } - bool quic_migrate_sessions_early_v2 = false; absl::optional<bool> quic_migrate_sessions_early_v2_in = quic_args->FindBoolKey(kQuicMigrateSessionsEarlyV2); if (quic_migrate_sessions_early_v2_in.has_value()) { - quic_migrate_sessions_early_v2 = - quic_migrate_sessions_early_v2_in.value(); quic_params->migrate_sessions_early_v2 = quic_migrate_sessions_early_v2_in.value(); }
diff --git a/components/desks_storage/core/desk_template.cc b/components/desks_storage/core/desk_template.cc deleted file mode 100644 index 03f15ea..0000000 --- a/components/desks_storage/core/desk_template.cc +++ /dev/null
@@ -1,72 +0,0 @@ -// Copyright 2021 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "components/desks_storage/core/desk_template.h" - -#include <memory> - -#include "base/check.h" -#include "base/guid.h" -#include "base/memory/ptr_util.h" -#include "base/strings/string_util.h" -#include "components/sync/protocol/workspace_desk_specifics.pb.h" - -namespace desks_storage { - -namespace { - -// Converts a time object to the format used in sync protobufs -// (Microseconds since the Windows epoch). -int64_t TimeToProtoTime(const base::Time t) { - return t.ToDeltaSinceWindowsEpoch().InMicroseconds(); -} - -// Converts a time field from sync protobufs to a time object. -base::Time ProtoTimeToTime(int64_t proto_t) { - return base::Time::FromDeltaSinceWindowsEpoch(base::Microseconds(proto_t)); -} - -} // namespace - -std::unique_ptr<DeskTemplate> DeskTemplate::FromProto( - const sync_pb::WorkspaceDeskSpecifics& pb_entry) { - const std::string uuid(pb_entry.uuid()); - if (uuid.empty()) - return nullptr; - - const base::Time created_time = ProtoTimeToTime(pb_entry.created_time_usec()); - - // Protobuf parsing enforces utf8 encoding for all strings. - return std::make_unique<DeskTemplate>(uuid, pb_entry.name(), created_time); -} - -std::unique_ptr<DeskTemplate> DeskTemplate::FromRequiredFields( - const std::string& uuid) { - return !uuid.empty() ? std::make_unique<DeskTemplate>(uuid, "", base::Time()) - : nullptr; -} - -DeskTemplate::DeskTemplate(const std::string& uuid, - const std::string& name, - base::Time created_time) - : uuid_(uuid), name_(name), created_time_(created_time) { - DCHECK(!uuid_.empty()); - DCHECK(base::IsStringUTF8(uuid_)); - DCHECK(base::IsStringUTF8(name_)); -} - -DeskTemplate::~DeskTemplate() = default; - -sync_pb::WorkspaceDeskSpecifics DeskTemplate::AsSyncProto() const { - sync_pb::WorkspaceDeskSpecifics pb_entry; - - pb_entry.set_uuid(uuid()); - pb_entry.set_name(name()); - pb_entry.set_created_time_usec(TimeToProtoTime(created_time())); - - // TODO(yzd) copy other data fields - return pb_entry; -} - -} // namespace desks_storage \ No newline at end of file
diff --git a/components/desks_storage/core/desk_template.h b/components/desks_storage/core/desk_template.h deleted file mode 100644 index 4bc8b56..0000000 --- a/components/desks_storage/core/desk_template.h +++ /dev/null
@@ -1,60 +0,0 @@ -// Copyright 2021 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef COMPONENTS_DESKS_STORAGE_CORE_DESK_TEMPLATE_H_ -#define COMPONENTS_DESKS_STORAGE_CORE_DESK_TEMPLATE_H_ - -#include <string> - -#include "base/time/time.h" - -namespace sync_pb { -class WorkspaceDeskSpecifics; -} - -namespace desks_storage { - -// A desk template being saved. The UUID is a unique identifier for a -// template. This class is a temporary placeholder. This could be replaced -// by future ash::DeskTemplate when it is ready. -// -// TODO(crbug/1225727): remove this class. -class DeskTemplate { - public: - // Creates a DeskTemplate from the protobuf format. - static std::unique_ptr<DeskTemplate> FromProto( - const sync_pb::WorkspaceDeskSpecifics& pb_entry); - - // Creates a DeskTemplate consisting of only the required fields. - static std::unique_ptr<DeskTemplate> FromRequiredFields( - const std::string& uuid); - - // Creates a DeskTemplate. - DeskTemplate(const std::string& uuid, - const std::string& name, - base::Time created_time); - DeskTemplate(const DeskTemplate&) = delete; - DeskTemplate& operator=(const DeskTemplate&) = delete; - ~DeskTemplate(); - - const std::string& uuid() const { return uuid_; } - const std::string& name() const { return name_; } - base::Time created_time() const { return created_time_; } - - // Returns a protobuf encoding the content of this DeskTemplate for - // Sync. - sync_pb::WorkspaceDeskSpecifics AsSyncProto() const; - - private: - // The unique random id for the entry. - std::string uuid_; - // The name of the desk template. Might be empty. - std::string name_; - // The time that the desk template was created. - base::Time created_time_; -}; - -} // namespace desks_storage - -#endif // COMPONENTS_DESKS_STORAGE_CORE_DESK_TEMPLATE_H_ \ No newline at end of file
diff --git a/components/desks_storage/core/local_desk_data_manager.cc b/components/desks_storage/core/local_desk_data_manager.cc index 9471107..0822082 100644 --- a/components/desks_storage/core/local_desk_data_manager.cc +++ b/components/desks_storage/core/local_desk_data_manager.cc
@@ -17,7 +17,6 @@ #include "base/values.h" #include "components/app_restore/restore_data.h" #include "components/desks_storage/core/desk_model.h" -#include "components/desks_storage/core/desk_template.h" #include "components/sync/protocol/workspace_desk_specifics.pb.h" #include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/re2/src/re2/re2.h"
diff --git a/components/desks_storage/core/local_desks_data_manager_unittests.cc b/components/desks_storage/core/local_desks_data_manager_unittests.cc index 6120ad4..46487d75 100644 --- a/components/desks_storage/core/local_desks_data_manager_unittests.cc +++ b/components/desks_storage/core/local_desks_data_manager_unittests.cc
@@ -20,7 +20,6 @@ #include "base/threading/thread_task_runner_handle.h" #include "base/time/time.h" #include "build/build_config.h" -#include "components/desks_storage/core/desk_template.h" #include "testing/gtest/include/gtest/gtest.h" namespace desks_storage {
diff --git a/components/discardable_memory/client/client_discardable_shared_memory_manager.cc b/components/discardable_memory/client/client_discardable_shared_memory_manager.cc index 8f2aed0..7dcb204 100644 --- a/components/discardable_memory/client/client_discardable_shared_memory_manager.cc +++ b/components/discardable_memory/client/client_discardable_shared_memory_manager.cc
@@ -357,7 +357,7 @@ reinterpret_cast<size_t>(leftover->shared_memory()->memory()), leftover->length() * base::GetPageSize()); leftover->set_is_locked(false); - heap_->MergeIntoFreeListsClean(std::move(leftover)); + MergeIntoFreeListsClean(std::move(leftover)); } if (pages >= allocation_pages) { @@ -459,7 +459,7 @@ auto span = mem->Purge(now - min_age); if (span) { allocated_memory_.erase(prev); - ReleaseSpan(std::move(span)); + ReleaseSpanLocked(std::move(span)); } } } @@ -540,12 +540,54 @@ if (!span->shared_memory()) return; - heap_->MergeIntoFreeLists(std::move(span)); + MergeIntoFreeLists(std::move(span)); // Bytes of free memory changed. MemoryUsageChanged(heap_->GetSize(), heap_->GetFreelistSize()); } +void ClientDiscardableSharedMemoryManager::ReleaseSpanLocked( + std::unique_ptr<DiscardableSharedMemoryHeap::Span> span) { + DCHECK(span); + + // Delete span instead of merging it into free lists if memory is gone. + if (!span->shared_memory()) + return; + + MergeIntoFreeListsLocked(std::move(span)); + + // Bytes of free memory changed. + MemoryUsageChanged(heap_->GetSize(), heap_->GetFreelistSize()); +} + +void ClientDiscardableSharedMemoryManager::MergeIntoFreeLists( + std::unique_ptr<DiscardableSharedMemoryHeap::Span> span) { + if (ReleaseDiscardableFreeListPages()) { + // We release the memory _without_ the lock held here to avoid performance + // issues on Windows, as releasing memory is a potentially expensive + // operation there. + lock_.Release(); + DiscardableSharedMemoryHeap::ReleaseMemoryIfPossible(span.get()); + lock_.Acquire(); + } + + heap_->MergeIntoFreeLists(std::move(span)); +} + +void ClientDiscardableSharedMemoryManager::MergeIntoFreeListsLocked( + std::unique_ptr<DiscardableSharedMemoryHeap::Span> span) { + if (ReleaseDiscardableFreeListPages()) { + DiscardableSharedMemoryHeap::ReleaseMemoryIfPossible(span.get()); + } + + heap_->MergeIntoFreeLists(std::move(span)); +} + +void ClientDiscardableSharedMemoryManager::MergeIntoFreeListsClean( + std::unique_ptr<DiscardableSharedMemoryHeap::Span> span) { + heap_->MergeIntoFreeListsClean(std::move(span)); +} + base::trace_event::MemoryAllocatorDump* ClientDiscardableSharedMemoryManager::CreateMemoryAllocatorDump( DiscardableSharedMemoryHeap::Span* span,
diff --git a/components/discardable_memory/client/client_discardable_shared_memory_manager.h b/components/discardable_memory/client/client_discardable_shared_memory_manager.h index 055c8f66..e8a1f83 100644 --- a/components/discardable_memory/client/client_discardable_shared_memory_manager.h +++ b/components/discardable_memory/client/client_discardable_shared_memory_manager.h
@@ -185,6 +185,19 @@ EXCLUSIVE_LOCKS_REQUIRED(lock_); void ReleaseSpan(std::unique_ptr<DiscardableSharedMemoryHeap::Span> span) EXCLUSIVE_LOCKS_REQUIRED(lock_); + void ReleaseSpanLocked( + std::unique_ptr<DiscardableSharedMemoryHeap::Span> span) + EXCLUSIVE_LOCKS_REQUIRED(lock_); + + void MergeIntoFreeListsClean( + std::unique_ptr<DiscardableSharedMemoryHeap::Span> span) + EXCLUSIVE_LOCKS_REQUIRED(lock_); + void MergeIntoFreeLists( + std::unique_ptr<DiscardableSharedMemoryHeap::Span> span) + EXCLUSIVE_LOCKS_REQUIRED(lock_); + void MergeIntoFreeListsLocked( + std::unique_ptr<DiscardableSharedMemoryHeap::Span> span) + EXCLUSIVE_LOCKS_REQUIRED(lock_); size_t GetBytesAllocatedLocked() const EXCLUSIVE_LOCKS_REQUIRED(lock_);
diff --git a/components/discardable_memory/client/client_discardable_shared_memory_manager_unittest.cc b/components/discardable_memory/client/client_discardable_shared_memory_manager_unittest.cc index 32bb6a1..bc71ac8 100644 --- a/components/discardable_memory/client/client_discardable_shared_memory_manager_unittest.cc +++ b/components/discardable_memory/client/client_discardable_shared_memory_manager_unittest.cc
@@ -533,5 +533,41 @@ ASSERT_EQ(0u, client->GetDirtyFreedMemoryPageCount()); } +TEST_F(ClientDiscardableSharedMemoryManagerTest, PurgeMultipleTimes) { + base::test::ScopedFeatureList fl; + fl.InitAndEnableFeature(discardable_memory::kReleaseDiscardableFreeListPages); + auto client = + base::MakeRefCounted<TestClientDiscardableSharedMemoryManager>(); + + auto mem1 = + client->AllocateLockedDiscardableMemory(base::GetPageSize() * 1.2); + + task_env_.FastForwardBy(base::TimeDelta::FromSeconds(60)); + + auto mem2 = + client->AllocateLockedDiscardableMemory(base::GetPageSize() * 2.2); + + EXPECT_TRUE(client->IsPurgeScheduled()); + + client->ReleaseFreeMemory(); + EXPECT_TRUE(client->IsPurgeScheduled()); + + task_env_.FastForwardBy( + ClientDiscardableSharedMemoryManager::kScheduledPurgeInterval); + + task_env_.FastForwardBy(base::TimeDelta::FromSeconds(60)); + + EXPECT_TRUE(client->IsPurgeScheduled()); + + client->ReleaseFreeMemory(); + + task_env_.FastForwardBy( + ClientDiscardableSharedMemoryManager::kScheduledPurgeInterval); + + EXPECT_TRUE(client->IsPurgeScheduled()); + + client->ReleaseFreeMemory(); +} + } // namespace } // namespace discardable_memory
diff --git a/components/discardable_memory/common/discardable_shared_memory_heap.cc b/components/discardable_memory/common/discardable_shared_memory_heap.cc index 9ab396a..ed90f3f 100644 --- a/components/discardable_memory/common/discardable_shared_memory_heap.cc +++ b/components/discardable_memory/common/discardable_shared_memory_heap.cc
@@ -26,6 +26,10 @@ const base::Feature kReleaseDiscardableFreeListPages{ "ReleaseDiscardableFreeListPages", base::FEATURE_DISABLED_BY_DEFAULT}; +bool ReleaseDiscardableFreeListPages() { + return base::FeatureList::IsEnabled(kReleaseDiscardableFreeListPages); +} + namespace { bool IsInFreeList(DiscardableSharedMemoryHeap::Span* span) { @@ -188,11 +192,34 @@ return span; } +// static +void DiscardableSharedMemoryHeap::ReleaseMemoryIfPossible(Span* span) { + SCOPED_UMA_HISTOGRAM_TIMER_MICROS("Memory.Discardable.FreeListReleaseTime"); + // Release as much memory as possible before putting it into the freelists + // in order to reduce their size. Getting this memory back is still much + // cheaper than an IPC, while also saving us space in the freelists. + // + // The "+ 1" in the offset is for the SharedState that's at the start of + // the DiscardableSharedMemory. See DiscardableSharedMemory for details on + // what this is used for. We don't want to remove it, so we offset by an + // extra page. + size_t offset = (1 + span->start_) * base::GetPageSize() - + reinterpret_cast<size_t>(span->shared_memory()->memory()); + // Since we always offset by at least one page because of the SharedState, + // our offset should never be 0. + DCHECK_GT(offset, 0u); + span->shared_memory()->ReleaseMemoryIfPossible( + offset, span->length_ * base::GetPageSize()); +} + void DiscardableSharedMemoryHeap::MergeIntoFreeLists( std::unique_ptr<Span> span) { + DCHECK(span->shared_memory_); + if (!base::FeatureList::IsEnabled(kReleaseDiscardableFreeListPages)) { dirty_freed_memory_page_count_ += span->MarkAsDirty(); } + MergeIntoFreeListsClean(std::move(span)); } @@ -200,25 +227,6 @@ std::unique_ptr<Span> span) { DCHECK(span->shared_memory_); - if (base::FeatureList::IsEnabled(kReleaseDiscardableFreeListPages)) { - SCOPED_UMA_HISTOGRAM_TIMER_MICROS("Memory.Discardable.FreeListReleaseTime"); - // Release as much memory as possible before putting it into the freelists - // in order to reduce their size. Getting this memory back is still much - // cheaper than an IPC, while also saving us space in the freelists. - // - // The "+ 1" in the offset is for the SharedState that's at the start of - // the DiscardableSharedMemory. See DiscardableSharedMemory for details on - // what this is used for. We don't want to remove it, so we offset by an - // extra page. - size_t offset = (1 + span->start_) * base::GetPageSize() - - reinterpret_cast<size_t>(span->shared_memory()->memory()); - // Since we always offset by at least one page because of the SharedState, - // our offset should never be 0. - DCHECK_GT(offset, 0u); - span->shared_memory()->ReleaseMemoryIfPossible( - offset, span->length_ * base::GetPageSize()); - } - // First add length of |span| to |num_free_blocks_|. num_free_blocks_ += span->length_;
diff --git a/components/discardable_memory/common/discardable_shared_memory_heap.h b/components/discardable_memory/common/discardable_shared_memory_heap.h index 5fbbbc2..90ffba2 100644 --- a/components/discardable_memory/common/discardable_shared_memory_heap.h +++ b/components/discardable_memory/common/discardable_shared_memory_heap.h
@@ -29,6 +29,8 @@ DISCARDABLE_MEMORY_EXPORT extern const base::Feature kReleaseDiscardableFreeListPages; +DISCARDABLE_MEMORY_EXPORT extern bool ReleaseDiscardableFreeListPages(); + // Implements a heap of discardable shared memory. An array of free lists // is used to keep track of free blocks. class DISCARDABLE_MEMORY_EXPORT DiscardableSharedMemoryHeap { @@ -90,6 +92,8 @@ int32_t id, base::OnceClosure deleted_callback); + static void ReleaseMemoryIfPossible(Span* span); + // Merge |span| into the free lists. This will coalesce |span| with // neighboring free spans when possible. void MergeIntoFreeLists(std::unique_ptr<Span> span);
diff --git a/components/enterprise/browser/reporting/browser_report_generator.cc b/components/enterprise/browser/reporting/browser_report_generator.cc index 328d936..91116a7 100644 --- a/components/enterprise/browser/reporting/browser_report_generator.cc +++ b/components/enterprise/browser/reporting/browser_report_generator.cc
@@ -23,17 +23,9 @@ BrowserReportGenerator::~BrowserReportGenerator() = default; -void BrowserReportGenerator::Generate(ReportType report_type, - ReportCallback callback) { +void BrowserReportGenerator::Generate(ReportCallback callback) { auto report = std::make_unique<em::BrowserReport>(); - GenerateProfileInfo(report_type, report.get()); - delegate_->OnProfileInfoGenerated(report_type); - - if (report_type == ReportType::kExtensionRequest) { - report->set_executable_path(delegate_->GetExecutablePath()); - std::move(callback).Run(std::move(report)); - return; - } + GenerateProfileInfo(report.get()); GenerateBasicInfo(report.get()); // std::move is required here because the function completes the report @@ -41,9 +33,8 @@ delegate_->GeneratePluginsIfNeeded(std::move(callback), std::move(report)); } -void BrowserReportGenerator::GenerateProfileInfo(ReportType report_type, - em::BrowserReport* report) { - for (auto entry : delegate_->GetReportedProfiles(report_type)) { +void BrowserReportGenerator::GenerateProfileInfo(em::BrowserReport* report) { + for (auto entry : delegate_->GetReportedProfiles()) { em::ChromeUserProfileInfo* profile = report->add_chrome_user_profile_infos(); profile->set_id(entry.id);
diff --git a/components/enterprise/browser/reporting/browser_report_generator.h b/components/enterprise/browser/reporting/browser_report_generator.h index cd94c4d..c0b8e280 100644 --- a/components/enterprise/browser/reporting/browser_report_generator.h +++ b/components/enterprise/browser/reporting/browser_report_generator.h
@@ -10,7 +10,6 @@ #include <vector> #include "base/callback_forward.h" -#include "components/enterprise/browser/reporting/report_type.h" namespace enterprise_management { class BrowserReport; @@ -44,15 +43,13 @@ virtual std::string GetExecutablePath() = 0; virtual version_info::Channel GetChannel() = 0; - virtual std::vector<ReportedProfileData> GetReportedProfiles( - ReportType report_type) = 0; + virtual std::vector<ReportedProfileData> GetReportedProfiles() = 0; virtual bool IsExtendedStableChannel() = 0; virtual void GenerateBuildStateInfo( enterprise_management::BrowserReport* report) = 0; virtual void GeneratePluginsIfNeeded( ReportCallback callback, std::unique_ptr<enterprise_management::BrowserReport> report) = 0; - virtual void OnProfileInfoGenerated(ReportType report_type) = 0; }; explicit BrowserReportGenerator(ReportingDelegateFactory* delegate_factory); @@ -64,11 +61,10 @@ // - browser_version, channel, executable_path // - user profiles: id, name, is_detail_available (always be false). // - plugins: name, version, filename, description. - void Generate(ReportType report_type, ReportCallback callback); + void Generate(ReportCallback callback); // Generates user profiles info in the given report instance. - void GenerateProfileInfo(ReportType report_type, - enterprise_management::BrowserReport* report); + void GenerateProfileInfo(enterprise_management::BrowserReport* report); private: std::unique_ptr<Delegate> delegate_;
diff --git a/components/enterprise/browser/reporting/profile_report_generator.cc b/components/enterprise/browser/reporting/profile_report_generator.cc index 4488f9a..9fe3a4a 100644 --- a/components/enterprise/browser/reporting/profile_report_generator.cc +++ b/components/enterprise/browser/reporting/profile_report_generator.cc
@@ -32,8 +32,7 @@ std::unique_ptr<em::ChromeUserProfileInfo> ProfileReportGenerator::MaybeGenerate(const base::FilePath& path, - const std::string& name, - ReportType report_type) { + const std::string& name) { if (!delegate_->Init(path)) { return nullptr; } @@ -41,35 +40,25 @@ report_ = std::make_unique<em::ChromeUserProfileInfo>(); report_->set_id(path.AsUTF8Unsafe()); - if (report_type == ReportType::kExtensionRequest) { - delegate_->GetExtensionRequest(report_.get()); - report_->set_is_detail_available(true); -#if BUILDFLAG(IS_CHROMEOS_ASH) - // Extension request is aggregated at the user level on CrOS. - report_->set_name(name); - delegate_->GetSigninUserInfo(report_.get()); -#endif // BUILDFLAG(IS_CHROMEOS_ASH) - } else { - report_->set_name(name); - report_->set_is_detail_available(true); + report_->set_name(name); + report_->set_is_detail_available(true); - delegate_->GetSigninUserInfo(report_.get()); - if (extensions_enabled_) { - delegate_->GetExtensionInfo(report_.get()); - } - delegate_->GetExtensionRequest(report_.get()); + delegate_->GetSigninUserInfo(report_.get()); + if (extensions_enabled_) { + delegate_->GetExtensionInfo(report_.get()); + } + delegate_->GetExtensionRequest(report_.get()); - if (policies_enabled_) { - // TODO(crbug.com/983151): Upload policy error as their IDs. - auto client = delegate_->MakePolicyConversionsClient(); - policies_ = policy::DictionaryPolicyConversions(std::move(client)) - .EnableConvertTypes(false) - .EnablePrettyPrint(false) - .ToValue(); - GetChromePolicyInfo(); - GetExtensionPolicyInfo(); - GetPolicyFetchTimestampInfo(); - } + if (policies_enabled_) { + // TODO(crbug.com/983151): Upload policy error as their IDs. + auto client = delegate_->MakePolicyConversionsClient(); + policies_ = policy::DictionaryPolicyConversions(std::move(client)) + .EnableConvertTypes(false) + .EnablePrettyPrint(false) + .ToValue(); + GetChromePolicyInfo(); + GetExtensionPolicyInfo(); + GetPolicyFetchTimestampInfo(); } return std::move(report_);
diff --git a/components/enterprise/browser/reporting/profile_report_generator.h b/components/enterprise/browser/reporting/profile_report_generator.h index fe86556..c24607d 100644 --- a/components/enterprise/browser/reporting/profile_report_generator.h +++ b/components/enterprise/browser/reporting/profile_report_generator.h
@@ -10,7 +10,6 @@ #include "base/values.h" #include "components/enterprise/browser/reporting/report_request_definition.h" -#include "components/enterprise/browser/reporting/report_type.h" #include "components/policy/core/browser/policy_conversions_client.h" #include "components/policy/proto/device_management_backend.pb.h" @@ -74,8 +73,7 @@ // generated. std::unique_ptr<enterprise_management::ChromeUserProfileInfo> MaybeGenerate( const base::FilePath& path, - const std::string& name, - ReportType report_type); + const std::string& name); protected: void GetChromePolicyInfo();
diff --git a/components/enterprise/browser/reporting/report_generator.cc b/components/enterprise/browser/reporting/report_generator.cc index be5cf9d..4128360 100644 --- a/components/enterprise/browser/reporting/report_generator.cc +++ b/components/enterprise/browser/reporting/report_generator.cc
@@ -43,13 +43,6 @@ std::unique_ptr<ReportRequest> basic_request, ReportType report_type, ReportCallback callback) { - if (report_type == kExtensionRequest) { - basic_request->add_partial_report_types( - em::PartialReportType::EXTENSION_REQUEST); - GenerateReport(report_type, std::move(callback), std::move(basic_request)); - return; - } - #if BUILDFLAG(IS_CHROMEOS_ASH) delegate_->SetAndroidAppInfos(basic_request.get()); #else @@ -107,7 +100,6 @@ ReportCallback callback, std::unique_ptr<ReportRequest> basic_request) { browser_report_generator_.Generate( - report_type, base::BindOnce(&ReportGenerator::OnBrowserReportReady, weak_ptr_factory_.GetWeakPtr(), std::move(basic_request), report_type, std::move(callback))); @@ -123,7 +115,7 @@ if (report_type != kBrowserVersion) { // Generate a queue of requests containing detailed profile information. std::move(callback).Run( - report_request_queue_generator_.Generate(report_type, *basic_request)); + report_request_queue_generator_.Generate(*basic_request)); return; }
diff --git a/components/enterprise/browser/reporting/report_request_queue_generator.cc b/components/enterprise/browser/reporting/report_request_queue_generator.cc index 3614627..82a1958 100644 --- a/components/enterprise/browser/reporting/report_request_queue_generator.cc +++ b/components/enterprise/browser/reporting/report_request_queue_generator.cc
@@ -54,8 +54,7 @@ } ReportRequestQueueGenerator::ReportRequests -ReportRequestQueueGenerator::Generate(ReportType report_type, - const ReportRequest& basic_request) { +ReportRequestQueueGenerator::Generate(const ReportRequest& basic_request) { ReportRequests requests; size_t basic_request_size = basic_request.ByteSizeLong(); base::UmaHistogramMemoryKB(kBasicRequestSizeMetricsName, @@ -66,8 +65,7 @@ int profile_infos_size = basic_request.browser_report().chrome_user_profile_infos_size(); for (int index = 0; index < profile_infos_size; index++) { - GenerateProfileReportWithIndex(index, report_type, basic_request, - &requests); + GenerateProfileReportWithIndex(index, basic_request, &requests); } base::UmaHistogramMemoryKB(kRequestSizeMetricsName, @@ -81,7 +79,6 @@ void ReportRequestQueueGenerator::GenerateProfileReportWithIndex( int profile_index, - ReportType report_type, const ReportRequest& basic_request, ReportRequests* requests) { DCHECK_LT(profile_index, @@ -91,8 +88,7 @@ auto basic_profile = basic_request.browser_report().chrome_user_profile_infos(profile_index); auto profile_report = profile_report_generator_.MaybeGenerate( - base::FilePath::FromUTF8Unsafe(basic_profile.id()), basic_profile.name(), - report_type); + base::FilePath::FromUTF8Unsafe(basic_profile.id()), basic_profile.name()); // Return if Profile is not loaded and there is no full report. if (!profile_report)
diff --git a/components/enterprise/browser/reporting/report_request_queue_generator.h b/components/enterprise/browser/reporting/report_request_queue_generator.h index 4dcb92af..2b458a7 100644 --- a/components/enterprise/browser/reporting/report_request_queue_generator.h +++ b/components/enterprise/browser/reporting/report_request_queue_generator.h
@@ -12,7 +12,6 @@ #include "build/build_config.h" #include "components/enterprise/browser/reporting/profile_report_generator.h" #include "components/enterprise/browser/reporting/report_request_definition.h" -#include "components/enterprise/browser/reporting/report_type.h" #include "components/policy/proto/device_management_backend.pb.h" namespace enterprise_reporting { @@ -44,14 +43,12 @@ // Generate a queue of requests including full profile info based on given // basic request. - ReportRequests Generate(ReportType report_type, - const ReportRequest& basic_request); + ReportRequests Generate(const ReportRequest& basic_request); private: // Generate request with full profile info at |profile_index| according to // |basic_request|, then store it into |requests|. void GenerateProfileReportWithIndex(int profile_index, - ReportType report_type, const ReportRequest& basic_request, ReportRequests* requests);
diff --git a/components/enterprise/browser/reporting/report_type.h b/components/enterprise/browser/reporting/report_type.h index f244dc6..d1498d4 100644 --- a/components/enterprise/browser/reporting/report_type.h +++ b/components/enterprise/browser/reporting/report_type.h
@@ -10,7 +10,6 @@ enum ReportType : uint32_t { kFull = 0, kBrowserVersion = 1u << 0, - kExtensionRequest = 2u << 1, }; } // namespace enterprise_reporting
diff --git a/components/feature_engagement/public/feature_configurations.cc b/components/feature_engagement/public/feature_configurations.cc index e1e6b2e1..452e9582 100644 --- a/components/feature_engagement/public/feature_configurations.cc +++ b/components/feature_engagement/public/feature_configurations.cc
@@ -478,6 +478,7 @@ config->event_configs.insert( EventConfig("auto_dark_user_education_message_trigger", Comparator(LESS_THAN, 6), 360, 360)); + return config; } if (kIPHInstanceSwitcherFeature.name == feature->name) {
diff --git a/components/global_media_controls/BUILD.gn b/components/global_media_controls/BUILD.gn index 5c377e8..d2763db7 100644 --- a/components/global_media_controls/BUILD.gn +++ b/components/global_media_controls/BUILD.gn
@@ -4,6 +4,7 @@ component("global_media_controls") { public = [ + "public/constants.h", "public/media_dialog_delegate.h", "public/media_item_manager.h", "public/media_item_manager_observer.h", @@ -11,24 +12,36 @@ "public/media_item_ui.h", "public/media_item_ui_observer.h", "public/media_item_ui_observer_set.h", + "public/views/media_item_ui_device_selector.h", + "public/views/media_item_ui_footer.h", + "public/views/media_item_ui_list_view.h", + "public/views/media_item_ui_view.h", ] defines = [ "IS_GLOBAL_MEDIA_CONTROLS_IMPL" ] deps = [ "//base", + "//components/strings:components_strings_grit", + "//components/vector_icons", + "//media", "//skia", + "//ui/color", + "//ui/message_center/public/cpp", ] public_deps = [ "//components/media_message_center", "//services/media_session/public/cpp", + "//ui/views", ] sources = [ "media_item_manager_impl.cc", "media_item_manager_impl.h", "public/media_item_ui_observer_set.cc", + "public/views/media_item_ui_list_view.cc", + "public/views/media_item_ui_view.cc", ] friend = [ ":*" ] @@ -37,15 +50,23 @@ source_set("unit_tests") { testonly = true - sources = [ "media_item_manager_impl_unittest.cc" ] + sources = [ + "media_item_manager_impl_unittest.cc", + "public/views/media_item_ui_list_view_unittest.cc", + "public/views/media_item_ui_view_unittest.cc", + ] deps = [ ":global_media_controls", ":test_support", "//base/test:test_support", + "//components/media_message_center:test_support", "//skia", "//testing/gmock", "//testing/gtest", + "//ui/display:test_support", + "//ui/events:test_support", + "//ui/views:test_support", ] } @@ -61,12 +82,17 @@ "public/test/mock_media_item_manager_observer.h", "public/test/mock_media_item_producer.cc", "public/test/mock_media_item_producer.h", + "public/test/mock_media_item_ui_device_selector.cc", + "public/test/mock_media_item_ui_device_selector.h", + "public/test/mock_media_item_ui_footer.cc", + "public/test/mock_media_item_ui_footer.h", "public/test/mock_media_item_ui_observer.cc", "public/test/mock_media_item_ui_observer.h", ] deps = [ ":global_media_controls", + "//components/media_message_center:test_support", "//skia", "//testing/gmock", ]
diff --git a/components/global_media_controls/DEPS b/components/global_media_controls/DEPS index c6626ef..9cd9e75 100644 --- a/components/global_media_controls/DEPS +++ b/components/global_media_controls/DEPS
@@ -1,4 +1,9 @@ include_rules = [ "+components/media_message_center", + "+components/strings", + "+components/vector_icons", + "+media", "+services/media_session/public", + "+third_party/skia/include/core", + "+ui", ]
diff --git a/chrome/browser/ui/views/global_media_controls/global_media_controls_types.h b/components/global_media_controls/public/constants.h similarity index 70% rename from chrome/browser/ui/views/global_media_controls/global_media_controls_types.h rename to components/global_media_controls/public/constants.h index 8e28d29..fe13dce 100644 --- a/chrome/browser/ui/views/global_media_controls/global_media_controls_types.h +++ b/components/global_media_controls/public/constants.h
@@ -2,8 +2,16 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_UI_VIEWS_GLOBAL_MEDIA_CONTROLS_GLOBAL_MEDIA_CONTROLS_TYPES_H_ -#define CHROME_BROWSER_UI_VIEWS_GLOBAL_MEDIA_CONTROLS_GLOBAL_MEDIA_CONTROLS_TYPES_H_ +#ifndef COMPONENTS_GLOBAL_MEDIA_CONTROLS_PUBLIC_CONSTANTS_H_ +#define COMPONENTS_GLOBAL_MEDIA_CONTROLS_PUBLIC_CONSTANTS_H_ + +#include "third_party/skia/include/core/SkColor.h" + +namespace global_media_controls { + +constexpr SkColor kDefaultForegroundColor = SK_ColorBLACK; + +constexpr SkColor kDefaultBackgroundColor = SK_ColorTRANSPARENT; // The entry point through which the dialog was opened. // These values are persisted to logs. Entries should not be renumbered and @@ -31,4 +39,6 @@ kMaxValue = kStopViaSystemTray, }; -#endif // CHROME_BROWSER_UI_VIEWS_GLOBAL_MEDIA_CONTROLS_GLOBAL_MEDIA_CONTROLS_TYPES_H_ +} // namespace global_media_controls + +#endif // COMPONENTS_GLOBAL_MEDIA_CONTROLS_PUBLIC_CONSTANTS_H_
diff --git a/components/global_media_controls/public/media_item_ui_observer.h b/components/global_media_controls/public/media_item_ui_observer.h index f2559c1..109a09b 100644 --- a/components/global_media_controls/public/media_item_ui_observer.h +++ b/components/global_media_controls/public/media_item_ui_observer.h
@@ -31,10 +31,6 @@ // Called when the item UI is about to be deleted. virtual void OnMediaItemUIDestroyed(const std::string& id) {} - // Called when the audio output device for the item UI should change. - virtual void OnAudioSinkChosen(const std::string& id, - const std::string& sink_id) {} - protected: ~MediaItemUIObserver() override = default; };
diff --git a/components/global_media_controls/public/media_item_ui_observer_set.cc b/components/global_media_controls/public/media_item_ui_observer_set.cc index 272b1980..c825976 100644 --- a/components/global_media_controls/public/media_item_ui_observer_set.cc +++ b/components/global_media_controls/public/media_item_ui_observer_set.cc
@@ -53,9 +53,4 @@ StopObserving(id); } -void MediaItemUIObserverSet::OnAudioSinkChosen(const std::string& id, - const std::string& sink_id) { - owner_->OnAudioSinkChosen(id, sink_id); -} - } // namespace global_media_controls
diff --git a/components/global_media_controls/public/media_item_ui_observer_set.h b/components/global_media_controls/public/media_item_ui_observer_set.h index ca9ab4a..d7e047f 100644 --- a/components/global_media_controls/public/media_item_ui_observer_set.h +++ b/components/global_media_controls/public/media_item_ui_observer_set.h
@@ -32,8 +32,6 @@ void OnMediaItemUIClicked(const std::string& id) override; void OnMediaItemUIDismissed(const std::string& id) override; void OnMediaItemUIDestroyed(const std::string& id) override; - void OnAudioSinkChosen(const std::string& id, - const std::string& sink_id) override; private: MediaItemUIObserver* const owner_;
diff --git a/components/global_media_controls/public/test/mock_media_item_producer.cc b/components/global_media_controls/public/test/mock_media_item_producer.cc index 376aa38..276ccd5 100644 --- a/components/global_media_controls/public/test/mock_media_item_producer.cc +++ b/components/global_media_controls/public/test/mock_media_item_producer.cc
@@ -4,42 +4,11 @@ #include "components/global_media_controls/public/test/mock_media_item_producer.h" -#include "components/media_message_center/media_notification_item.h" +#include "components/media_message_center/mock_media_notification_item.h" namespace global_media_controls { namespace test { -namespace { - -class MockMediaNotificationItem - : public media_message_center::MediaNotificationItem { - public: - MockMediaNotificationItem() = default; - MockMediaNotificationItem(const MockMediaNotificationItem&) = delete; - MockMediaNotificationItem& operator=(const MockMediaNotificationItem&) = - delete; - ~MockMediaNotificationItem() override = default; - - MOCK_METHOD(void, SetView, (media_message_center::MediaNotificationView*)); - MOCK_METHOD(void, - OnMediaSessionActionButtonPressed, - (media_session::mojom::MediaSessionAction)); - MOCK_METHOD(void, SeekTo, (base::TimeDelta)); - MOCK_METHOD(void, Dismiss, ()); - MOCK_METHOD(void, SetVolume, (float)); - MOCK_METHOD(void, SetMute, (bool)); - MOCK_METHOD(media_message_center::SourceType, SourceType, ()); - - base::WeakPtr<MockMediaNotificationItem> GetWeakPtr() { - return weak_ptr_factory_.GetWeakPtr(); - } - - private: - base::WeakPtrFactory<MockMediaNotificationItem> weak_ptr_factory_{this}; -}; - -} // namespace - struct MockMediaItemProducer::Item { public: Item(const std::string& item_id, @@ -58,7 +27,7 @@ bool active; bool frozen; bool playing; - MockMediaNotificationItem item; + media_message_center::test::MockMediaNotificationItem item; }; MockMediaItemProducer::MockMediaItemProducer() = default;
diff --git a/components/global_media_controls/public/test/mock_media_item_ui_device_selector.cc b/components/global_media_controls/public/test/mock_media_item_ui_device_selector.cc new file mode 100644 index 0000000..03fac12 --- /dev/null +++ b/components/global_media_controls/public/test/mock_media_item_ui_device_selector.cc
@@ -0,0 +1,15 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/global_media_controls/public/test/mock_media_item_ui_device_selector.h" + +namespace global_media_controls { +namespace test { + +MockMediaItemUIDeviceSelector::MockMediaItemUIDeviceSelector() = default; + +MockMediaItemUIDeviceSelector::~MockMediaItemUIDeviceSelector() = default; + +} // namespace test +} // namespace global_media_controls
diff --git a/components/global_media_controls/public/test/mock_media_item_ui_device_selector.h b/components/global_media_controls/public/test/mock_media_item_ui_device_selector.h new file mode 100644 index 0000000..d471b6b --- /dev/null +++ b/components/global_media_controls/public/test/mock_media_item_ui_device_selector.h
@@ -0,0 +1,31 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_GLOBAL_MEDIA_CONTROLS_PUBLIC_TEST_MOCK_MEDIA_ITEM_UI_DEVICE_SELECTOR_H_ +#define COMPONENTS_GLOBAL_MEDIA_CONTROLS_PUBLIC_TEST_MOCK_MEDIA_ITEM_UI_DEVICE_SELECTOR_H_ + +#include "components/global_media_controls/public/views/media_item_ui_device_selector.h" +#include "testing/gmock/include/gmock/gmock.h" + +namespace global_media_controls { +namespace test { + +class MockMediaItemUIDeviceSelector : public MediaItemUIDeviceSelector { + public: + MockMediaItemUIDeviceSelector(); + MockMediaItemUIDeviceSelector(const MockMediaItemUIDeviceSelector&) = delete; + MockMediaItemUIDeviceSelector& operator=( + const MockMediaItemUIDeviceSelector&) = delete; + ~MockMediaItemUIDeviceSelector() override; + + // MediaItemUIDeviceSelector: + MOCK_METHOD(void, SetMediaItemUIView, (MediaItemUIView*)); + MOCK_METHOD(void, OnColorsChanged, (SkColor, SkColor)); + MOCK_METHOD(void, UpdateCurrentAudioDevice, (const std::string&)); +}; + +} // namespace test +} // namespace global_media_controls + +#endif // COMPONENTS_GLOBAL_MEDIA_CONTROLS_PUBLIC_TEST_MOCK_MEDIA_ITEM_UI_DEVICE_SELECTOR_H_
diff --git a/components/global_media_controls/public/test/mock_media_item_ui_footer.cc b/components/global_media_controls/public/test/mock_media_item_ui_footer.cc new file mode 100644 index 0000000..478b7a3 --- /dev/null +++ b/components/global_media_controls/public/test/mock_media_item_ui_footer.cc
@@ -0,0 +1,15 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/global_media_controls/public/test/mock_media_item_ui_footer.h" + +namespace global_media_controls { +namespace test { + +MockMediaItemUIFooter::MockMediaItemUIFooter() = default; + +MockMediaItemUIFooter::~MockMediaItemUIFooter() = default; + +} // namespace test +} // namespace global_media_controls
diff --git a/components/global_media_controls/public/test/mock_media_item_ui_footer.h b/components/global_media_controls/public/test/mock_media_item_ui_footer.h new file mode 100644 index 0000000..b86bdcf --- /dev/null +++ b/components/global_media_controls/public/test/mock_media_item_ui_footer.h
@@ -0,0 +1,28 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_GLOBAL_MEDIA_CONTROLS_PUBLIC_TEST_MOCK_MEDIA_ITEM_UI_FOOTER_H_ +#define COMPONENTS_GLOBAL_MEDIA_CONTROLS_PUBLIC_TEST_MOCK_MEDIA_ITEM_UI_FOOTER_H_ + +#include "components/global_media_controls/public/views/media_item_ui_footer.h" +#include "testing/gmock/include/gmock/gmock.h" + +namespace global_media_controls { +namespace test { + +class MockMediaItemUIFooter : public MediaItemUIFooter { + public: + MockMediaItemUIFooter(); + MockMediaItemUIFooter(const MockMediaItemUIFooter&) = delete; + MockMediaItemUIFooter& operator=(const MockMediaItemUIFooter&) = delete; + ~MockMediaItemUIFooter() override; + + // MediaItemUIFooter: + MOCK_METHOD(void, OnColorsChanged, (SkColor, SkColor)); +}; + +} // namespace test +} // namespace global_media_controls + +#endif // COMPONENTS_GLOBAL_MEDIA_CONTROLS_PUBLIC_TEST_MOCK_MEDIA_ITEM_UI_FOOTER_H_
diff --git a/components/global_media_controls/public/test/mock_media_item_ui_observer.h b/components/global_media_controls/public/test/mock_media_item_ui_observer.h index 9dabeca..75df9be0 100644 --- a/components/global_media_controls/public/test/mock_media_item_ui_observer.h +++ b/components/global_media_controls/public/test/mock_media_item_ui_observer.h
@@ -24,9 +24,6 @@ MOCK_METHOD(void, OnMediaItemUIClicked, (const std::string&)); MOCK_METHOD(void, OnMediaItemUIDismissed, (const std::string&)); MOCK_METHOD(void, OnMediaItemUIDestroyed, (const std::string&)); - MOCK_METHOD(void, - OnAudioSinkChosen, - (const std::string&, const std::string&)); }; } // namespace test
diff --git a/components/global_media_controls/public/views/media_item_ui_device_selector.h b/components/global_media_controls/public/views/media_item_ui_device_selector.h new file mode 100644 index 0000000..ebc04db --- /dev/null +++ b/components/global_media_controls/public/views/media_item_ui_device_selector.h
@@ -0,0 +1,33 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_GLOBAL_MEDIA_CONTROLS_PUBLIC_VIEWS_MEDIA_ITEM_UI_DEVICE_SELECTOR_H_ +#define COMPONENTS_GLOBAL_MEDIA_CONTROLS_PUBLIC_VIEWS_MEDIA_ITEM_UI_DEVICE_SELECTOR_H_ + +#include "ui/views/view.h" + +namespace global_media_controls { + +class MediaItemUIView; + +// A MediaItemUIDeviceSelector is a views::View that should be inserted into the +// bottom of the MediaItemUI which contains and expandable list of devices to +// connect to (audio/Cast/etc). +class MediaItemUIDeviceSelector : public views::View { + public: + // Gives the device selector a pointer to the MediaItemUIView so that it can + // inform it of size changes. + virtual void SetMediaItemUIView(MediaItemUIView* view) = 0; + + // Called when the color theme has changed. + virtual void OnColorsChanged(SkColor foreground, SkColor background) = 0; + + // Called when an audio device switch has occurred + virtual void UpdateCurrentAudioDevice( + const std::string& current_device_id) = 0; +}; + +} // namespace global_media_controls + +#endif // COMPONENTS_GLOBAL_MEDIA_CONTROLS_PUBLIC_VIEWS_MEDIA_ITEM_UI_DEVICE_SELECTOR_H_
diff --git a/components/global_media_controls/public/views/media_item_ui_footer.h b/components/global_media_controls/public/views/media_item_ui_footer.h new file mode 100644 index 0000000..3ca8373 --- /dev/null +++ b/components/global_media_controls/public/views/media_item_ui_footer.h
@@ -0,0 +1,23 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_GLOBAL_MEDIA_CONTROLS_PUBLIC_VIEWS_MEDIA_ITEM_UI_FOOTER_H_ +#define COMPONENTS_GLOBAL_MEDIA_CONTROLS_PUBLIC_VIEWS_MEDIA_ITEM_UI_FOOTER_H_ + +#include "ui/views/view.h" + +namespace global_media_controls { + +// A MediaItemUIFooter is a type of views::View that can be inserted at the +// bottom of a MediaItemUI. Users of global media controls can create views that +// extend this class that will be inserted into the MediaItemUI and receive +// color updates. +class MediaItemUIFooter : public views::View { + public: + virtual void OnColorsChanged(SkColor foreground, SkColor background) = 0; +}; + +} // namespace global_media_controls + +#endif // COMPONENTS_GLOBAL_MEDIA_CONTROLS_PUBLIC_VIEWS_MEDIA_ITEM_UI_FOOTER_H_
diff --git a/components/global_media_controls/public/views/media_item_ui_list_view.cc b/components/global_media_controls/public/views/media_item_ui_list_view.cc new file mode 100644 index 0000000..0e95602 --- /dev/null +++ b/components/global_media_controls/public/views/media_item_ui_list_view.cc
@@ -0,0 +1,109 @@ +// 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 "components/global_media_controls/public/views/media_item_ui_list_view.h" + +#include "base/containers/contains.h" +#include "components/global_media_controls/public/views/media_item_ui_view.h" +#include "ui/base/metadata/metadata_impl_macros.h" +#include "ui/color/color_id.h" +#include "ui/color/color_provider.h" +#include "ui/views/border.h" +#include "ui/views/controls/scrollbar/overlay_scroll_bar.h" +#include "ui/views/layout/box_layout.h" + +namespace global_media_controls { + +namespace { + +constexpr int kMediaListMaxHeight = 478; + +// Thickness of separator border. +constexpr int kMediaListSeparatorThickness = 2; + +std::unique_ptr<views::Border> CreateMediaListSeparatorBorder(SkColor color, + int thickness) { + return views::CreateSolidSidedBorder(/*top=*/thickness, + /*left=*/0, + /*bottom=*/0, + /*right=*/0, color); +} + +} // anonymous namespace + +MediaItemUIListView::SeparatorStyle::SeparatorStyle(SkColor separator_color, + int separator_thickness) + : separator_color(separator_color), + separator_thickness(separator_thickness) {} + +MediaItemUIListView::MediaItemUIListView() + : MediaItemUIListView(absl::nullopt) {} + +MediaItemUIListView::MediaItemUIListView( + const absl::optional<SeparatorStyle>& separator_style) + : separator_style_(separator_style) { + SetBackgroundColor(absl::nullopt); + SetContents(std::make_unique<views::View>()); + contents()->SetLayoutManager(std::make_unique<views::BoxLayout>( + views::BoxLayout::Orientation::kVertical)); + ClipHeightTo(0, kMediaListMaxHeight); + + SetVerticalScrollBar( + std::make_unique<views::OverlayScrollBar>(/*horizontal=*/false)); + SetHorizontalScrollBar( + std::make_unique<views::OverlayScrollBar>(/*horizontal=*/true)); +} + +MediaItemUIListView::~MediaItemUIListView() = default; + +void MediaItemUIListView::ShowItem(const std::string& id, + std::unique_ptr<MediaItemUIView> item) { + DCHECK(!base::Contains(items_, id)); + DCHECK_NE(nullptr, item.get()); + + // If this isn't the first item, then create a top-sided separator + // border. + if (!items_.empty()) { + if (separator_style_.has_value()) { + item->SetBorder(CreateMediaListSeparatorBorder( + separator_style_->separator_color, + separator_style_->separator_thickness)); + } else { + item->SetBorder(CreateMediaListSeparatorBorder( + GetColorProvider()->GetColor(ui::kColorMenuSeparator), + kMediaListSeparatorThickness)); + } + } + + items_[id] = contents()->AddChildView(std::move(item)); + + contents()->InvalidateLayout(); + PreferredSizeChanged(); +} + +void MediaItemUIListView::HideItem(const std::string& id) { + if (!base::Contains(items_, id)) + return; + + // If we're removing the topmost item and there are others, then we need to + // remove the top-sided separator border from the new topmost item. + if (contents()->children().size() > 1 && + contents()->children().at(0) == items_[id]) { + contents()->children().at(1)->SetBorder(nullptr); + } + + // Remove the item. Note that since |RemoveChildView()| does not delete the + // item, we now have ownership. + contents()->RemoveChildView(items_[id]); + delete items_[id]; + items_.erase(id); + + contents()->InvalidateLayout(); + PreferredSizeChanged(); +} + +BEGIN_METADATA(MediaItemUIListView, views::ScrollView) +END_METADATA + +} // namespace global_media_controls
diff --git a/components/global_media_controls/public/views/media_item_ui_list_view.h b/components/global_media_controls/public/views/media_item_ui_list_view.h new file mode 100644 index 0000000..0dd5dbb3 --- /dev/null +++ b/components/global_media_controls/public/views/media_item_ui_list_view.h
@@ -0,0 +1,61 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_GLOBAL_MEDIA_CONTROLS_PUBLIC_VIEWS_MEDIA_ITEM_UI_LIST_VIEW_H_ +#define COMPONENTS_GLOBAL_MEDIA_CONTROLS_PUBLIC_VIEWS_MEDIA_ITEM_UI_LIST_VIEW_H_ + +#include <map> +#include <memory> + +#include "base/component_export.h" +#include "third_party/abseil-cpp/absl/types/optional.h" +#include "ui/base/metadata/metadata_header_macros.h" +#include "ui/views/controls/scroll_view.h" + +namespace global_media_controls { + +class MediaItemUIView; + +// MediaItemUIListView is a container that holds a list of MediaItemUIViews and +// handles adding/removing separators and creating a scrollable view. +class COMPONENT_EXPORT(GLOBAL_MEDIA_CONTROLS) MediaItemUIListView + : public views::ScrollView { + public: + METADATA_HEADER(MediaItemUIListView); + struct SeparatorStyle { + SeparatorStyle(SkColor separator_color, int separator_thickness); + + const SkColor separator_color; + const int separator_thickness; + }; + + explicit MediaItemUIListView( + const absl::optional<SeparatorStyle>& separator_style); + MediaItemUIListView(); + MediaItemUIListView(const MediaItemUIListView&) = delete; + MediaItemUIListView& operator=(const MediaItemUIListView&) = delete; + ~MediaItemUIListView() override; + + // Adds the given item into the list. + void ShowItem(const std::string& id, std::unique_ptr<MediaItemUIView> item); + + // Removes the given item from the list. + void HideItem(const std::string& id); + + bool empty() { return items_.empty(); } + + const std::map<const std::string, MediaItemUIView*>& items_for_testing() + const { + return items_; + } + + private: + std::map<const std::string, MediaItemUIView*> items_; + + absl::optional<SeparatorStyle> separator_style_; +}; + +} // namespace global_media_controls + +#endif // COMPONENTS_GLOBAL_MEDIA_CONTROLS_PUBLIC_VIEWS_MEDIA_ITEM_UI_LIST_VIEW_H_
diff --git a/components/global_media_controls/public/views/media_item_ui_list_view_unittest.cc b/components/global_media_controls/public/views/media_item_ui_list_view_unittest.cc new file mode 100644 index 0000000..2a5fa30 --- /dev/null +++ b/components/global_media_controls/public/views/media_item_ui_list_view_unittest.cc
@@ -0,0 +1,126 @@ +// 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 "components/global_media_controls/public/views/media_item_ui_list_view.h" + +#include <memory> +#include <string> + +#include "components/global_media_controls/public/views/media_item_ui_view.h" +#include "components/media_message_center/mock_media_notification_item.h" +#include "ui/views/test/views_test_base.h" + +using testing::NiceMock; + +namespace global_media_controls { + +namespace { + +// Test IDs for items. +const char kTestItemId1[] = "testid1"; +const char kTestItemId2[] = "testid2"; +const char kTestItemId3[] = "testid3"; + +} // anonymous namespace + +class MediaItemUIListViewTest : public views::ViewsTestBase { + public: + MediaItemUIListViewTest() = default; + MediaItemUIListViewTest(const MediaItemUIListViewTest&) = delete; + MediaItemUIListViewTest& operator=(const MediaItemUIListViewTest&) = delete; + ~MediaItemUIListViewTest() override = default; + + // views::ViewsTestBase: + void SetUp() override { + views::ViewsTestBase::SetUp(); + + widget_ = CreateTestWidget(); + + list_view_ = + widget_->SetContentsView(std::make_unique<MediaItemUIListView>()); + + item_ = std::make_unique< + NiceMock<media_message_center::test::MockMediaNotificationItem>>(); + widget_->Show(); + } + + void TearDown() override { + widget_.reset(); + views::ViewsTestBase::TearDown(); + } + + void ShowItem(const std::string& id) { + list_view_->ShowItem(id, std::make_unique<MediaItemUIView>( + id, item_->GetWeakPtr(), nullptr, nullptr)); + } + + void HideItem(const std::string& id) { list_view_->HideItem(id); } + + MediaItemUIListView* list_view() { return list_view_; } + + private: + std::unique_ptr<views::Widget> widget_; + MediaItemUIListView* list_view_ = nullptr; + std::unique_ptr<media_message_center::test::MockMediaNotificationItem> item_; +}; + +TEST_F(MediaItemUIListViewTest, NoSeparatorForOneItem) { + // Show a single item. + ShowItem(kTestItemId1); + + // There should be just one item. + EXPECT_EQ(1u, list_view()->items_for_testing().size()); + + // Since there's only one, there should be no separator line. + EXPECT_EQ(nullptr, + list_view()->items_for_testing().at(kTestItemId1)->GetBorder()); +} + +TEST_F(MediaItemUIListViewTest, SeparatorBetweenItems) { + // Show two items. + ShowItem(kTestItemId1); + ShowItem(kTestItemId2); + + // There should be two items. + EXPECT_EQ(2u, list_view()->items_for_testing().size()); + + // There should be a separator between them. Since the separators are + // top-sided, the bottom item should have one. + EXPECT_EQ(nullptr, + list_view()->items_for_testing().at(kTestItemId1)->GetBorder()); + EXPECT_NE(nullptr, + list_view()->items_for_testing().at(kTestItemId2)->GetBorder()); +} + +TEST_F(MediaItemUIListViewTest, SeparatorRemovedWhenItemRemoved) { + // Show three items. + ShowItem(kTestItemId1); + ShowItem(kTestItemId2); + ShowItem(kTestItemId3); + + // There should be three items. + EXPECT_EQ(3u, list_view()->items_for_testing().size()); + + // There should be separators. + EXPECT_EQ(nullptr, + list_view()->items_for_testing().at(kTestItemId1)->GetBorder()); + EXPECT_NE(nullptr, + list_view()->items_for_testing().at(kTestItemId2)->GetBorder()); + EXPECT_NE(nullptr, + list_view()->items_for_testing().at(kTestItemId3)->GetBorder()); + + // Remove the topmost item. + HideItem(kTestItemId1); + + // There should be two items. + EXPECT_EQ(2u, list_view()->items_for_testing().size()); + + // The new top item should have lost its top separator. + EXPECT_EQ(nullptr, + list_view()->items_for_testing().at(kTestItemId2)->GetBorder()); + EXPECT_NE(nullptr, + list_view()->items_for_testing().at(kTestItemId3)->GetBorder()); +} + +} // namespace global_media_controls
diff --git a/components/global_media_controls/public/views/media_item_ui_view.cc b/components/global_media_controls/public/views/media_item_ui_view.cc new file mode 100644 index 0000000..bdf2ff16 --- /dev/null +++ b/components/global_media_controls/public/views/media_item_ui_view.cc
@@ -0,0 +1,379 @@ +// 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 "components/global_media_controls/public/views/media_item_ui_view.h" + +#include "base/bind.h" +#include "base/containers/contains.h" +#include "base/feature_list.h" +#include "components/global_media_controls/public/constants.h" +#include "components/global_media_controls/public/media_item_manager.h" +#include "components/global_media_controls/public/media_item_ui_observer.h" +#include "components/global_media_controls/public/views/media_item_ui_device_selector.h" +#include "components/global_media_controls/public/views/media_item_ui_footer.h" +#include "components/media_message_center/media_notification_item.h" +#include "components/media_message_center/media_notification_view_modern_impl.h" +#include "components/strings/grit/components_strings.h" +#include "components/vector_icons/vector_icons.h" +#include "media/audio/audio_device_description.h" +#include "ui/base/l10n/l10n_util.h" +#include "ui/base/metadata/metadata_header_macros.h" +#include "ui/base/metadata/metadata_impl_macros.h" +#include "ui/compositor/layer.h" +#include "ui/message_center/public/cpp/message_center_constants.h" +#include "ui/views/animation/ink_drop.h" +#include "ui/views/animation/slide_out_controller.h" +#include "ui/views/background.h" +#include "ui/views/border.h" +#include "ui/views/controls/button/image_button.h" +#include "ui/views/controls/button/image_button_factory.h" +#include "ui/views/controls/highlight_path_generator.h" +#include "ui/views/controls/image_view.h" +#include "ui/views/layout/box_layout.h" +#include "ui/views/layout/fill_layout.h" + +namespace global_media_controls { + +namespace { + +constexpr int kWidth = 400; +constexpr int kModernUIWidth = 350; +constexpr gfx::Size kNormalSize = gfx::Size(kWidth, 100); +constexpr gfx::Size kExpandedSize = gfx::Size(kWidth, 150); +constexpr gfx::Size kModernUISize = gfx::Size(kModernUIWidth, 168); +constexpr gfx::Size kDismissButtonSize = gfx::Size(30, 30); +constexpr int kDismissButtonIconSize = 20; +constexpr int kDismissButtonBackgroundRadius = 15; +constexpr gfx::Size kCrOSDismissButtonSize = gfx::Size(20, 20); +constexpr int kCrOSDismissButtonIconSize = 12; +constexpr gfx::Size kModernDismissButtonSize = gfx::Size(14, 14); +constexpr int kModernDismissButtonIconSize = 10; + +// The minimum number of enabled and visible user actions such that we should +// force the MediaNotificationView to be expanded. +constexpr int kMinVisibleActionsForExpanding = 4; + +} // anonymous namespace + +class MediaItemUIView::DismissButton : public views::ImageButton { + public: + METADATA_HEADER(DismissButton); + + explicit DismissButton(PressedCallback callback) + : views::ImageButton(std::move(callback)) { + views::ConfigureVectorImageButton(this); + views::InstallFixedSizeCircleHighlightPathGenerator( + this, kDismissButtonBackgroundRadius); + SetFocusBehavior(views::View::FocusBehavior::ALWAYS); + } + DismissButton(const DismissButton&) = delete; + DismissButton& operator=(const DismissButton&) = delete; + ~DismissButton() override = default; +}; + +BEGIN_METADATA(MediaItemUIView, DismissButton, views::ImageButton) +END_METADATA + +MediaItemUIView::MediaItemUIView( + const std::string& id, + base::WeakPtr<media_message_center::MediaNotificationItem> item, + std::unique_ptr<MediaItemUIFooter> footer_view, + std::unique_ptr<MediaItemUIDeviceSelector> device_selector_view, + absl::optional<media_message_center::NotificationTheme> theme) + : views::Button(base::BindRepeating(&MediaItemUIView::ContainerClicked, + base::Unretained(this))), + id_(id), + footer_view_(footer_view.get()), + foreground_color_(kDefaultForegroundColor), + background_color_(kDefaultBackgroundColor), + is_cros_(theme.has_value()) { + DCHECK(item); + SetLayoutManager(std::make_unique<views::BoxLayout>( + views::BoxLayout::Orientation::kVertical)); + SetPreferredSize(kNormalSize); + SetNotifyEnterExitOnChild(true); + SetFocusBehavior(views::View::FocusBehavior::ALWAYS); + SetTooltipText( + l10n_util::GetStringUTF16(IDS_GLOBAL_MEDIA_CONTROLS_BACK_TO_TAB)); + + auto swipeable_container = std::make_unique<views::View>(); + swipeable_container->SetLayoutManager(std::make_unique<views::FillLayout>()); + swipeable_container->SetPaintToLayer(); + swipeable_container->layer()->SetFillsBoundsOpaquely(false); + swipeable_container_ = AddChildView(std::move(swipeable_container)); + + gfx::Size dismiss_button_size = + is_cros_ ? kCrOSDismissButtonSize : kDismissButtonSize; + if (base::FeatureList::IsEnabled(media::kGlobalMediaControlsModernUI)) + dismiss_button_size = kModernDismissButtonSize; + + auto dismiss_button_placeholder = std::make_unique<views::View>(); + dismiss_button_placeholder->SetPreferredSize(dismiss_button_size); + dismiss_button_placeholder->SetLayoutManager( + std::make_unique<views::FillLayout>()); + dismiss_button_placeholder_ = dismiss_button_placeholder.get(); + + auto dismiss_button_container = std::make_unique<views::View>(); + dismiss_button_container->SetPreferredSize(dismiss_button_size); + dismiss_button_container->SetLayoutManager( + std::make_unique<views::FillLayout>()); + dismiss_button_container->SetVisible(false); + dismiss_button_container_ = dismiss_button_placeholder_->AddChildView( + std::move(dismiss_button_container)); + + auto dismiss_button = std::make_unique<DismissButton>(base::BindRepeating( + &MediaItemUIView::DismissNotification, base::Unretained(this))); + dismiss_button->SetPreferredSize(dismiss_button_size); + dismiss_button->SetTooltipText(l10n_util::GetStringUTF16( + IDS_GLOBAL_MEDIA_CONTROLS_DISMISS_ICON_TOOLTIP_TEXT)); + dismiss_button_ = + dismiss_button_container_->AddChildView(std::move(dismiss_button)); + UpdateDismissButtonIcon(); + + std::unique_ptr<media_message_center::MediaNotificationView> view; + if (base::FeatureList::IsEnabled(media::kGlobalMediaControlsModernUI)) { + view = + std::make_unique<media_message_center::MediaNotificationViewModernImpl>( + this, std::move(item), std::move(dismiss_button_placeholder), + std::move(footer_view), kModernUIWidth); + SetPreferredSize(kModernUISize); + } else { + view = std::make_unique<media_message_center::MediaNotificationViewImpl>( + this, std::move(item), std::move(dismiss_button_placeholder), + std::u16string(), kWidth, /*should_show_icon=*/false, theme); + + if (footer_view) + AddChildView(std::move(footer_view)); + + SetPreferredSize(kNormalSize); + } + view_ = swipeable_container_->AddChildView(std::move(view)); + + if (device_selector_view) { + device_selector_view_ = device_selector_view.get(); + device_selector_view_->SetMediaItemUIView(this); + AddChildView(std::move(device_selector_view)); + view_->UpdateCornerRadius(message_center::kNotificationCornerRadius, 0); + } + + ForceExpandedState(); + + slide_out_controller_ = + std::make_unique<views::SlideOutController>(this, this); +} + +MediaItemUIView::~MediaItemUIView() { + for (auto& observer : observers_) + observer.OnMediaItemUIDestroyed(id_); +} + +void MediaItemUIView::AddedToWidget() { + if (GetFocusManager()) + GetFocusManager()->AddFocusChangeListener(this); +} + +void MediaItemUIView::RemovedFromWidget() { + if (GetFocusManager()) + GetFocusManager()->RemoveFocusChangeListener(this); +} + +void MediaItemUIView::OnMouseEntered(const ui::MouseEvent& event) { + UpdateDismissButtonVisibility(); +} + +void MediaItemUIView::OnMouseExited(const ui::MouseEvent& event) { + UpdateDismissButtonVisibility(); +} + +void MediaItemUIView::OnDidChangeFocus(views::View* focused_before, + views::View* focused_now) { + UpdateDismissButtonVisibility(); +} + +void MediaItemUIView::OnExpanded(bool expanded) { + is_expanded_ = expanded; + OnSizeChanged(); +} + +void MediaItemUIView::OnMediaSessionInfoChanged( + const media_session::mojom::MediaSessionInfoPtr& session_info) { + is_playing_ = + session_info && session_info->playback_state == + media_session::mojom::MediaPlaybackState::kPlaying; + if (session_info) { + auto audio_sink_id = session_info->audio_sink_id.value_or( + media::AudioDeviceDescription::kDefaultDeviceId); + if (device_selector_view_ && + base::FeatureList::IsEnabled( + media::kGlobalMediaControlsSeamlessTransfer)) { + device_selector_view_->UpdateCurrentAudioDevice(audio_sink_id); + } + } +} + +void MediaItemUIView::OnMediaSessionMetadataChanged( + const media_session::MediaMetadata& metadata) { + title_ = metadata.title; + + for (auto& observer : observers_) + observer.OnMediaItemUIMetadataChanged(); +} + +void MediaItemUIView::OnVisibleActionsChanged( + const base::flat_set<media_session::mojom::MediaSessionAction>& actions) { + has_many_actions_ = + (actions.size() >= kMinVisibleActionsForExpanding || + base::Contains( + actions, + media_session::mojom::MediaSessionAction::kEnterPictureInPicture) || + base::Contains( + actions, + media_session::mojom::MediaSessionAction::kExitPictureInPicture)); + ForceExpandedState(); + + for (auto& observer : observers_) + observer.OnMediaItemUIActionsChanged(); +} + +void MediaItemUIView::OnMediaArtworkChanged(const gfx::ImageSkia& image) { + has_artwork_ = !image.isNull(); + + UpdateDismissButtonBackground(); + ForceExpandedState(); +} + +void MediaItemUIView::OnColorsChanged(SkColor foreground, SkColor background) { + if (foreground_color_ != foreground) { + foreground_color_ = foreground; + UpdateDismissButtonIcon(); + } + + if (background_color_ != background) { + background_color_ = background; + UpdateDismissButtonBackground(); + } + if (footer_view_) + footer_view_->OnColorsChanged(foreground, background); + + if (device_selector_view_) + device_selector_view_->OnColorsChanged(foreground, background); +} + +void MediaItemUIView::OnHeaderClicked() { + // Since we disable the expand button, nothing happens on the + // MediaNotificationView when the header is clicked. Treat the click as if we + // were clicked directly. + ContainerClicked(); +} + +void MediaItemUIView::OnDeviceSelectorViewSizeChanged() { + OnSizeChanged(); +} + +ui::Layer* MediaItemUIView::GetSlideOutLayer() { + return swipeable_container_->layer(); +} + +void MediaItemUIView::OnSlideOut() { + DismissNotification(); +} + +void MediaItemUIView::AddObserver( + global_media_controls::MediaItemUIObserver* observer) { + observers_.AddObserver(observer); +} + +void MediaItemUIView::RemoveObserver( + global_media_controls::MediaItemUIObserver* observer) { + observers_.RemoveObserver(observer); +} + +const std::u16string& MediaItemUIView::GetTitle() const { + return title_; +} + +views::ImageButton* MediaItemUIView::GetDismissButtonForTesting() { + return dismiss_button_; +} + +void MediaItemUIView::UpdateDismissButtonIcon() { + int icon_size = + is_cros_ ? kCrOSDismissButtonIconSize : kDismissButtonIconSize; + if (base::FeatureList::IsEnabled(media::kGlobalMediaControlsModernUI)) + icon_size = kModernDismissButtonIconSize; + + views::SetImageFromVectorIconWithColor(dismiss_button_, + vector_icons::kCloseRoundedIcon, + icon_size, foreground_color_); +} + +void MediaItemUIView::UpdateDismissButtonBackground() { + if (!has_artwork_) { + dismiss_button_container_->SetBackground(nullptr); + return; + } + + dismiss_button_container_->SetBackground(views::CreateRoundedRectBackground( + background_color_, kDismissButtonBackgroundRadius)); +} + +void MediaItemUIView::UpdateDismissButtonVisibility() { + bool has_focus = false; + if (GetFocusManager()) { + views::View* focused_view = GetFocusManager()->GetFocusedView(); + if (focused_view) + has_focus = Contains(focused_view); + } + + dismiss_button_container_->SetVisible(IsMouseHovered() || has_focus); +} + +void MediaItemUIView::DismissNotification() { + for (auto& observer : observers_) + observer.OnMediaItemUIDismissed(id_); +} + +void MediaItemUIView::ForceExpandedState() { + if (view_) { + bool should_expand = has_many_actions_ || has_artwork_; + view_->SetForcedExpandedState(&should_expand); + } +} + +void MediaItemUIView::ContainerClicked() { + for (auto& observer : observers_) + observer.OnMediaItemUIClicked(id_); +} + +void MediaItemUIView::OnSizeChanged() { + gfx::Size new_size; + if (base::FeatureList::IsEnabled(media::kGlobalMediaControlsModernUI)) { + new_size = kModernUISize; + } else { + new_size = is_expanded_ ? kExpandedSize : kNormalSize; + } + + // |new_size| does not contain the height for the device selector view. + // If this view is present, we should query it for its preferred height and + // include that in |new_size|. + if (device_selector_view_) { + auto device_selector_view_size = device_selector_view_->GetPreferredSize(); + DCHECK(device_selector_view_size.width() == kWidth); + new_size.set_height(new_size.height() + device_selector_view_size.height()); + view_->UpdateDeviceSelectorAvailability( + device_selector_view_->GetVisible()); + } + + SetPreferredSize(new_size); + PreferredSizeChanged(); + + for (auto& observer : observers_) + observer.OnMediaItemUISizeChanged(); +} + +BEGIN_METADATA(MediaItemUIView, views::Button) +ADD_READONLY_PROPERTY_METADATA(std::u16string, Title) +END_METADATA + +} // namespace global_media_controls
diff --git a/chrome/browser/ui/views/global_media_controls/media_notification_container_impl_view.h b/components/global_media_controls/public/views/media_item_ui_view.h similarity index 62% rename from chrome/browser/ui/views/global_media_controls/media_notification_container_impl_view.h rename to components/global_media_controls/public/views/media_item_ui_view.h index 8fe19aff..f41ddc69 100644 --- a/chrome/browser/ui/views/global_media_controls/media_notification_container_impl_view.h +++ b/components/global_media_controls/public/views/media_item_ui_view.h
@@ -2,71 +2,60 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_UI_VIEWS_GLOBAL_MEDIA_CONTROLS_MEDIA_NOTIFICATION_CONTAINER_IMPL_VIEW_H_ -#define CHROME_BROWSER_UI_VIEWS_GLOBAL_MEDIA_CONTROLS_MEDIA_NOTIFICATION_CONTAINER_IMPL_VIEW_H_ +#ifndef COMPONENTS_GLOBAL_MEDIA_CONTROLS_PUBLIC_VIEWS_MEDIA_ITEM_UI_VIEW_H_ +#define COMPONENTS_GLOBAL_MEDIA_CONTROLS_PUBLIC_VIEWS_MEDIA_ITEM_UI_VIEW_H_ #include <string> +#include "base/component_export.h" #include "base/memory/weak_ptr.h" #include "base/observer_list.h" -#include "chrome/browser/ui/views/global_media_controls/global_media_controls_types.h" -#include "chrome/browser/ui/views/global_media_controls/media_notification_device_selector_view_delegate.h" +#include "components/global_media_controls/public/constants.h" #include "components/global_media_controls/public/media_item_ui.h" +#include "components/global_media_controls/public/views/media_item_ui_device_selector.h" +#include "components/global_media_controls/public/views/media_item_ui_footer.h" #include "components/media_message_center/media_notification_container.h" #include "components/media_message_center/media_notification_view_impl.h" -#include "media/audio/audio_device_description.h" #include "media/base/media_switches.h" #include "ui/base/metadata/metadata_header_macros.h" #include "ui/views/animation/slide_out_controller_delegate.h" #include "ui/views/focus/focus_manager.h" -#include "ui/views/widget/unique_widget_ptr.h" - -namespace global_media_controls { -class MediaItemUIObserver; -} // namespace global_media_controls namespace media_message_center { class MediaNotificationItem; } // namespace media_message_center namespace views { -class LabelButton; class ImageButton; class SlideOutController; } // namespace views -class CastMediaNotificationItem; -class MediaNotificationDeviceSelectorView; -class MediaNotificationFooterView; -class MediaNotificationService; -class Profile; +namespace global_media_controls { -// MediaNotificationContainerImplView holds a media notification for display +class MediaItemUIObserver; + +// MediaItemUIView holds a media notification for display // within the MediaDialogView. The media notification shows metadata for a media // session and can control playback. -class MediaNotificationContainerImplView +class COMPONENT_EXPORT(GLOBAL_MEDIA_CONTROLS) MediaItemUIView : public views::Button, public media_message_center::MediaNotificationContainer, public global_media_controls::MediaItemUI, - public MediaNotificationDeviceSelectorViewDelegate, public views::SlideOutControllerDelegate, public views::FocusChangeListener { public: - METADATA_HEADER(MediaNotificationContainerImplView); + METADATA_HEADER(MediaItemUIView); - MediaNotificationContainerImplView( + MediaItemUIView( const std::string& id, base::WeakPtr<media_message_center::MediaNotificationItem> item, - MediaNotificationService* service, - GlobalMediaControlsEntryPoint entry_point, - Profile* profile, + std::unique_ptr<MediaItemUIFooter> footer_view, + std::unique_ptr<MediaItemUIDeviceSelector> device_selector_view, absl::optional<media_message_center::NotificationTheme> theme = absl::nullopt); - MediaNotificationContainerImplView( - const MediaNotificationContainerImplView&) = delete; - MediaNotificationContainerImplView& operator=( - const MediaNotificationContainerImplView&) = delete; - ~MediaNotificationContainerImplView() override; + MediaItemUIView(const MediaItemUIView&) = delete; + MediaItemUIView& operator=(const MediaItemUIView&) = delete; + ~MediaItemUIView() override; // views::Button: void AddedToWidget() override; @@ -105,27 +94,17 @@ void RemoveObserver( global_media_controls::MediaItemUIObserver* observer) override; - // MediaNotificationDeviceSelectorViewDelegate - // Called when an audio device has been selected for output. - void OnAudioSinkChosen(const std::string& sink_id) override; - void OnDeviceSelectorViewSizeChanged() override; - base::CallbackListSubscription RegisterAudioOutputDeviceDescriptionsCallback( - MediaNotificationDeviceProvider::GetOutputDevicesCallbackList:: - CallbackType callback) override; - base::CallbackListSubscription - RegisterIsAudioOutputDeviceSwitchingSupportedCallback( - base::RepeatingCallback<void(bool)> callback) override; + void OnDeviceSelectorViewSizeChanged(); const std::u16string& GetTitle() const; views::ImageButton* GetDismissButtonForTesting(); - views::Button* GetStopCastingButtonForTesting(); media_message_center::MediaNotificationViewImpl* view_for_testing() { DCHECK(!base::FeatureList::IsEnabled(media::kGlobalMediaControlsModernUI)); return static_cast<media_message_center::MediaNotificationViewImpl*>(view_); } - MediaNotificationDeviceSelectorView* device_selector_view_for_testing() { + MediaItemUIDeviceSelector* device_selector_view_for_testing() { return device_selector_view_; } @@ -135,12 +114,6 @@ private: class DismissButton; - void AddStopCastButton(CastMediaNotificationItem* item); - void AddDeviceSelectorView(bool is_local_media_session, - bool show_expand_button); - void StopCasting(CastMediaNotificationItem* item); - void UpdateStopCastButtonIcon(); - void UpdateStopCastButtonBackground(); void UpdateDismissButtonIcon(); void UpdateDismissButtonBackground(); void UpdateDismissButtonVisibility(); @@ -167,12 +140,10 @@ DismissButton* dismiss_button_ = nullptr; media_message_center::MediaNotificationView* view_ = nullptr; - MediaNotificationDeviceSelectorView* device_selector_view_ = nullptr; - MediaNotificationFooterView* footer_view_ = nullptr; - // Only shows up for cast notifications. - views::View* stop_button_strip_ = nullptr; - views::LabelButton* stop_cast_button_ = nullptr; + MediaItemUIFooter* const footer_view_; + + MediaItemUIDeviceSelector* device_selector_view_ = nullptr; SkColor foreground_color_; SkColor background_color_; @@ -184,18 +155,14 @@ bool is_expanded_ = false; - std::string audio_sink_id_ = media::AudioDeviceDescription::kDefaultDeviceId; - base::ObserverList<global_media_controls::MediaItemUIObserver> observers_; // Handles gesture events for swiping to dismiss notifications. std::unique_ptr<views::SlideOutController> slide_out_controller_; - MediaNotificationService* const service_; - const bool is_cros_; - const GlobalMediaControlsEntryPoint entry_point_; - Profile* const profile_; }; -#endif // CHROME_BROWSER_UI_VIEWS_GLOBAL_MEDIA_CONTROLS_MEDIA_NOTIFICATION_CONTAINER_IMPL_VIEW_H_ +} // namespace global_media_controls + +#endif // COMPONENTS_GLOBAL_MEDIA_CONTROLS_PUBLIC_VIEWS_MEDIA_ITEM_UI_VIEW_H_
diff --git a/components/global_media_controls/public/views/media_item_ui_view_unittest.cc b/components/global_media_controls/public/views/media_item_ui_view_unittest.cc new file mode 100644 index 0000000..4b656fbd --- /dev/null +++ b/components/global_media_controls/public/views/media_item_ui_view_unittest.cc
@@ -0,0 +1,360 @@ +// 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 "components/global_media_controls/public/views/media_item_ui_view.h" + +#include <memory> +#include <utility> + +#include "base/containers/flat_set.h" +#include "build/build_config.h" +#include "components/global_media_controls/public/test/mock_media_item_manager.h" +#include "components/global_media_controls/public/test/mock_media_item_ui_device_selector.h" +#include "components/global_media_controls/public/test/mock_media_item_ui_footer.h" +#include "components/global_media_controls/public/test/mock_media_item_ui_observer.h" +#include "components/media_message_center/mock_media_notification_item.h" +#include "services/media_session/public/mojom/media_session.mojom.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "ui/display/test/scoped_screen_override.h" +#include "ui/display/test/test_screen.h" +#include "ui/events/base_event_utils.h" +#include "ui/events/test/event_generator.h" +#include "ui/views/test/button_test_api.h" +#include "ui/views/test/view_metadata_test_utils.h" +#include "ui/views/test/views_test_base.h" +#include "ui/views/widget/widget_utils.h" + +using media_session::mojom::MediaPlaybackState; +using media_session::mojom::MediaSessionAction; +using ::testing::_; +using ::testing::NiceMock; + +namespace global_media_controls { + +namespace { + +const char kTestNotificationId[] = "testid"; +const char kOtherTestNotificationId[] = "othertestid"; + +} // anonymous namespace + +class MediaItemUIViewTest : public views::ViewsTestBase { + public: + MediaItemUIViewTest() : screen_override_(&fake_screen_) {} + MediaItemUIViewTest(const MediaItemUIViewTest&) = delete; + MediaItemUIViewTest& operator=(const MediaItemUIViewTest&) = delete; + ~MediaItemUIViewTest() override = default; + + // views::ViewsTestBase: + void SetUp() override { + views::ViewsTestBase::SetUp(); + item_ = std::make_unique< + NiceMock<media_message_center::test::MockMediaNotificationItem>>(); + widget_ = CreateTestWidget(); + + auto footer = std::make_unique<NiceMock<test::MockMediaItemUIFooter>>(); + footer_ = footer.get(); + + auto device_selector = + std::make_unique<NiceMock<test::MockMediaItemUIDeviceSelector>>(); + device_selector_ = device_selector.get(); + device_selector_->SetPreferredSize({400, 50}); + + item_ui_ = widget_->SetContentsView(std::make_unique<MediaItemUIView>( + kTestNotificationId, item_->GetWeakPtr(), std::move(footer), + std::move(device_selector))); + + observer_ = std::make_unique< + NiceMock<global_media_controls::test::MockMediaItemUIObserver>>(); + item_ui_->AddObserver(observer_.get()); + + SimulateMediaSessionData(); + + widget_->Show(); + } + + void TearDown() override { + item_ui_->RemoveObserver(observer_.get()); + widget_.reset(); + ViewsTestBase::TearDown(); + } + + void SimulateItemUISwipedToDismiss() { + // When the item ui is swiped, the SlideOutController sends this to the + // MediaItemUIView. + item_ui()->OnSlideOut(); + } + + bool IsDismissButtonVisible() { return GetDismissButton()->IsDrawn(); } + + void SimulateHoverOverItemUI() { + fake_screen_.set_cursor_screen_point( + item_ui_->GetBoundsInScreen().CenterPoint()); + + ui::MouseEvent event(ui::ET_MOUSE_ENTERED, gfx::Point(), gfx::Point(), + ui::EventTimeForNow(), 0, 0); + item_ui_->OnMouseEntered(event); + } + + void SimulateNotHoveringOverItemUI() { + gfx::Rect container_bounds = item_ui_->GetBoundsInScreen(); + gfx::Point point_outside_container = + container_bounds.bottom_right() + gfx::Vector2d(1, 1); + fake_screen_.set_cursor_screen_point(point_outside_container); + + ui::MouseEvent event(ui::ET_MOUSE_EXITED, gfx::Point(), gfx::Point(), + ui::EventTimeForNow(), 0, 0); + item_ui_->OnMouseExited(event); + } + + void SimulateItemUIClicked() { + ui::MouseEvent event(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(), + ui::EventTimeForNow(), 0, 0); + views::test::ButtonTestApi(item_ui_).NotifyClick(event); + } + + void SimulateHeaderClicked() { + ui::MouseEvent event(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(), + ui::EventTimeForNow(), 0, 0); + views::test::ButtonTestApi(GetView()->GetHeaderRowForTesting()) + .NotifyClick(event); + } + + void SimulateDismissButtonClicked() { + ui::MouseEvent event(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(), + ui::EventTimeForNow(), 0, 0); + views::test::ButtonTestApi(GetDismissButton()).NotifyClick(event); + } + + void SimulatePressingDismissButtonWithKeyboard() { + GetFocusManager()->SetFocusedView(item_ui_->GetDismissButtonForTesting()); + +// On Mac OS, we need to use the space bar to press a button. +#if defined(OS_MAC) + ui::KeyboardCode button_press_keycode = ui::VKEY_SPACE; +#else + ui::KeyboardCode button_press_keycode = ui::VKEY_RETURN; +#endif // defined(OS_MAC) + + ui::test::EventGenerator generator(GetRootWindow(widget_.get())); + generator.PressKey(button_press_keycode, 0); + } + + void SimulateSessionPlaying() { SimulateSessionInfo(true); } + + void SimulateSessionPaused() { SimulateSessionInfo(false); } + + void SimulateMetadataChanged() { + media_session::MediaMetadata metadata; + metadata.source_title = u"source_title2"; + metadata.title = u"title2"; + metadata.artist = u"artist2"; + GetView()->UpdateWithMediaMetadata(metadata); + } + + void SimulateAllActionsEnabled() { + actions_.insert(MediaSessionAction::kPlay); + actions_.insert(MediaSessionAction::kPause); + actions_.insert(MediaSessionAction::kPreviousTrack); + actions_.insert(MediaSessionAction::kNextTrack); + actions_.insert(MediaSessionAction::kSeekBackward); + actions_.insert(MediaSessionAction::kSeekForward); + actions_.insert(MediaSessionAction::kStop); + + NotifyUpdatedActions(); + } + + void SimulateOnlyPlayPauseEnabled() { + actions_.clear(); + actions_.insert(MediaSessionAction::kPlay); + actions_.insert(MediaSessionAction::kPause); + NotifyUpdatedActions(); + } + + void SimulateHasArtwork() { + SkBitmap image; + image.allocN32Pixels(10, 10); + image.eraseColor(SK_ColorMAGENTA); + GetView()->UpdateWithMediaArtwork( + gfx::ImageSkia::CreateFrom1xBitmap(image)); + } + + void SimulateHasNoArtwork() { + GetView()->UpdateWithMediaArtwork(gfx::ImageSkia()); + } + + views::FocusManager* GetFocusManager() { return item_ui_->GetFocusManager(); } + + test::MockMediaItemUIObserver& observer() { return *observer_; } + + MediaItemUIView* item_ui() { return item_ui_; } + + base::WeakPtr<media_message_center::test::MockMediaNotificationItem> + notification_item() { + return item_->GetWeakPtr(); + } + + private: + void SimulateSessionInfo(bool playing) { + media_session::mojom::MediaSessionInfoPtr session_info( + media_session::mojom::MediaSessionInfo::New()); + session_info->playback_state = + playing ? MediaPlaybackState::kPlaying : MediaPlaybackState::kPaused; + session_info->is_controllable = true; + + GetView()->UpdateWithMediaSessionInfo(std::move(session_info)); + } + + void SimulateMediaSessionData() { + SimulateSessionInfo(true); + + media_session::MediaMetadata metadata; + metadata.source_title = u"source_title"; + metadata.title = u"title"; + metadata.artist = u"artist"; + GetView()->UpdateWithMediaMetadata(metadata); + + SimulateOnlyPlayPauseEnabled(); + } + + void NotifyUpdatedActions() { GetView()->UpdateWithMediaActions(actions_); } + + media_message_center::MediaNotificationViewImpl* GetView() { + return item_ui()->view_for_testing(); + } + + views::ImageButton* GetDismissButton() { + return item_ui()->GetDismissButtonForTesting(); + } + + std::unique_ptr<views::Widget> widget_; + test::MockMediaItemUIFooter* footer_ = nullptr; + test::MockMediaItemUIDeviceSelector* device_selector_ = nullptr; + MediaItemUIView* item_ui_ = nullptr; + std::unique_ptr<global_media_controls::test::MockMediaItemUIObserver> + observer_; + std::unique_ptr<media_message_center::test::MockMediaNotificationItem> item_; + + // Set of actions currently enabled. + base::flat_set<MediaSessionAction> actions_; + + display::test::TestScreen fake_screen_; + display::test::ScopedScreenOverride screen_override_; +}; + +TEST_F(MediaItemUIViewTest, SwipeToDismiss) { + EXPECT_CALL(observer(), OnMediaItemUIDismissed(kTestNotificationId)); + SimulateItemUISwipedToDismiss(); +} + +TEST_F(MediaItemUIViewTest, ClickToDismiss) { + // Ensure that the mouse is not over the container and that nothing is + // focused. The dismiss button should not be visible. + SimulateNotHoveringOverItemUI(); + ASSERT_EQ(nullptr, GetFocusManager()->GetFocusedView()); + ASSERT_FALSE(item_ui()->IsMouseHovered()); + EXPECT_FALSE(IsDismissButtonVisible()); + + // Hovering over the notification should show the dismiss button. + SimulateHoverOverItemUI(); + EXPECT_TRUE(IsDismissButtonVisible()); + + // Moving the mouse away from the notification should hide the dismiss button. + SimulateNotHoveringOverItemUI(); + EXPECT_FALSE(IsDismissButtonVisible()); + + // Moving the mouse back over the notification should re-show it. + SimulateHoverOverItemUI(); + EXPECT_TRUE(IsDismissButtonVisible()); + + // Clicking it should inform observers that we've been dismissed. + EXPECT_CALL(observer(), OnMediaItemUIDismissed(kTestNotificationId)); + SimulateDismissButtonClicked(); + testing::Mock::VerifyAndClearExpectations(&observer()); +} + +TEST_F(MediaItemUIViewTest, KeyboardToDismiss) { + // Ensure that the mouse is not over the container and that nothing is + // focused. The dismiss button should not be visible. + SimulateNotHoveringOverItemUI(); + ASSERT_EQ(nullptr, GetFocusManager()->GetFocusedView()); + ASSERT_FALSE(item_ui()->IsMouseHovered()); + EXPECT_FALSE(IsDismissButtonVisible()); + + // When the notification receives keyboard focus, the dismiss button should be + // visible. + GetFocusManager()->SetFocusedView(item_ui()); + EXPECT_TRUE(IsDismissButtonVisible()); + + // When the notification loses keyboard focus, the dismiss button should be + // hidden. + GetFocusManager()->SetFocusedView(nullptr); + EXPECT_FALSE(IsDismissButtonVisible()); + + // If it gets focus again, it should re-show the dismiss button. + GetFocusManager()->SetFocusedView(item_ui()); + EXPECT_TRUE(IsDismissButtonVisible()); + + // Clicking it should inform observers that we've been dismissed. + EXPECT_CALL(observer(), OnMediaItemUIDismissed(kTestNotificationId)); + SimulatePressingDismissButtonWithKeyboard(); + testing::Mock::VerifyAndClearExpectations(&observer()); +} + +TEST_F(MediaItemUIViewTest, ForceExpandedState) { + // When we have many actions enabled, we should be forced into the expanded + // state. + SimulateAllActionsEnabled(); + EXPECT_TRUE(item_ui()->is_expanded_for_testing()); + + // When we don't have many actions enabled, we should be forced out of the + // expanded state. + SimulateOnlyPlayPauseEnabled(); + EXPECT_FALSE(item_ui()->is_expanded_for_testing()); + + // We will also be forced into the expanded state when artwork is present. + SimulateHasArtwork(); + EXPECT_TRUE(item_ui()->is_expanded_for_testing()); + + // Once the artwork is gone, we should be forced back out of the expanded + // state. + SimulateHasNoArtwork(); + EXPECT_FALSE(item_ui()->is_expanded_for_testing()); +} + +TEST_F(MediaItemUIViewTest, SendsMetadataUpdates) { + EXPECT_CALL(observer(), OnMediaItemUIMetadataChanged()); + SimulateMetadataChanged(); +} + +TEST_F(MediaItemUIViewTest, SendsDestroyedUpdates) { + auto container = std::make_unique<MediaItemUIView>( + kOtherTestNotificationId, notification_item(), nullptr, nullptr); + global_media_controls::test::MockMediaItemUIObserver observer; + container->AddObserver(&observer); + + // When the container is destroyed, it should notify the observer. + EXPECT_CALL(observer, OnMediaItemUIDestroyed(kOtherTestNotificationId)); + container.reset(); + testing::Mock::VerifyAndClearExpectations(&observer); +} + +TEST_F(MediaItemUIViewTest, SendsClicks) { + // When the container is clicked directly, it should notify its observers. + EXPECT_CALL(observer(), OnMediaItemUIClicked(kTestNotificationId)); + SimulateItemUIClicked(); + testing::Mock::VerifyAndClearExpectations(&observer()); + + // It should also notify its observers when the header is clicked. + EXPECT_CALL(observer(), OnMediaItemUIClicked(kTestNotificationId)); + SimulateHeaderClicked(); +} + +TEST_F(MediaItemUIViewTest, MetadataTest) { + auto container_view = std::make_unique<MediaItemUIView>( + kOtherTestNotificationId, notification_item(), nullptr, nullptr); + views::test::TestViewMetadata(container_view.get()); +} + +} // namespace global_media_controls
diff --git a/components/global_media_controls_strings.grdp b/components/global_media_controls_strings.grdp new file mode 100644 index 0000000..24e9a21 --- /dev/null +++ b/components/global_media_controls_strings.grdp
@@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8"?> +<grit-part> + <message name="IDS_GLOBAL_MEDIA_CONTROLS_BACK_TO_TAB" desc="A11y text for the Global Media Controls container describing how clicking it takes you back to the tab."> + Back to tab + </message> + <message name="IDS_GLOBAL_MEDIA_CONTROLS_DISMISS_ICON_TOOLTIP_TEXT" desc="Tooltip for the dismiss button within the Global Media Controls dialog. The tooltip appears on mouseover of the icon."> + Dismiss + </message> +</grit-part>
diff --git a/chrome/app/global_media_controls_strings_grdp/IDS_GLOBAL_MEDIA_CONTROLS_BACK_TO_TAB.png.sha1 b/components/global_media_controls_strings_grdp/IDS_GLOBAL_MEDIA_CONTROLS_BACK_TO_TAB.png.sha1 similarity index 100% rename from chrome/app/global_media_controls_strings_grdp/IDS_GLOBAL_MEDIA_CONTROLS_BACK_TO_TAB.png.sha1 rename to components/global_media_controls_strings_grdp/IDS_GLOBAL_MEDIA_CONTROLS_BACK_TO_TAB.png.sha1
diff --git a/chrome/app/global_media_controls_strings_grdp/IDS_GLOBAL_MEDIA_CONTROLS_DISMISS_ICON_TOOLTIP_TEXT.png.sha1 b/components/global_media_controls_strings_grdp/IDS_GLOBAL_MEDIA_CONTROLS_DISMISS_ICON_TOOLTIP_TEXT.png.sha1 similarity index 100% rename from chrome/app/global_media_controls_strings_grdp/IDS_GLOBAL_MEDIA_CONTROLS_DISMISS_ICON_TOOLTIP_TEXT.png.sha1 rename to components/global_media_controls_strings_grdp/IDS_GLOBAL_MEDIA_CONTROLS_DISMISS_ICON_TOOLTIP_TEXT.png.sha1
diff --git a/components/media_message_center/BUILD.gn b/components/media_message_center/BUILD.gn index 106f9729..9389449 100644 --- a/components/media_message_center/BUILD.gn +++ b/components/media_message_center/BUILD.gn
@@ -60,6 +60,7 @@ deps = [ ":media_message_center", + ":test_support", "//base", "//base/test:test_support", "//services/media_session/public/cpp/test:test_support", @@ -79,6 +80,8 @@ testonly = true sources = [ + "mock_media_notification_item.cc", + "mock_media_notification_item.h", "mock_media_notification_view.cc", "mock_media_notification_view.h", ]
diff --git a/components/media_message_center/media_notification_view_impl_unittest.cc b/components/media_message_center/media_notification_view_impl_unittest.cc index 44454d3..60bfcb1 100644 --- a/components/media_message_center/media_notification_view_impl_unittest.cc +++ b/components/media_message_center/media_notification_view_impl_unittest.cc
@@ -18,7 +18,7 @@ #include "build/build_config.h" #include "components/media_message_center/media_notification_background_impl.h" #include "components/media_message_center/media_notification_container.h" -#include "components/media_message_center/media_notification_item.h" +#include "components/media_message_center/mock_media_notification_item.h" #include "services/media_session/public/mojom/media_session.mojom.h" #include "testing/gmock/include/gmock/gmock.h" #include "ui/accessibility/ax_enums.mojom.h" @@ -57,32 +57,6 @@ constexpr int kViewArtworkWidth = kViewWidth * 0.4; const gfx::Size kViewSize(kViewWidth, 400); -class MockMediaNotificationItem : public MediaNotificationItem { - public: - MockMediaNotificationItem() = default; - MockMediaNotificationItem(const MockMediaNotificationItem&) = delete; - MockMediaNotificationItem& operator=(const MockMediaNotificationItem&) = - delete; - ~MockMediaNotificationItem() override = default; - - MOCK_METHOD(void, SetView, (MediaNotificationView*)); - MOCK_METHOD(void, - OnMediaSessionActionButtonPressed, - (media_session::mojom::MediaSessionAction)); - MOCK_METHOD(void, SeekTo, (base::TimeDelta)); - MOCK_METHOD(void, Dismiss, ()); - MOCK_METHOD(void, SetVolume, (float)); - MOCK_METHOD(void, SetMute, (bool)); - MOCK_METHOD(media_message_center::SourceType, SourceType, ()); - - base::WeakPtr<MockMediaNotificationItem> GetWeakPtr() { - return weak_ptr_factory_.GetWeakPtr(); - } - - private: - base::WeakPtrFactory<MockMediaNotificationItem> weak_ptr_factory_{this}; -}; - class MockMediaNotificationContainer : public MediaNotificationContainer { public: MockMediaNotificationContainer() = default; @@ -212,7 +186,7 @@ return GetButtonForAction(action)->GetVisible(); } - MockMediaNotificationItem& item() { return item_; } + test::MockMediaNotificationItem& item() { return item_; } const gfx::ImageSkia& GetArtworkImage() const { return static_cast<MediaNotificationBackgroundImpl*>( @@ -292,7 +266,7 @@ base::flat_set<MediaSessionAction> actions_; MockMediaNotificationContainer container_; - MockMediaNotificationItem item_; + test::MockMediaNotificationItem item_; MediaNotificationViewImpl* view_; std::unique_ptr<views::Widget> widget_; };
diff --git a/components/media_message_center/media_notification_view_modern_impl_unittest.cc b/components/media_message_center/media_notification_view_modern_impl_unittest.cc index 42ebd69..e949fd87 100644 --- a/components/media_message_center/media_notification_view_modern_impl_unittest.cc +++ b/components/media_message_center/media_notification_view_modern_impl_unittest.cc
@@ -19,8 +19,8 @@ #include "components/media_message_center/media_controls_progress_view.h" #include "components/media_message_center/media_notification_background_impl.h" #include "components/media_message_center/media_notification_container.h" -#include "components/media_message_center/media_notification_item.h" #include "components/media_message_center/media_notification_util.h" +#include "components/media_message_center/mock_media_notification_item.h" #include "services/media_session/public/mojom/media_session.mojom.h" #include "testing/gmock/include/gmock/gmock.h" #include "ui/accessibility/ax_enums.mojom.h" @@ -52,32 +52,6 @@ constexpr int kViewWidth = 350; const gfx::Size kViewSize(kViewWidth, 400); -class MockMediaNotificationItem : public MediaNotificationItem { - public: - MockMediaNotificationItem() = default; - MockMediaNotificationItem(const MockMediaNotificationItem&) = delete; - MockMediaNotificationItem& operator=(const MockMediaNotificationItem&) = - delete; - ~MockMediaNotificationItem() override = default; - - MOCK_METHOD(void, SetView, (MediaNotificationView*)); - MOCK_METHOD(void, - OnMediaSessionActionButtonPressed, - (media_session::mojom::MediaSessionAction)); - MOCK_METHOD(void, SeekTo, (base::TimeDelta)); - MOCK_METHOD(void, Dismiss, ()); - MOCK_METHOD(void, SetVolume, (float)); - MOCK_METHOD(void, SetMute, (bool)); - MOCK_METHOD(media_message_center::SourceType, SourceType, ()); - - base::WeakPtr<MockMediaNotificationItem> GetWeakPtr() { - return weak_ptr_factory_.GetWeakPtr(); - } - - private: - base::WeakPtrFactory<MockMediaNotificationItem> weak_ptr_factory_{this}; -}; - class MockMediaNotificationContainer : public MediaNotificationContainer { public: MockMediaNotificationContainer() = default; @@ -172,7 +146,7 @@ return view()->accessible_name_; } - MockMediaNotificationItem& item() { return item_; } + test::MockMediaNotificationItem& item() { return item_; } views::Label* title_label() const { return view()->title_label_; } @@ -274,7 +248,7 @@ base::flat_set<MediaSessionAction> actions_; MockMediaNotificationContainer container_; - MockMediaNotificationItem item_; + test::MockMediaNotificationItem item_; MediaNotificationViewModernImpl* view_; std::unique_ptr<views::Widget> widget_; };
diff --git a/components/media_message_center/mock_media_notification_item.cc b/components/media_message_center/mock_media_notification_item.cc new file mode 100644 index 0000000..fce1b78 --- /dev/null +++ b/components/media_message_center/mock_media_notification_item.cc
@@ -0,0 +1,20 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/media_message_center/mock_media_notification_item.h" + +namespace media_message_center { +namespace test { + +MockMediaNotificationItem::MockMediaNotificationItem() = default; + +MockMediaNotificationItem::~MockMediaNotificationItem() = default; + +base::WeakPtr<MockMediaNotificationItem> +MockMediaNotificationItem::GetWeakPtr() { + return weak_ptr_factory_.GetWeakPtr(); +} + +} // namespace test +} // namespace media_message_center
diff --git a/components/media_message_center/mock_media_notification_item.h b/components/media_message_center/mock_media_notification_item.h new file mode 100644 index 0000000..99c7530 --- /dev/null +++ b/components/media_message_center/mock_media_notification_item.h
@@ -0,0 +1,41 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_MEDIA_MESSAGE_CENTER_MOCK_MEDIA_NOTIFICATION_ITEM_H_ +#define COMPONENTS_MEDIA_MESSAGE_CENTER_MOCK_MEDIA_NOTIFICATION_ITEM_H_ + +#include "components/media_message_center/media_notification_item.h" +#include "testing/gmock/include/gmock/gmock.h" + +namespace media_message_center { +namespace test { + +class MockMediaNotificationItem : public MediaNotificationItem { + public: + MockMediaNotificationItem(); + MockMediaNotificationItem(const MockMediaNotificationItem&) = delete; + MockMediaNotificationItem& operator=(const MockMediaNotificationItem&) = + delete; + ~MockMediaNotificationItem() override; + + MOCK_METHOD(void, SetView, (MediaNotificationView*)); + MOCK_METHOD(void, + OnMediaSessionActionButtonPressed, + (media_session::mojom::MediaSessionAction)); + MOCK_METHOD(void, SeekTo, (base::TimeDelta)); + MOCK_METHOD(void, Dismiss, ()); + MOCK_METHOD(void, SetVolume, (float)); + MOCK_METHOD(void, SetMute, (bool)); + MOCK_METHOD(media_message_center::SourceType, SourceType, ()); + + base::WeakPtr<MockMediaNotificationItem> GetWeakPtr(); + + private: + base::WeakPtrFactory<MockMediaNotificationItem> weak_ptr_factory_{this}; +}; + +} // namespace test +} // namespace media_message_center + +#endif // COMPONENTS_MEDIA_MESSAGE_CENTER_MOCK_MEDIA_NOTIFICATION_ITEM_H_
diff --git a/components/messages/android/internal/java/src/org/chromium/components/messages/MessageQueueManager.java b/components/messages/android/internal/java/src/org/chromium/components/messages/MessageQueueManager.java index 6d2c46a..215dec81 100644 --- a/components/messages/android/internal/java/src/org/chromium/components/messages/MessageQueueManager.java +++ b/components/messages/android/internal/java/src/org/chromium/components/messages/MessageQueueManager.java
@@ -25,7 +25,8 @@ * including situations in which the message is already dismissed and hide animation is running. */ @Nullable - private MessageQueueManager.MessageState mCurrentDisplayedMessage; + private MessageState mCurrentDisplayedMessage; + private MessageState mLastShownMessage; private MessageQueueDelegate mMessageQueueDelegate; // TokenHolder tracking whether the queue should be suspended. private final TokenHolder mSuppressionTokenHolder = @@ -182,7 +183,13 @@ if (mCurrentDisplayedMessage != candidate) { if (mCurrentDisplayedMessage == null) { mCurrentDisplayedMessage = candidate; - mMessageQueueDelegate.onStartShowing(mCurrentDisplayedMessage.handler::show); + mMessageQueueDelegate.onStartShowing(() -> { + if (mCurrentDisplayedMessage == null) { + return; + } + mCurrentDisplayedMessage.handler.show(); + mLastShownMessage = mCurrentDisplayedMessage; + }); } else { hideMessage(!isQueueSuspended() && animateTransition, !isQueueSuspended()); } @@ -205,11 +212,19 @@ } private void hideMessage(boolean animate, boolean updateCurrentMessage) { - mCurrentDisplayedMessage.handler.hide(animate, () -> { + assert mCurrentDisplayedMessage + != null + : "This should not be called when there is no valid currently displayed message."; + Runnable runnable = () -> { mMessageQueueDelegate.onFinishHiding(); mCurrentDisplayedMessage = null; if (updateCurrentMessage) updateCurrentDisplayedMessage(true, getNextMessage()); - }); + }; + if (mLastShownMessage != mCurrentDisplayedMessage) { + runnable.run(); + return; + } + mCurrentDisplayedMessage.handler.hide(animate, runnable); } /**
diff --git a/components/messages/android/internal/java/src/org/chromium/components/messages/MessageQueueManagerTest.java b/components/messages/android/internal/java/src/org/chromium/components/messages/MessageQueueManagerTest.java index 4416605..9ac40db 100644 --- a/components/messages/android/internal/java/src/org/chromium/components/messages/MessageQueueManagerTest.java +++ b/components/messages/android/internal/java/src/org/chromium/components/messages/MessageQueueManagerTest.java
@@ -24,6 +24,7 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; import org.mockito.Mockito; import org.robolectric.annotation.Config; @@ -463,6 +464,40 @@ } /** + * Test that callback can be correctly called if #hide is called without #show called before. + */ + @Test + @SmallTest + public void testShowHideMultipleTimes() { + MessageQueueDelegate delegate = Mockito.spy(MessageQueueDelegate.class); + MessageQueueManager queueManager = new MessageQueueManager(); + queueManager.setDelegate(delegate); + MessageStateHandler m1 = Mockito.spy(new EmptyMessageStateHandler()); + queueManager.enqueueMessage(m1, m1, SCOPE_INSTANCE_ID, false); + + ArgumentCaptor<Runnable> runnableCaptor = ArgumentCaptor.forClass(Runnable.class); + verify(delegate).onStartShowing(runnableCaptor.capture()); + Runnable onShow = runnableCaptor.getValue(); + verify(m1, never()).show(); + queueManager.onScopeChange( + new MessageScopeChange(SCOPE_TYPE, SCOPE_INSTANCE_ID, ChangeType.INACTIVE)); + verify(m1, never()).hide(anyBoolean(), any()); + onShow.run(); + verify(m1, never()).show(); + + queueManager.onScopeChange( + new MessageScopeChange(SCOPE_TYPE, SCOPE_INSTANCE_ID, ChangeType.ACTIVE)); + runnableCaptor = ArgumentCaptor.forClass(Runnable.class); + verify(delegate, times(2)).onStartShowing(runnableCaptor.capture()); + runnableCaptor.getValue().run(); + verify(m1).show(); + + queueManager.onScopeChange( + new MessageScopeChange(SCOPE_TYPE, SCOPE_INSTANCE_ID, ChangeType.DESTROY)); + verify(m1).hide(anyBoolean(), any()); + } + + /** * Test scope change controller is properly called when message is enqueued and dismissed. */ @Test
diff --git a/components/metrics/clean_exit_beacon_unittest.cc b/components/metrics/clean_exit_beacon_unittest.cc index 0cdd64a..436fbda7 100644 --- a/components/metrics/clean_exit_beacon_unittest.cc +++ b/components/metrics/clean_exit_beacon_unittest.cc
@@ -51,23 +51,6 @@ } // namespace -class FakeTestingPrefStore : public TestingPrefStore { - public: - void CommitPendingWriteSynchronously() override { - was_commit_pending_write_synchronously_called_ = true; - } - - bool was_commit_pending_write_synchronously_called() { - return was_commit_pending_write_synchronously_called_; - } - - protected: - ~FakeTestingPrefStore() override = default; - - private: - bool was_commit_pending_write_synchronously_called_ = false; -}; - class TestCleanExitBeacon : public CleanExitBeacon { public: explicit TestCleanExitBeacon( @@ -363,20 +346,10 @@ ASSERT_EQ(variations::kControlGroup, base::FieldTrialList::FindFullName( variations::kExtendedSafeModeTrial)); - PrefServiceFactory factory; - scoped_refptr<FakeTestingPrefStore> pref_store(new FakeTestingPrefStore); - factory.set_user_prefs(pref_store); - scoped_refptr<PrefRegistrySimple> registry(new PrefRegistrySimple); - std::unique_ptr<PrefService> prefs(factory.Create(registry.get())); - CleanExitBeacon::RegisterPrefs(registry.get()); - TestCleanExitBeacon clean_exit_beacon(prefs.get(), user_data_dir_.GetPath()); + TestCleanExitBeacon clean_exit_beacon(&prefs_, user_data_dir_.GetPath()); EXPECT_DCHECK_DEATH( clean_exit_beacon.WriteBeaconValue(/*exited_cleanly=*/false, /*write_synchronously=*/true)); - - // Verify that CommitPendingWriteSynchronously() was not called and that - // the WritePrefsTime metric was not emitted. - EXPECT_FALSE(pref_store->was_commit_pending_write_synchronously_called()); histogram_tester_.ExpectTotalCount( "Variations.ExtendedSafeMode.WritePrefsTime", 0); }
diff --git a/components/optimization_guide/proto/common_types.proto b/components/optimization_guide/proto/common_types.proto index 85c0d62..48683c2 100644 --- a/components/optimization_guide/proto/common_types.proto +++ b/components/optimization_guide/proto/common_types.proto
@@ -78,6 +78,19 @@ optional int32 nanos = 2; } +message Timestamp { + // Represents seconds of UTC time since Unix epoch + // 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to + // 9999-12-31T23:59:59Z inclusive. + optional int64 seconds = 1; + + // Non-negative fractions of a second at nanosecond resolution. Negative + // second values with fractions must still have non-negative nanos values + // that count forward in time. Must be from 0 to 999,999,999 + // inclusive. + optional int32 nanos = 2; +} + message Any { // A URL/resource name that uniquely identifies the type of the serialized // protocol buffer message.
diff --git a/components/optimization_guide/proto/hints.proto b/components/optimization_guide/proto/hints.proto index a6fd2fe..889a0bf 100644 --- a/components/optimization_guide/proto/hints.proto +++ b/components/optimization_guide/proto/hints.proto
@@ -311,19 +311,6 @@ repeated OptimizationFilter optimization_allowlists = 3; } -message Timestamp { - // Represents seconds of UTC time since Unix epoch - // 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to - // 9999-12-31T23:59:59Z inclusive. - optional int64 seconds = 1; - - // Non-negative fractions of a second at nanosecond resolution. Negative - // second values with fractions must still have non-negative nanos values - // that count forward in time. Must be from 0 to 999,999,999 - // inclusive. - optional int32 nanos = 2; -} - enum HintSource { HINT_SOURCE_UNKNOWN = 0; // Served from the Chrome Optimization Hints Component.
diff --git a/components/page_info/BUILD.gn b/components/page_info/BUILD.gn index d933a85..a3cd3aa 100644 --- a/components/page_info/BUILD.gn +++ b/components/page_info/BUILD.gn
@@ -1,7 +1,27 @@ +import("//third_party/protobuf/proto_library.gni") + if (is_android) { import("//build/config/android/rules.gni") } +proto_library("proto") { + proto_in_dir = "//" + sources = [ "proto/about_this_site_metadata.proto" ] + + deps = [ "//components/optimization_guide/proto:optimization_guide_proto" ] +} + +if (is_android) { + proto_java_library("proto_java") { + proto_path = "//" + sources = [ "proto/about_this_site_metadata.proto" ] + + deps = [ + "//components/optimization_guide/proto:optimization_guide_proto_java", + ] + } +} + static_library("page_info") { sources = [ "about_this_site_service.cc", @@ -25,6 +45,7 @@ "//components/keyed_service/core", "//components/omnibox/common", "//components/optimization_guide/core", + "//components/page_info:proto", "//components/password_manager/core/browser", "//components/permissions", "//components/prefs",
diff --git a/components/page_info/DEPS b/components/page_info/DEPS index dde4bec..bf0ac75 100644 --- a/components/page_info/DEPS +++ b/components/page_info/DEPS
@@ -4,6 +4,7 @@ "+components/content_settings", "+components/keyed_service/core", "+components/optimization_guide/core", + "+components/optimization_guide/proto", "+components/password_manager", "+components/permissions", "+components/prefs",
diff --git a/components/page_info/about_this_site_service.cc b/components/page_info/about_this_site_service.cc index 58b3f174..cc85126 100644 --- a/components/page_info/about_this_site_service.cc +++ b/components/page_info/about_this_site_service.cc
@@ -12,23 +12,39 @@ AboutThisSiteService::AboutThisSiteService(std::unique_ptr<Client> client) : client_(std::move(client)) {} -std::u16string AboutThisSiteService::GetAboutThisSiteDescription( - const GURL& url) const { - // TODO(crbug.com/1250653): Return the actual data after server-side is ready - // and proto is added. +absl::optional<page_info::proto::SiteInfo> +AboutThisSiteService::GetAboutThisSiteInfo(const GURL& url) const { + optimization_guide::OptimizationMetadata metadata; + client_->CanApplyOptimization(url, &metadata); + absl::optional<page_info::proto::AboutThisSiteMetadata> + about_this_site_metadata = + metadata.ParsedMetadata<page_info::proto::AboutThisSiteMetadata>(); + // TODO(crbug.com/1250653): Add validation to check if proto contains any + // useful data. + if (about_this_site_metadata) { + return about_this_site_metadata->site_info(); + } + + // TODO(crbug.com/1250653): Remove returning fake data after server-side is + // ready. + page_info::proto::SiteInfo site_info_metadata; const GURL test_gurl("https://example.com"); if (url == test_gurl) { - return u"A domain used in illustrative examples in documents"; + site_info_metadata.set_entity_description( + "A domain used in illustrative examples in documents"); + return site_info_metadata; } const GURL permissions_gurl("https://permission.site"); if (url == permissions_gurl) { - return u"A site containing test buttons for various browser APIs, in order" - " to trigger permission dialogues and similar UI in modern " - "browsers."; + site_info_metadata.set_entity_description( + "A site containing test buttons for various browser APIs, in order" + " to trigger permission dialogues and similar UI in modern " + "browsers."); + return site_info_metadata; } - return std::u16string(); + return absl::nullopt; } AboutThisSiteService::~AboutThisSiteService() = default;
diff --git a/components/page_info/about_this_site_service.h b/components/page_info/about_this_site_service.h index bd82bd5..d12160c 100644 --- a/components/page_info/about_this_site_service.h +++ b/components/page_info/about_this_site_service.h
@@ -10,6 +10,7 @@ #include "components/keyed_service/core/keyed_service.h" #include "components/optimization_guide/core/optimization_guide_decision.h" #include "components/optimization_guide/core/optimization_metadata.h" +#include "components/page_info/proto/about_this_site_metadata.pb.h" class GURL; @@ -38,7 +39,8 @@ AboutThisSiteService& operator=(const AboutThisSiteService&) = delete; // Returns "About this site" information for the website with |url|. - std::u16string GetAboutThisSiteDescription(const GURL& url) const; + absl::optional<page_info::proto::SiteInfo> GetAboutThisSiteInfo( + const GURL& url) const; private: std::unique_ptr<Client> client_;
diff --git a/components/page_info/proto/about_this_site_metadata.proto b/components/page_info/proto/about_this_site_metadata.proto new file mode 100644 index 0000000..ce424f8 --- /dev/null +++ b/components/page_info/proto/about_this_site_metadata.proto
@@ -0,0 +1,60 @@ +// Copyright 2021 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. + +syntax = "proto2"; + +option optimize_for = LITE_RUNTIME; +option java_package = "org.chromium.components.page_info.proto"; + +package page_info.proto; + +// Represents a duration like “3 days” or “2 years”. It should always use the +// lowest possible granularity. E.g. use “1 month” as soon as an event happened +// at least 30 days ago. When precision is MORE_THAN, the event happened at +// least the specified time ago, e.g. “more than 2 years ago”. +message CoarseDuration { + optional int32 count = 1; + optional DurationUnit unit = 2; + optional DurationPrecision precision = 3; +} + +enum DurationUnit { + DURATION_UNIT_UNSPECIFIED = 0; + DURATION_UNIT_DAYS = 1; + DURATION_UNIT_MONTHS = 2; + DURATION_UNIT_YEARS = 3; +} + +enum DurationPrecision { + DURATION_PRECISION_UNSPECIFIED = 0; + DURATION_PRECISION_ABOUT = 1; + DURATION_PRECISION_LESS_THAN = 2; + DURATION_PRECISION_MORE_THAN = 3; +} + +message SiteInfo { + // First-seen date information related to this host/domain. + // When Google first indexed this site. + optional CoarseDuration first_seen = 1; + + // Name of the entity associated with the site. + optional string entity_name = 2; + + // Description of the entity associated with the site. + optional string entity_description = 3; + + // Source URL of this information. + optional string source_url = 4; + + // Name of the source of this information. + optional string source_name = 5; +} + +// Optimization metadata associated with SiteInfo. +// +// This is only populated for the ABOUT_THIS_SITE optimization type. +message AboutThisSiteMetadata { + // A SiteInfo hint. + optional SiteInfo site_info = 1; +}
diff --git a/components/password_manager/core/browser/BUILD.gn b/components/password_manager/core/browser/BUILD.gn index a3dca1c..d37db989 100644 --- a/components/password_manager/core/browser/BUILD.gn +++ b/components/password_manager/core/browser/BUILD.gn
@@ -313,6 +313,8 @@ if (is_android) { sources += [ + "built_in_backend_to_android_backend_migrator.cc", + "built_in_backend_to_android_backend_migrator.h", "password_scripts_fetcher.h", "password_scripts_fetcher_impl.cc", "password_scripts_fetcher_impl.h",
diff --git a/components/password_manager/core/browser/built_in_backend_to_android_backend_migrator.cc b/components/password_manager/core/browser/built_in_backend_to_android_backend_migrator.cc new file mode 100644 index 0000000..b534535 --- /dev/null +++ b/components/password_manager/core/browser/built_in_backend_to_android_backend_migrator.cc
@@ -0,0 +1,24 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/password_manager/core/browser/built_in_backend_to_android_backend_migrator.h" + +namespace password_manager { + +BuiltInBackendToAndroidBackendMigrator:: + BuiltInBackendToAndroidBackendMigrator() = default; + +BuiltInBackendToAndroidBackendMigrator:: + ~BuiltInBackendToAndroidBackendMigrator() = default; + +void BuiltInBackendToAndroidBackendMigrator::StartMigrationIfNecessary() { + // TODO:(crbug.com/1252443) Check current migration version and version + // saved in pref. If current version is higher, start migration. +} + +void BuiltInBackendToAndroidBackendMigrator::UpdateMigrationVersionInPref() { + // TODO:(crbug.com/1252443) Save current migration version in pref. +} + +} // namespace password_manager
diff --git a/components/password_manager/core/browser/built_in_backend_to_android_backend_migrator.h b/components/password_manager/core/browser/built_in_backend_to_android_backend_migrator.h new file mode 100644 index 0000000..c815c22 --- /dev/null +++ b/components/password_manager/core/browser/built_in_backend_to_android_backend_migrator.h
@@ -0,0 +1,37 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_BUILT_IN_BACKEND_TO_ANDROID_BACKEND_MIGRATOR_H_ +#define COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_BUILT_IN_BACKEND_TO_ANDROID_BACKEND_MIGRATOR_H_ + +#include "base/callback.h" +#include "base/callback_forward.h" + +namespace password_manager { +// Instantiate this object to migrate all password stored in the built-in +// backend to the Android backend. Migration is potentially an expensive +// operation and shouldn't start during the hot phase of Chrome start. +class BuiltInBackendToAndroidBackendMigrator { + public: + BuiltInBackendToAndroidBackendMigrator(); + BuiltInBackendToAndroidBackendMigrator( + const BuiltInBackendToAndroidBackendMigrator&) = delete; + BuiltInBackendToAndroidBackendMigrator& operator=( + const BuiltInBackendToAndroidBackendMigrator&) = delete; + BuiltInBackendToAndroidBackendMigrator( + BuiltInBackendToAndroidBackendMigrator&&) = delete; + BuiltInBackendToAndroidBackendMigrator& operator=( + BuiltInBackendToAndroidBackendMigrator&&) = delete; + ~BuiltInBackendToAndroidBackendMigrator(); + + void StartMigrationIfNecessary(); + + private: + // Saves current migration version in 'pref_'. + void UpdateMigrationVersionInPref(); +}; + +} // namespace password_manager + +#endif // COMPONENTS_PASSWORD_MANAGER_CORE_BROWSER_BUILT_IN_BACKEND_TO_ANDROID_BACKEND_MIGRATOR_H_
diff --git a/components/password_manager/core/browser/password_store_backend_migration_decorator.cc b/components/password_manager/core/browser/password_store_backend_migration_decorator.cc index f52b513..4d69935 100644 --- a/components/password_manager/core/browser/password_store_backend_migration_decorator.cc +++ b/components/password_manager/core/browser/password_store_backend_migration_decorator.cc
@@ -5,6 +5,7 @@ #include "components/password_manager/core/browser/password_store_backend_migration_decorator.h" #include "base/bind.h" +#include "components/password_manager/core/browser/built_in_backend_to_android_backend_migrator.h" #include "components/password_manager/core/browser/field_info_table.h" #include "components/password_manager/core/browser/password_store_impl.h" #include "components/password_manager/core/browser/password_store_proxy_backend.h" @@ -33,6 +34,8 @@ active_backend_->InitBackend(std::move(remote_form_changes_received), std::move(sync_enabled_or_disabled_cb), std::move(completion)); + // TODO:(crbug.com/1252443) If feature is enabled post delayed task to start + // migration. } void PasswordStoreBackendMigrationDecorator::Shutdown( @@ -132,4 +135,9 @@ return active_backend_->CreateSyncControllerDelegateFactory(); } +void PasswordStoreBackendMigrationDecorator::StartMigration() { + migrator_ = std::make_unique<BuiltInBackendToAndroidBackendMigrator>(); + migrator_->StartMigrationIfNecessary(); +} + } // namespace password_manager
diff --git a/components/password_manager/core/browser/password_store_backend_migration_decorator.h b/components/password_manager/core/browser/password_store_backend_migration_decorator.h index 39a8c2f..21c536a 100644 --- a/components/password_manager/core/browser/password_store_backend_migration_decorator.h +++ b/components/password_manager/core/browser/password_store_backend_migration_decorator.h
@@ -12,6 +12,8 @@ namespace password_manager { +class BuiltInBackendToAndroidBackendMigrator; + // This is the backend that should be used on Android platform until the full // migration to the Android backend is launched. Internally, this backend // owns two backends: the built-in and the Android backend. In addition @@ -69,11 +71,16 @@ std::unique_ptr<syncer::ProxyModelTypeControllerDelegate> CreateSyncControllerDelegateFactory() override; + // Creates 'migrator_' and starts migration process. + void StartMigration(); + std::unique_ptr<PasswordStoreBackend> built_in_backend_; std::unique_ptr<PasswordStoreBackend> android_backend_; // Proxy backend to which all responsibilities are being delegated. std::unique_ptr<PasswordStoreBackend> active_backend_; + + std::unique_ptr<BuiltInBackendToAndroidBackendMigrator> migrator_; }; } // namespace password_manager
diff --git a/components/payments/content/android/BUILD.gn b/components/payments/content/android/BUILD.gn index 03eaa25..2aa2881 100644 --- a/components/payments/content/android/BUILD.gn +++ b/components/payments/content/android/BUILD.gn
@@ -212,6 +212,7 @@ "//ui/android:ui_utils_java", "//url:gurl_java", "//url:origin_java", + "//url/mojom:url_mojom_origin_java", ] srcjar_deps = [ ":payments_journey_logger_enum_javagen", @@ -318,6 +319,7 @@ "//url:gurl_java", "//url:gurl_junit_test_support", "//url:origin_java", + "//url/mojom:url_mojom_origin_java", ] } @@ -352,6 +354,7 @@ "//url:gurl_java", "//url:gurl_junit_test_support", "//url:origin_java", + "//url/mojom:url_mojom_origin_java", ] }
diff --git a/components/payments/content/android/java/src/org/chromium/components/payments/PaymentRequestService.java b/components/payments/content/android/java/src/org/chromium/components/payments/PaymentRequestService.java index 4293837..f468798 100644 --- a/components/payments/content/android/java/src/org/chromium/components/payments/PaymentRequestService.java +++ b/components/payments/content/android/java/src/org/chromium/components/payments/PaymentRequestService.java
@@ -533,8 +533,7 @@ if (PaymentFeatureList.isEnabledOrExperimentalFeaturesEnabled( PaymentFeatureList.SECURE_PAYMENT_CONFIRMATION) && methodData.containsKey(MethodStrings.SECURE_PAYMENT_CONFIRMATION) - && (methodData.size() > 1 || options.requestPayerEmail || options.requestPayerPhone - || options.requestShipping || options.requestPayerName)) { + && !isValidSecurePaymentConfirmationRequest(methodData, options)) { mJourneyLogger.setAborted(AbortReason.INVALID_DATA_FROM_RENDERER); disconnectFromClientWithDebugMessage(ErrorStrings.INVALID_PAYMENT_METHODS_OR_DATA, PaymentErrorReason.INVALID_DATA_FROM_RENDERER); @@ -574,6 +573,22 @@ return true; } + private boolean isValidSecurePaymentConfirmationRequest( + Map<String, PaymentMethodData> methodData, PaymentOptions options) { + if (methodData.size() > 1) return false; + if (options.requestPayerEmail || options.requestPayerPhone || options.requestShipping + || options.requestPayerName) { + return false; + } + PaymentMethodData spcMethodData = methodData.get(MethodStrings.SECURE_PAYMENT_CONFIRMATION); + if (spcMethodData.securePaymentConfirmation == null) return false; + if (spcMethodData.securePaymentConfirmation.payeeOrigin == null) return false; + Origin origin = new Origin(spcMethodData.securePaymentConfirmation.payeeOrigin); + if (origin.isOpaque()) return false; + if (origin.getScheme() == null) return false; + return origin.getScheme().equals("https"); + } + private void startPaymentAppService() { PaymentAppService service = mDelegate.getPaymentAppService(); mBrowserPaymentRequest.addPaymentAppFactories(service, /*delegate=*/this); @@ -893,10 +908,13 @@ assert mSpcAuthnUiController == null; mSpcAuthnUiController = SecurePaymentConfirmationAuthnController.create(mWebContents); + PaymentMethodData spcMethodData = + mSpec.getMethodData().get(MethodStrings.SECURE_PAYMENT_CONFIRMATION); + assert spcMethodData != null; boolean success = mSpcAuthnUiController.show( mBrowserPaymentRequest.getSelectedPaymentApp().getDrawableIcon(), - mBrowserPaymentRequest.getSelectedPaymentApp().getLabel(), getRawTotal(), - (response) -> { + mBrowserPaymentRequest.getSelectedPaymentApp().getLabel(), + getRawTotal(), (response) -> { if (response) { onSecurePaymentConfirmationUiAccepted( mBrowserPaymentRequest.getSelectedPaymentApp()); @@ -908,7 +926,7 @@ } mSpcAuthnUiController = null; - }); + }, new Origin(spcMethodData.securePaymentConfirmation.payeeOrigin)); if (success) { mJourneyLogger.setShown();
diff --git a/components/payments/content/android/java/src/org/chromium/components/payments/secure_payment_confirmation/SecurePaymentConfirmationAuthnController.java b/components/payments/content/android/java/src/org/chromium/components/payments/secure_payment_confirmation/SecurePaymentConfirmationAuthnController.java index bb2cd81..8ef6320 100644 --- a/components/payments/content/android/java/src/org/chromium/components/payments/secure_payment_confirmation/SecurePaymentConfirmationAuthnController.java +++ b/components/payments/content/android/java/src/org/chromium/components/payments/secure_payment_confirmation/SecurePaymentConfirmationAuthnController.java
@@ -23,6 +23,7 @@ import org.chromium.ui.base.WindowAndroid; import org.chromium.ui.modelutil.PropertyModel; import org.chromium.ui.modelutil.PropertyModelChangeProcessor; +import org.chromium.url.Origin; import java.util.Locale; @@ -140,9 +141,10 @@ * @param paymentInstrumentLabel The label to display for the payment instrument. * @param total The total amount of the transaction. * @param callback The function to call on sheet dismiss; false if it failed. + * @param payeeOrigin The origin of the payee. */ public boolean show(Drawable paymentIcon, String paymentInstrumentLabel, PaymentItem total, - Callback<Boolean> callback) { + Callback<Boolean> callback, Origin payeeOrigin) { if (mHider != null) return false; WindowAndroid windowAndroid = mWebContents.getTopLevelNativeWindow(); @@ -155,8 +157,7 @@ PropertyModel model = new PropertyModel.Builder(SecurePaymentConfirmationAuthnProperties.ALL_KEYS) - .with(SecurePaymentConfirmationAuthnProperties.STORE_ORIGIN, - mWebContents.getVisibleUrl().getOrigin()) + .with(SecurePaymentConfirmationAuthnProperties.STORE_ORIGIN, payeeOrigin) .with(SecurePaymentConfirmationAuthnProperties.PAYMENT_ICON, paymentIcon) .with(SecurePaymentConfirmationAuthnProperties.PAYMENT_INSTRUMENT_LABEL, paymentInstrumentLabel)
diff --git a/components/payments/content/android/java/src/org/chromium/components/payments/secure_payment_confirmation/SecurePaymentConfirmationAuthnProperties.java b/components/payments/content/android/java/src/org/chromium/components/payments/secure_payment_confirmation/SecurePaymentConfirmationAuthnProperties.java index bff6e9b..65743fb 100644 --- a/components/payments/content/android/java/src/org/chromium/components/payments/secure_payment_confirmation/SecurePaymentConfirmationAuthnProperties.java +++ b/components/payments/content/android/java/src/org/chromium/components/payments/secure_payment_confirmation/SecurePaymentConfirmationAuthnProperties.java
@@ -8,7 +8,7 @@ import org.chromium.ui.modelutil.PropertyKey; import org.chromium.ui.modelutil.PropertyModel.ReadableObjectPropertyKey; -import org.chromium.url.GURL; +import org.chromium.url.Origin; /** * The properties of the SecurePaymentConfirmation Authn UI, which fully describe the state of the @@ -16,7 +16,7 @@ */ /* package */ class SecurePaymentConfirmationAuthnProperties { /** The store value of the UI. */ - /* package */ static final ReadableObjectPropertyKey<GURL> STORE_ORIGIN = + /* package */ static final ReadableObjectPropertyKey<Origin> STORE_ORIGIN = new ReadableObjectPropertyKey<>(); /** The payment icon for the UI. */
diff --git a/components/payments/content/android/java/src/org/chromium/components/payments/secure_payment_confirmation/SecurePaymentConfirmationAuthnViewBinder.java b/components/payments/content/android/java/src/org/chromium/components/payments/secure_payment_confirmation/SecurePaymentConfirmationAuthnViewBinder.java index 1b0cf11..7360990 100644 --- a/components/payments/content/android/java/src/org/chromium/components/payments/secure_payment_confirmation/SecurePaymentConfirmationAuthnViewBinder.java +++ b/components/payments/content/android/java/src/org/chromium/components/payments/secure_payment_confirmation/SecurePaymentConfirmationAuthnViewBinder.java
@@ -17,7 +17,7 @@ /* package */ static void bind( PropertyModel model, SecurePaymentConfirmationAuthnView view, PropertyKey propertyKey) { if (SecurePaymentConfirmationAuthnProperties.STORE_ORIGIN == propertyKey) { - String origin = UrlFormatter.formatUrlForSecurityDisplay( + String origin = UrlFormatter.formatOriginForSecurityDisplay( model.get(SecurePaymentConfirmationAuthnProperties.STORE_ORIGIN), SchemeDisplay.OMIT_HTTP_AND_HTTPS); view.mStoreOrigin.setText(origin);
diff --git a/components/payments/content/android/junit/src/org/chromium/components/payments/PaymentRequestServiceTest.java b/components/payments/content/android/junit/src/org/chromium/components/payments/PaymentRequestServiceTest.java index 128840a..ba52106e 100644 --- a/components/payments/content/android/junit/src/org/chromium/components/payments/PaymentRequestServiceTest.java +++ b/components/payments/content/android/junit/src/org/chromium/components/payments/PaymentRequestServiceTest.java
@@ -712,6 +712,37 @@ PaymentErrorReason.INVALID_DATA_FROM_RENDERER); } + @Test + @Feature({"Payments"}) + public void testSpcCanOnlyBeRequestedAlone_failedForNullPayeeUrl() { + ShadowPaymentFeatureList.setFeatureEnabled( + PaymentFeatureList.SECURE_PAYMENT_CONFIRMATION, true); + Assert.assertNull(defaultBuilder() + .setPayeeOrigin(null) + .setOnlySpcMethodWithoutPaymentOptions() + .build()); + assertErrorAndReason(ErrorStrings.INVALID_PAYMENT_METHODS_OR_DATA, + PaymentErrorReason.INVALID_DATA_FROM_RENDERER); + } + + @Test + @Feature({"Payments"}) + public void testSpcCanOnlyBeRequestedAlone_failedForHttpPayeeUrl() { + ShadowPaymentFeatureList.setFeatureEnabled( + PaymentFeatureList.SECURE_PAYMENT_CONFIRMATION, true); + org.chromium.url.internal.mojom.Origin payeeOrigin = + new org.chromium.url.internal.mojom.Origin(); + payeeOrigin.scheme = "http"; + payeeOrigin.host = "www.example.com"; + payeeOrigin.port = 443; + Assert.assertNull(defaultBuilder() + .setPayeeOrigin(payeeOrigin) + .setOnlySpcMethodWithoutPaymentOptions() + .build()); + assertErrorAndReason(ErrorStrings.INVALID_PAYMENT_METHODS_OR_DATA, + PaymentErrorReason.INVALID_DATA_FROM_RENDERER); + } + // The restriction is imposed only when the SPC flag is enabled. @Test @Feature({"Payments"})
diff --git a/components/payments/content/android/junit/src/org/chromium/components/payments/secure_payment_confirmation/SecurePaymentConfirmationAuthnTest.java b/components/payments/content/android/junit/src/org/chromium/components/payments/secure_payment_confirmation/SecurePaymentConfirmationAuthnTest.java index 4c8b3970..e616eee 100644 --- a/components/payments/content/android/junit/src/org/chromium/components/payments/secure_payment_confirmation/SecurePaymentConfirmationAuthnTest.java +++ b/components/payments/content/android/junit/src/org/chromium/components/payments/secure_payment_confirmation/SecurePaymentConfirmationAuthnTest.java
@@ -39,7 +39,7 @@ import org.chromium.payments.mojom.PaymentCurrencyAmount; import org.chromium.payments.mojom.PaymentItem; import org.chromium.ui.base.WindowAndroid; -import org.chromium.url.GURL; +import org.chromium.url.Origin; import java.lang.ref.WeakReference; @@ -86,7 +86,6 @@ Mockito.doReturn(new WeakReference<Context>(RuntimeEnvironment.application)) .when(windowAndroid) .getContext(); - Mockito.when(mWebContents.getVisibleUrl().getOrigin()).thenReturn(GURL.emptyGURL()); // Create formatter mocks UrlFormatter.Natives urlFormatterJniMock = Mockito.mock(UrlFormatter.Natives.class); @@ -141,7 +140,10 @@ mIsPaymentConfirmed = false; mIsPaymentCancelled = false; - return mAuthnController.show(mDrawable, "paymentInstrumentLabel", mTotal, mCallback); + org.chromium.url.internal.mojom.Origin mojoOrigin = + new org.chromium.url.internal.mojom.Origin(); + return mAuthnController.show( + mDrawable, "paymentInstrumentLabel", mTotal, mCallback, new Origin(mojoOrigin)); } private void setWindowAndroid(WindowAndroid windowAndroid, WebContents webContents) {
diff --git a/components/payments/content/android/junit/src/org/chromium/components/payments/test_support/PaymentRequestServiceBuilder.java b/components/payments/content/android/junit/src/org/chromium/components/payments/test_support/PaymentRequestServiceBuilder.java index 8e7ef8b..c0b0491 100644 --- a/components/payments/content/android/junit/src/org/chromium/components/payments/test_support/PaymentRequestServiceBuilder.java +++ b/components/payments/content/android/junit/src/org/chromium/components/payments/test_support/PaymentRequestServiceBuilder.java
@@ -23,6 +23,7 @@ import org.chromium.payments.mojom.PaymentMethodData; import org.chromium.payments.mojom.PaymentOptions; import org.chromium.payments.mojom.PaymentRequestClient; +import org.chromium.payments.mojom.SecurePaymentConfirmationRequest; import org.chromium.url.GURL; import org.chromium.url.JUnitTestGURLs; import org.chromium.url.Origin; @@ -53,6 +54,7 @@ private boolean mIsOriginAllowedToUseWebPaymentApis = true; private boolean mIsPaymentDetailsValid = true; private PaymentRequestSpec mSpec; + private SecurePaymentConfirmationRequest mSecurePaymentConfirmationRequest; public static PaymentRequestServiceBuilder defaultBuilder(Runnable onClosedListener, PaymentRequestClient client, PaymentAppService appService, @@ -92,6 +94,13 @@ mOnClosedListener = onClosedListener; mClient = client; mPaymentAppService = appService; + mSecurePaymentConfirmationRequest = new SecurePaymentConfirmationRequest(); + org.chromium.url.internal.mojom.Origin payeeOrigin = + new org.chromium.url.internal.mojom.Origin(); + payeeOrigin.scheme = "https"; + payeeOrigin.host = "chromium.org"; + payeeOrigin.port = 443; + mSecurePaymentConfirmationRequest.payeeOrigin = payeeOrigin; } @Override @@ -224,10 +233,18 @@ } public PaymentRequestServiceBuilder setOnlySpcMethodWithoutPaymentOptions() { + mOptions = new PaymentOptions(); mMethodData = new PaymentMethodData[1]; mMethodData[0] = new PaymentMethodData(); mMethodData[0].supportedMethod = MethodStrings.SECURE_PAYMENT_CONFIRMATION; - mOptions = new PaymentOptions(); + + mMethodData[0].securePaymentConfirmation = mSecurePaymentConfirmationRequest; + return this; + } + + public PaymentRequestServiceBuilder setPayeeOrigin( + org.chromium.url.internal.mojom.Origin payeeOrigin) { + mSecurePaymentConfirmationRequest.payeeOrigin = payeeOrigin; return this; }
diff --git a/components/prefs/in_memory_pref_store.cc b/components/prefs/in_memory_pref_store.cc index 1f9b76f3..662e7a1 100644 --- a/components/prefs/in_memory_pref_store.cc +++ b/components/prefs/in_memory_pref_store.cc
@@ -7,7 +7,6 @@ #include <memory> #include <utility> -#include "base/notreached.h" #include "base/values.h" InMemoryPrefStore::InMemoryPrefStore() {} @@ -81,12 +80,6 @@ return PersistentPrefStore::PREF_READ_ERROR_NONE; } -void InMemoryPrefStore::CommitPendingWriteSynchronously() { - // This function was added for one very specific use case and is intentionally - // not implemented for other pref stores. - NOTREACHED(); -} - void InMemoryPrefStore::ReportValueChanged(const std::string& key, uint32_t flags) { for (Observer& observer : observers_)
diff --git a/components/prefs/in_memory_pref_store.h b/components/prefs/in_memory_pref_store.h index 682b602..6f8bc490 100644 --- a/components/prefs/in_memory_pref_store.h +++ b/components/prefs/in_memory_pref_store.h
@@ -49,7 +49,6 @@ PrefReadError GetReadError() const override; PersistentPrefStore::PrefReadError ReadPrefs() override; void ReadPrefsAsync(ReadErrorDelegate* error_delegate) override {} - void CommitPendingWriteSynchronously() override; void SchedulePendingLossyWrites() override {} void ClearMutableValues() override {} void OnStoreDeletionFromDisk() override {}
diff --git a/components/prefs/json_pref_store.cc b/components/prefs/json_pref_store.cc index 6ba38dd..e7afbd2 100644 --- a/components/prefs/json_pref_store.cc +++ b/components/prefs/json_pref_store.cc
@@ -321,28 +321,6 @@ } } -void JsonPrefStore::CommitPendingWriteSynchronously() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - - // Schedule a write for any lossy writes that are outstanding to ensure that - // they get flushed when this function is called. - SchedulePendingLossyWrites(); - if (!writer_.HasPendingWrite() || read_only_) - return; - - const base::FilePath path = writer_.path(); - std::string data; - if (!SerializeData(&data)) { - DVLOG(1) << "Failed to serialize data to be saved in " << path.value(); - return; - } - - const std::string suffix = GetHistogramSuffix(path); - if (!base::ImportantFileWriter::WriteFileAtomically(path, data, suffix)) { - DVLOG(1) << "Could not write " << suffix << " into " << path.value(); - } -} - void JsonPrefStore::SchedulePendingLossyWrites() { if (pending_lossy_write_) writer_.ScheduleWrite(this);
diff --git a/components/prefs/json_pref_store.h b/components/prefs/json_pref_store.h index 749171e..23cec50a 100644 --- a/components/prefs/json_pref_store.h +++ b/components/prefs/json_pref_store.h
@@ -104,7 +104,6 @@ base::OnceClosure reply_callback = base::OnceClosure(), base::OnceClosure synchronous_done_callback = base::OnceClosure()) override; - void CommitPendingWriteSynchronously() override; void SchedulePendingLossyWrites() override; void ReportValueChanged(const std::string& key, uint32_t flags) override;
diff --git a/components/prefs/json_pref_store_unittest.cc b/components/prefs/json_pref_store_unittest.cc index ccc1e6d..bad903ab 100644 --- a/components/prefs/json_pref_store_unittest.cc +++ b/components/prefs/json_pref_store_unittest.cc
@@ -24,12 +24,10 @@ #include "base/strings/utf_string_conversions.h" #include "base/synchronization/waitable_event.h" #include "base/task/single_thread_task_runner_forward.h" -#include "base/test/gtest_util.h" #include "base/test/metrics/histogram_tester.h" #include "base/test/task_environment.h" #include "base/threading/sequenced_task_runner_handle.h" #include "base/threading/thread.h" -#include "base/threading/thread_restrictions.h" #include "base/values.h" #include "components/prefs/persistent_pref_store_unittest.h" #include "components/prefs/pref_filter.h" @@ -575,65 +573,6 @@ JsonPrefStoreTest, ::testing::Values(CommitPendingWriteMode::WITH_SYNCHRONOUS_CALLBACK)); -class JsonPrefStoreWriteSynchronouslyTest : public testing::Test { - public: - JsonPrefStoreWriteSynchronouslyTest() = default; - ~JsonPrefStoreWriteSynchronouslyTest() override = default; - - protected: - void SetUp() override { ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); } - - base::test::TaskEnvironment task_environment_; - base::ScopedTempDir temp_dir_; -}; - -TEST_F(JsonPrefStoreWriteSynchronouslyTest, - WriteFailsWhenBlockingIsDisallowed) { - const char kEmptyPrefContents[] = "{}"; - - base::FilePath pref_file = temp_dir_.GetPath().AppendASCII("write.json"); - ASSERT_LT(0, base::WriteFile(pref_file, kEmptyPrefContents, - base::size(kEmptyPrefContents) - 1)); - - auto pref_store = base::MakeRefCounted<JsonPrefStore>(pref_file); - ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE, pref_store->ReadPrefs()); - - const std::string test_pref = "test"; - pref_store->SetValue(test_pref, std::make_unique<Value>(3), - WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS); - { - base::ScopedDisallowBlocking scoped_disallow_blocking; - EXPECT_DCHECK_DEATH(pref_store->CommitPendingWriteSynchronously()); - } -} - -TEST_F(JsonPrefStoreWriteSynchronouslyTest, CommitPendingWriteSynchronously) { - const char kInputPrefContents[] = - "{\n" - " \"homepage\": \"http://www.cnn.com\"\n" - "}"; - - const std::string kExpectedPrefContents = - "{\"homepage\":\"http://www.cnn.com\",\"test\":3}"; - - base::FilePath pref_file = temp_dir_.GetPath().AppendASCII("write.json"); - ASSERT_LT(0, base::WriteFile(pref_file, kInputPrefContents, - base::size(kInputPrefContents) - 1)); - - auto pref_store = base::MakeRefCounted<JsonPrefStore>(pref_file); - ASSERT_EQ(PersistentPrefStore::PREF_READ_ERROR_NONE, pref_store->ReadPrefs()); - - const std::string test_pref = "test"; - pref_store->SetValue(test_pref, std::make_unique<Value>(3), - WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS); - pref_store->CommitPendingWriteSynchronously(); - - std::string pref_file_contents; - ASSERT_TRUE(base::ReadFileToString(pref_file, &pref_file_contents)); - EXPECT_EQ(kExpectedPrefContents, pref_file_contents); - ASSERT_TRUE(base::DeleteFile(pref_file)); -} - class JsonPrefStoreLossyWriteTest : public JsonPrefStoreTest { public: JsonPrefStoreLossyWriteTest() = default;
diff --git a/components/prefs/overlay_user_pref_store.cc b/components/prefs/overlay_user_pref_store.cc index a8b27a3..7861736 100644 --- a/components/prefs/overlay_user_pref_store.cc +++ b/components/prefs/overlay_user_pref_store.cc
@@ -9,7 +9,6 @@ #include <utility> #include "base/memory/ptr_util.h" -#include "base/notreached.h" #include "base/values.h" #include "components/prefs/in_memory_pref_store.h" @@ -194,12 +193,6 @@ // We do not write our content intentionally. } -void OverlayUserPrefStore::CommitPendingWriteSynchronously() { - // This function was added for one very specific use case and is intentionally - // not implemented for other pref stores. - NOTREACHED(); -} - void OverlayUserPrefStore::SchedulePendingLossyWrites() { persistent_user_pref_store_->SchedulePendingLossyWrites(); }
diff --git a/components/prefs/overlay_user_pref_store.h b/components/prefs/overlay_user_pref_store.h index 2da006c2..90cddab 100644 --- a/components/prefs/overlay_user_pref_store.h +++ b/components/prefs/overlay_user_pref_store.h
@@ -63,7 +63,6 @@ void ReadPrefsAsync(ReadErrorDelegate* delegate) override; void CommitPendingWrite(base::OnceClosure reply_callback, base::OnceClosure synchronous_done_callback) override; - void CommitPendingWriteSynchronously() override; void SchedulePendingLossyWrites() override; void ReportValueChanged(const std::string& key, uint32_t flags) override;
diff --git a/components/prefs/persistent_pref_store.h b/components/prefs/persistent_pref_store.h index 2b1f80b0..df395051 100644 --- a/components/prefs/persistent_pref_store.h +++ b/components/prefs/persistent_pref_store.h
@@ -71,12 +71,6 @@ base::OnceClosure reply_callback = base::OnceClosure(), base::OnceClosure synchronous_done_callback = base::OnceClosure()); - // Like CommitPendingWrite(), but writes to disk on this thread synchronously - // rather than scheduling a write. CommitPendingWriteSynchronously() is - // appropriate to call only in the exceptional situation in which you need to - // write to disk early on during startup before threads have been started. - virtual void CommitPendingWriteSynchronously() = 0; - // Schedules a write if there is any lossy data pending. Unlike // CommitPendingWrite() this does not immediately sync to disk, instead it // triggers an eventual write if there is lossy data pending and if there
diff --git a/components/prefs/pref_service.cc b/components/prefs/pref_service.cc index b2cf2462..e6e45d5 100644 --- a/components/prefs/pref_service.cc +++ b/components/prefs/pref_service.cc
@@ -712,8 +712,3 @@ DCHECK(value) << "Trying to read an unregistered pref: " << path; return value; } - -void PrefService::CommitPendingWriteSynchronously() { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - user_pref_store_->CommitPendingWriteSynchronously(); -}
diff --git a/components/prefs/pref_service.h b/components/prefs/pref_service.h index e0eac20..2c362d0c 100644 --- a/components/prefs/pref_service.h +++ b/components/prefs/pref_service.h
@@ -469,12 +469,6 @@ const base::Value* GetPreferenceValue(const std::string& path) const; const base::Value* GetPreferenceValueChecked(const std::string& path) const; - // Like CommitPendingWrite(), but writes to disk on this thread synchronously - // rather than scheduling a write. CommitPendingWriteSynchronously() is - // appropriate to call only in the exceptional situation in which you need to - // write to disk early on during startup before threads have been started. - void CommitPendingWriteSynchronously(); - const scoped_refptr<PrefRegistry> pref_registry_; // Local cache of registered Preference objects. The pref_registry_
diff --git a/components/prefs/segregated_pref_store.cc b/components/prefs/segregated_pref_store.cc index 6686ef1..1f3ccc52 100644 --- a/components/prefs/segregated_pref_store.cc +++ b/components/prefs/segregated_pref_store.cc
@@ -195,12 +195,6 @@ synchronous_callback_wrapper); } -void SegregatedPrefStore::CommitPendingWriteSynchronously() { - // This function was added for one very specific use case and is intentionally - // not implemented for other pref stores. - NOTREACHED(); -} - void SegregatedPrefStore::SchedulePendingLossyWrites() { default_pref_store_->SchedulePendingLossyWrites(); selected_pref_store_->SchedulePendingLossyWrites();
diff --git a/components/prefs/segregated_pref_store.h b/components/prefs/segregated_pref_store.h index 8b820d0..cfe90ee7 100644 --- a/components/prefs/segregated_pref_store.h +++ b/components/prefs/segregated_pref_store.h
@@ -76,7 +76,6 @@ base::OnceClosure reply_callback = base::OnceClosure(), base::OnceClosure synchronous_done_callback = base::OnceClosure()) override; - void CommitPendingWriteSynchronously() override; void SchedulePendingLossyWrites() override; void ClearMutableValues() override; void OnStoreDeletionFromDisk() override;
diff --git a/components/prefs/testing_pref_store.cc b/components/prefs/testing_pref_store.cc index ce0bd44..5d3d1ec 100644 --- a/components/prefs/testing_pref_store.cc +++ b/components/prefs/testing_pref_store.cc
@@ -111,12 +111,6 @@ std::move(synchronous_done_callback)); } -void TestingPrefStore::CommitPendingWriteSynchronously() { - // This function was added for one very specific use case and is intentionally - // not implemented for other pref stores. - NOTREACHED(); -} - void TestingPrefStore::SchedulePendingLossyWrites() {} void TestingPrefStore::SetInitializationCompleted() {
diff --git a/components/prefs/testing_pref_store.h b/components/prefs/testing_pref_store.h index cc23eedb..5a4348e 100644 --- a/components/prefs/testing_pref_store.h +++ b/components/prefs/testing_pref_store.h
@@ -51,7 +51,6 @@ void ReadPrefsAsync(ReadErrorDelegate* error_delegate) override; void CommitPendingWrite(base::OnceClosure reply_callback, base::OnceClosure synchronous_done_callback) override; - void CommitPendingWriteSynchronously() override; void SchedulePendingLossyWrites() override; // Marks the store as having completed initialization.
diff --git a/components/safe_browsing/content/browser/password_protection/mock_password_protection_service.h b/components/safe_browsing/content/browser/password_protection/mock_password_protection_service.h index aac6fae..4acad7a 100644 --- a/components/safe_browsing/content/browser/password_protection/mock_password_protection_service.h +++ b/components/safe_browsing/content/browser/password_protection/mock_password_protection_service.h
@@ -119,6 +119,8 @@ PasswordType, const std::vector<password_manager::MatchingReusedCredential>&, bool)); + MOCK_CONST_METHOD0(GetUserPopulationPref, + ChromeUserPopulation::UserPopulation()); }; } // namespace safe_browsing
diff --git a/components/safe_browsing/content/browser/user_population.cc b/components/safe_browsing/content/browser/user_population.cc index 2d6b3f13..5dafc13 100644 --- a/components/safe_browsing/content/browser/user_population.cc +++ b/components/safe_browsing/content/browser/user_population.cc
@@ -14,6 +14,20 @@ namespace safe_browsing { +ChromeUserPopulation::UserPopulation GetUserPopulationPref(PrefService* prefs) { + if (prefs) { + if (IsEnhancedProtectionEnabled(*prefs)) { + return ChromeUserPopulation::ENHANCED_PROTECTION; + } else if (IsExtendedReportingEnabled(*prefs)) { + return ChromeUserPopulation::EXTENDED_REPORTING; + } else if (IsSafeBrowsingEnabled(*prefs)) { + return ChromeUserPopulation::SAFE_BROWSING; + } + } + + return ChromeUserPopulation::UNKNOWN_USER_POPULATION; +} + ChromeUserPopulation GetUserPopulation( PrefService* prefs, bool is_incognito, @@ -25,15 +39,9 @@ absl::optional<size_t> num_open_profiles) { ChromeUserPopulation population; - if (prefs) { - if (IsEnhancedProtectionEnabled(*prefs)) { - population.set_user_population(ChromeUserPopulation::ENHANCED_PROTECTION); - } else if (IsExtendedReportingEnabled(*prefs)) { - population.set_user_population(ChromeUserPopulation::EXTENDED_REPORTING); - } else if (IsSafeBrowsingEnabled(*prefs)) { - population.set_user_population(ChromeUserPopulation::SAFE_BROWSING); - } + population.set_user_population(GetUserPopulationPref(prefs)); + if (prefs) { population.set_is_mbb_enabled(prefs->GetBoolean( unified_consent::prefs::kUrlKeyedAnonymizedDataCollectionEnabled)); }
diff --git a/components/safe_browsing/content/browser/user_population.h b/components/safe_browsing/content/browser/user_population.h index 62f4a0ea..21c56e42 100644 --- a/components/safe_browsing/content/browser/user_population.h +++ b/components/safe_browsing/content/browser/user_population.h
@@ -16,6 +16,9 @@ namespace safe_browsing { +// Returns the UserPopulation enum for the given prefs +ChromeUserPopulation::UserPopulation GetUserPopulationPref(PrefService* prefs); + // Creates a ChromeUserPopulation proto for the given state. ChromeUserPopulation GetUserPopulation( // The below may be null.
diff --git a/components/safe_browsing/core/browser/password_protection/password_protection_request.cc b/components/safe_browsing/core/browser/password_protection/password_protection_request.cc index ba7e761..f78790b 100644 --- a/components/safe_browsing/core/browser/password_protection/password_protection_request.cc +++ b/components/safe_browsing/core/browser/password_protection/password_protection_request.cc
@@ -7,6 +7,7 @@ #include <cstddef> #include "base/bind.h" +#include "base/metrics/histogram_functions.h" #include "base/strings/strcat.h" #include "base/strings/utf_string_conversions.h" #include "components/safe_browsing/core/browser/db/allowlist_checker_client.h" @@ -109,6 +110,17 @@ void PasswordProtectionRequest::Start() { DCHECK(ui_task_runner()->RunsTasksInCurrentSequence()); + if (trigger_type_ == LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE) { + base::UmaHistogramExactLinear( + "PasswordProtection.OnFocus.UserPopulationStart", + password_protection_service_->GetUserPopulationPref(), + ChromeUserPopulation::UserPopulation_MAX + 1); + } else { + base::UmaHistogramExactLinear( + "PasswordProtection.PasswordEntry.UserPopulationStart", + password_protection_service_->GetUserPopulationPref(), + ChromeUserPopulation::UserPopulation_MAX + 1); + } CheckAllowlist(); } @@ -321,6 +333,19 @@ void PasswordProtectionRequest::SendRequest() { DCHECK(ui_task_runner()->RunsTasksInCurrentSequence()); + + if (trigger_type_ == LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE) { + base::UmaHistogramExactLinear( + "PasswordProtection.OnFocus.UserPopulationOnPing", + password_protection_service_->GetUserPopulationPref(), + ChromeUserPopulation::UserPopulation_MAX + 1); + } else { + base::UmaHistogramExactLinear( + "PasswordProtection.PasswordEntry.UserPopulationOnPing", + password_protection_service_->GetUserPopulationPref(), + ChromeUserPopulation::UserPopulation_MAX + 1); + } + if (password_protection_service_->CanGetAccessToken() && password_protection_service_->token_fetcher()) { password_protection_service_->token_fetcher()->Start(
diff --git a/components/safe_browsing/core/browser/password_protection/password_protection_service_base.h b/components/safe_browsing/core/browser/password_protection/password_protection_service_base.h index 3026347..d201c3ce 100644 --- a/components/safe_browsing/core/browser/password_protection/password_protection_service_base.h +++ b/components/safe_browsing/core/browser/password_protection/password_protection_service_base.h
@@ -245,6 +245,10 @@ // Returns the URL where PasswordProtectionRequest instances send requests. static GURL GetPasswordProtectionRequestUrl(); + // Gets the UserPopulation value for this profile. + virtual ChromeUserPopulation::UserPopulation GetUserPopulationPref() + const = 0; + protected: friend class PasswordProtectionRequest; friend class PasswordProtectionRequestContent;
diff --git a/components/send_tab_to_self/send_tab_to_self_bridge.cc b/components/send_tab_to_self/send_tab_to_self_bridge.cc index 5ed63fb..f6e17045 100644 --- a/components/send_tab_to_self/send_tab_to_self_bridge.cc +++ b/components/send_tab_to_self/send_tab_to_self_bridge.cc
@@ -9,6 +9,7 @@ #include "base/bind.h" #include "base/callback_helpers.h" #include "base/check_op.h" +#include "base/containers/cxx20_erase_vector.h" #include "base/guid.h" #include "base/memory/ptr_util.h" #include "base/strings/string_util.h" @@ -24,7 +25,6 @@ #include "components/sync/model/model_type_change_processor.h" #include "components/sync/model/mutable_data_batch.h" #include "components/sync/protocol/model_type_state.pb.h" -#include "components/sync_device_info/device_info_tracker.h" #include "components/sync_device_info/local_device_info_util.h" #include "third_party/abseil-cpp/absl/types/optional.h" @@ -99,6 +99,9 @@ if (history_service) { history_service_observation_.Observe(history_service); } + device_info_tracker_observation_.Observe(device_info_tracker); + + ComputeTargetDeviceInfoSortedList(); std::move(create_store_callback) .Run(syncer::SEND_TAB_TO_SELF, @@ -433,23 +436,33 @@ DeleteAllEntries(); } +void SendTabToSelfBridge::OnDeviceInfoChange() { + ComputeTargetDeviceInfoSortedList(); +} + bool SendTabToSelfBridge::IsReady() { return change_processor()->IsTrackingMetadata(); } bool SendTabToSelfBridge::HasValidTargetDevice() { - if (ShouldUpdateTargetDeviceInfoList()) { - SetTargetDeviceInfoList(); - } - return target_device_name_to_cache_info_.size() > 0; + return GetTargetDeviceInfoSortedList().size() > 0; } std::vector<TargetDeviceInfo> SendTabToSelfBridge::GetTargetDeviceInfoSortedList() { - if (ShouldUpdateTargetDeviceInfoList()) { - SetTargetDeviceInfoList(); - } - return target_device_name_to_cache_info_; + // Filter expired devices (some timestamps in the cached list may now be too + // old). |target_device_info_sorted_list_| is copied here to avoid mutations + // inside a getter. + // TODO(crbug.com/1257573): Consider having a timer that fires on the next + // expiry and removes the corresponding device(s) then. + std::vector<TargetDeviceInfo> non_expired_devices = + target_device_info_sorted_list_; + const base::Time now = clock_->Now(); + base::EraseIf(non_expired_devices, [now](const TargetDeviceInfo& device) { + return now - device.last_updated_timestamp > kDeviceExpiration; + }); + + return non_expired_devices; } // static @@ -459,10 +472,6 @@ return std::move(bridge->store_); } -bool SendTabToSelfBridge::ShouldUpdateTargetDeviceInfoListForTest() { - return ShouldUpdateTargetDeviceInfoList(); -} - void SendTabToSelfBridge::SetLocalDeviceNameForTest( const std::string& local_device_name) { local_device_name_ = local_device_name; @@ -618,28 +627,13 @@ NotifyRemoteSendTabToSelfEntryDeleted(removed); } -bool SendTabToSelfBridge::ShouldUpdateTargetDeviceInfoList() const { +void SendTabToSelfBridge::ComputeTargetDeviceInfoSortedList() { if (!device_info_tracker_->IsSyncing()) { - return false; + return; } - // The vector should be updated if any of these is true: - // * The vector is empty. - // * The number of total devices changed. - // * The oldest non-expired entry in the vector is now expired. - return target_device_name_to_cache_info_.empty() || - device_info_tracker_->GetAllDeviceInfo().size() != - number_of_devices_ || - clock_->Now() - oldest_non_expired_device_timestamp_ > - kDeviceExpiration; -} - -void SendTabToSelfBridge::SetTargetDeviceInfoList() { - DCHECK(device_info_tracker_->IsSyncing()); - std::vector<std::unique_ptr<syncer::DeviceInfo>> all_devices = device_info_tracker_->GetAllDeviceInfo(); - number_of_devices_ = all_devices.size(); // Sort the DeviceInfo vector so the most recently modified devices are first. std::stable_sort(all_devices.begin(), all_devices.end(), @@ -649,7 +643,7 @@ device2->last_updated_timestamp(); }); - target_device_name_to_cache_info_.clear(); + target_device_info_sorted_list_.clear(); std::set<std::string> unique_device_names; std::unordered_map<std::string, int> short_names_counter; for (const auto& device : all_devices) { @@ -686,13 +680,12 @@ TargetDeviceInfo target_device_info( device_names.full_name, device_names.short_name, device->guid(), device->device_type(), device->last_updated_timestamp()); - target_device_name_to_cache_info_.push_back(target_device_info); - oldest_non_expired_device_timestamp_ = device->last_updated_timestamp(); + target_device_info_sorted_list_.push_back(target_device_info); short_names_counter[device_names.short_name]++; } } - for (auto& device_info : target_device_name_to_cache_info_) { + for (auto& device_info : target_device_info_sorted_list_) { bool unique_short_name = short_names_counter[device_info.short_name] == 1; device_info.device_name = (unique_short_name ? device_info.short_name : device_info.full_name);
diff --git a/components/send_tab_to_self/send_tab_to_self_bridge.h b/components/send_tab_to_self/send_tab_to_self_bridge.h index 648c797e..67bb1ab 100644 --- a/components/send_tab_to_self/send_tab_to_self_bridge.h +++ b/components/send_tab_to_self/send_tab_to_self_bridge.h
@@ -20,9 +20,9 @@ #include "components/sync/base/model_type.h" #include "components/sync/model/model_type_store.h" #include "components/sync/model/model_type_sync_bridge.h" +#include "components/sync_device_info/device_info_tracker.h" namespace syncer { -class DeviceInfoTracker; class ModelTypeChangeProcessor; } // namespace syncer @@ -38,6 +38,7 @@ // All interface methods have to be called on main thread. class SendTabToSelfBridge : public syncer::ModelTypeSyncBridge, public SendTabToSelfModel, + public syncer::DeviceInfoTracker::Observer, public history::HistoryServiceObserver { public: // The caller should ensure that all raw pointers are not null and will @@ -91,10 +92,12 @@ void OnURLsDeleted(history::HistoryService* history_service, const history::DeletionInfo& deletion_info) override; + // syncer::DeviceInfoTracker::Observer overrides. + void OnDeviceInfoChange() override; + // For testing only. static std::unique_ptr<syncer::ModelTypeStore> DestroyAndStealStoreForTest( std::unique_ptr<SendTabToSelfBridge> bridge); - bool ShouldUpdateTargetDeviceInfoListForTest(); void SetLocalDeviceNameForTest(const std::string& local_device_name); private: @@ -139,11 +142,7 @@ // Delete expired entries. void DoGarbageCollection(); - // Returns whether the target device info list should be updated. - bool ShouldUpdateTargetDeviceInfoList() const; - - // Sets the target device info list. - void SetTargetDeviceInfoList(); + void ComputeTargetDeviceInfoSortedList(); // Remove entry with |guid| from entries, but doesn't call Commit on provided // |batch|. This allows multiple for deletions without duplicate batch calls. @@ -174,16 +173,14 @@ // A pointer to the most recently used entry used for deduplication. const SendTabToSelfEntry* mru_entry_; - // A list of target devices and their associated cache information. - std::vector<TargetDeviceInfo> target_device_name_to_cache_info_; - - // The following two variables are used to determine whether we should update - // the target device name to cache guid map. - base::Time oldest_non_expired_device_timestamp_; - size_t number_of_devices_ = 0; + // The list of target devices, deduplicated and sorted by most recently used. + std::vector<TargetDeviceInfo> target_device_info_sorted_list_; base::ScopedObservation<history::HistoryService, HistoryServiceObserver> history_service_observation_{this}; + base::ScopedObservation<syncer::DeviceInfoTracker, + syncer::DeviceInfoTracker::Observer> + device_info_tracker_observation_{this}; base::WeakPtrFactory<SendTabToSelfBridge> weak_ptr_factory_{this}; };
diff --git a/components/send_tab_to_self/send_tab_to_self_bridge_unittest.cc b/components/send_tab_to_self/send_tab_to_self_bridge_unittest.cc index 5e5252ad..f75ffe44 100644 --- a/components/send_tab_to_self/send_tab_to_self_bridge_unittest.cc +++ b/components/send_tab_to_self/send_tab_to_self_bridge_unittest.cc
@@ -812,14 +812,14 @@ recent_device->guid(), recent_device->device_type(), recent_device->last_updated_timestamp()); - // Set the map by calling it. Make sure it has the 2 devices. + // Make sure the list has the 2 devices. EXPECT_THAT(bridge()->GetTargetDeviceInfoSortedList(), ElementsAre(recent_device_info, older_device_info)); // Advance the time so that the older device expires. clock()->Advance(base::Days(5)); - // Make sure only the recent device is in the map. + // Make sure only the recent device is in the list. EXPECT_THAT(bridge()->GetTargetDeviceInfoSortedList(), ElementsAre(recent_device_info)); } @@ -834,7 +834,7 @@ CreateDevice("guid", "name", clock()->Now()); AddTestDevice(device.get()); - // Set the map by calling it. Make sure it has the device. + // Make sure the list has the device. TargetDeviceInfo device_info(device->client_name(), device->client_name(), device->guid(), device->device_type(), device->last_updated_timestamp()); @@ -847,7 +847,7 @@ CreateDevice("new_guid", "new_name", clock()->Now()); AddTestDevice(new_device.get()); - // Make sure both devices are in the map. + // Make sure both devices are in the list. TargetDeviceInfo new_device_info( new_device->client_name(), new_device->client_name(), new_device->guid(), new_device->device_type(), new_device->last_updated_timestamp()); @@ -856,6 +856,48 @@ ElementsAre(device_info, new_device_info)); } +// Tests the device list is updated if the last_updated_timestamp of one of +// them changes. Regression test for crbug.com/1257573. +TEST_F(SendTabToSelfBridgeTest, + GetTargetDeviceInfoSortedList_Updated_LastUpdatedTimestampChanged) { + InitializeBridge(); + + std::unique_ptr<syncer::DeviceInfo> device1 = + CreateDevice("guid1", "name1", clock()->Now() - base::Days(1)); + AddTestDevice(device1.get()); + std::unique_ptr<syncer::DeviceInfo> device2_old = + CreateDevice("guid2", "name2", clock()->Now() - base::Days(2)); + AddTestDevice(device2_old.get()); + + EXPECT_THAT( + bridge()->GetTargetDeviceInfoSortedList(), + ElementsAre( + TargetDeviceInfo(device1->client_name(), device1->client_name(), + device1->guid(), device1->device_type(), + device1->last_updated_timestamp()), + TargetDeviceInfo(device2_old->client_name(), + device2_old->client_name(), device2_old->guid(), + device2_old->device_type(), + device2_old->last_updated_timestamp()))); + + // Simulate device 2 being used today. + std::unique_ptr<syncer::DeviceInfo> device2_new = CreateDevice( + device2_old->guid(), device2_old->client_name(), clock()->Now()); + device_info_tracker()->Replace(device2_old.get(), device2_new.get()); + + // Device 2 is now the most recently used and should be the first on the list. + EXPECT_THAT( + bridge()->GetTargetDeviceInfoSortedList(), + ElementsAre( + TargetDeviceInfo(device2_new->client_name(), + device2_new->client_name(), device2_new->guid(), + device2_new->device_type(), + device2_new->last_updated_timestamp()), + TargetDeviceInfo(device1->client_name(), device1->client_name(), + device1->guid(), device1->device_type(), + device1->last_updated_timestamp()))); +} + TEST_F(SendTabToSelfBridgeTest, NotifyRemoteSendTabToSelfEntryOpened) { InitializeBridge(); SetLocalDeviceCacheGuid("Device1"); @@ -891,14 +933,13 @@ } TEST_F(SendTabToSelfBridgeTest, - ShouldNotUpdateTargetDeviceInfoListWhileEmptyDeviceInfo) { + ShouldHaveEmptyTargetDeviceInfoListWhileEmptyDeviceInfo) { InitializeBridgeWithoutDevice(); SetLocalDeviceCacheGuid("cache_guid"); ASSERT_FALSE(bridge()->change_processor()->TrackedCacheGuid().empty()); ASSERT_FALSE(device_info_tracker()->IsSyncing()); - EXPECT_FALSE(bridge()->ShouldUpdateTargetDeviceInfoListForTest()); EXPECT_FALSE(bridge()->HasValidTargetDevice()); }
diff --git a/components/signin/internal/identity_manager/primary_account_mutator_impl.cc b/components/signin/internal/identity_manager/primary_account_mutator_impl.cc index 11460ad..25bcd85 100644 --- a/components/signin/internal/identity_manager/primary_account_mutator_impl.cc +++ b/components/signin/internal/identity_manager/primary_account_mutator_impl.cc
@@ -45,13 +45,13 @@ PrimaryAccountMutatorImpl::~PrimaryAccountMutatorImpl() {} -bool PrimaryAccountMutatorImpl::SetPrimaryAccount( - const CoreAccountId& account_id, - ConsentLevel consent_level) { +PrimaryAccountMutator::PrimaryAccountError +PrimaryAccountMutatorImpl::SetPrimaryAccount(const CoreAccountId& account_id, + ConsentLevel consent_level) { DCHECK(!account_id.empty()); AccountInfo account_info = account_tracker_->GetAccountInfo(account_id); if (account_info.IsEmpty()) - return false; + return PrimaryAccountError::kAccountInfoEmpty; DCHECK_EQ(account_info.account_id, account_id); DCHECK(!account_info.email.empty()); @@ -66,17 +66,17 @@ DCHECK(is_signin_allowed); #endif if (!is_signin_allowed) - return false; + return PrimaryAccountError::kSigninNotAllowed; #endif switch (consent_level) { case ConsentLevel::kSync: #if !BUILDFLAG(IS_CHROMEOS_ASH) if (primary_account_manager_->HasPrimaryAccount(ConsentLevel::kSync)) - return false; + return PrimaryAccountError::kSyncConsentAlreadySet; #endif primary_account_manager_->SetSyncPrimaryAccountInfo(account_info); - return true; + return PrimaryAccountError::kNoError; case ConsentLevel::kSignin: #if BUILDFLAG(IS_CHROMEOS_ASH) // On Chrome OS the UPA can only be set once and never removed or changed. @@ -85,9 +85,10 @@ #endif DCHECK(!primary_account_manager_->HasPrimaryAccount(ConsentLevel::kSync)); primary_account_manager_->SetUnconsentedPrimaryAccountInfo(account_info); - return true; + return PrimaryAccountError::kNoError; } - return false; + CHECK(false) << "Unknown consent level: " << static_cast<int>(consent_level); + return PrimaryAccountError::kNoError; } #if !BUILDFLAG(IS_CHROMEOS_ASH)
diff --git a/components/signin/internal/identity_manager/primary_account_mutator_impl.h b/components/signin/internal/identity_manager/primary_account_mutator_impl.h index 0fe8259..c29a46d 100644 --- a/components/signin/internal/identity_manager/primary_account_mutator_impl.h +++ b/components/signin/internal/identity_manager/primary_account_mutator_impl.h
@@ -29,8 +29,8 @@ ~PrimaryAccountMutatorImpl() override; // PrimaryAccountMutator implementation. - bool SetPrimaryAccount(const CoreAccountId& account_id, - ConsentLevel consent_level) override; + PrimaryAccountError SetPrimaryAccount(const CoreAccountId& account_id, + ConsentLevel consent_level) override; void RevokeSyncConsent(signin_metrics::ProfileSignout source_metric, signin_metrics::SignoutDelete delete_metric) override; #if !BUILDFLAG(IS_CHROMEOS_ASH)
diff --git a/components/signin/public/identity_manager/identity_manager.cc b/components/signin/public/identity_manager/identity_manager.cc index 594d563..0339ff1 100644 --- a/components/signin/public/identity_manager/identity_manager.cc +++ b/components/signin/public/identity_manager/identity_manager.cc
@@ -76,8 +76,11 @@ signin_metrics::ACCOUNT_REMOVED_FROM_DEVICE, signin_metrics::SignoutDelete::kIgnoreMetric); } - CHECK(identity_manager->GetPrimaryAccountMutator()->SetPrimaryAccount( - device_account_id, ConsentLevel::kSync)); + PrimaryAccountMutator::PrimaryAccountError error = + identity_manager->GetPrimaryAccountMutator()->SetPrimaryAccount( + device_account_id, ConsentLevel::kSync); + CHECK_EQ(PrimaryAccountMutator::PrimaryAccountError::kNoError, error) + << "SetPrimaryAccount error: " << static_cast<int>(error); CHECK(identity_manager->HasPrimaryAccount(ConsentLevel::kSync)); CHECK_EQ(identity_manager->GetPrimaryAccountInfo(ConsentLevel::kSync).gaia, device_account.key.id());
diff --git a/components/signin/public/identity_manager/identity_mutator.cc b/components/signin/public/identity_manager/identity_mutator.cc index 094e440..25619a3 100644 --- a/components/signin/public/identity_manager/identity_mutator.cc +++ b/components/signin/public/identity_manager/identity_mutator.cc
@@ -30,9 +30,11 @@ identity_mutator_->GetPrimaryAccountMutator(); DCHECK(primary_account_mutator); - return primary_account_mutator->SetPrimaryAccount( - ConvertFromJavaCoreAccountId(env, primary_account_id), - static_cast<ConsentLevel>(j_consent_level)); + PrimaryAccountMutator::PrimaryAccountError error = + primary_account_mutator->SetPrimaryAccount( + ConvertFromJavaCoreAccountId(env, primary_account_id), + static_cast<ConsentLevel>(j_consent_level)); + return error == PrimaryAccountMutator::PrimaryAccountError::kNoError; } bool JniIdentityMutator::ClearPrimaryAccount(JNIEnv* env,
diff --git a/components/signin/public/identity_manager/primary_account_mutator.h b/components/signin/public/identity_manager/primary_account_mutator.h index 604daa2..4fc1464 100644 --- a/components/signin/public/identity_manager/primary_account_mutator.h +++ b/components/signin/public/identity_manager/primary_account_mutator.h
@@ -27,6 +27,18 @@ // available at runtime (thus accessors may return null). class PrimaryAccountMutator { public: + // Error returned by SetPrimaryAccount(). + enum class PrimaryAccountError { + // No error, the operation was successful. + kNoError = 0, + // Account info is empty. + kAccountInfoEmpty = 1, + // Sync consent was already set. + kSyncConsentAlreadySet = 2, + // Sign-in is disallowed. + kSigninNotAllowed = 4, + }; + PrimaryAccountMutator() = default; virtual ~PrimaryAccountMutator() = default; @@ -55,8 +67,8 @@ // (i.e. without implying browser sync consent). Requires that the account // is known by the IdentityManager. See README.md for details on the meaning // of "unconsented". Returns whether the operation succeeded or not. - virtual bool SetPrimaryAccount(const CoreAccountId& account_id, - ConsentLevel consent_level) = 0; + virtual PrimaryAccountError SetPrimaryAccount(const CoreAccountId& account_id, + ConsentLevel consent_level) = 0; // Revokes sync consent from the primary account. We distinguish the following // cases:
diff --git a/components/signin/public/identity_manager/primary_account_mutator_unittest.cc b/components/signin/public/identity_manager/primary_account_mutator_unittest.cc index e7c8707..ce93c21 100644 --- a/components/signin/public/identity_manager/primary_account_mutator_unittest.cc +++ b/components/signin/public/identity_manager/primary_account_mutator_unittest.cc
@@ -131,8 +131,11 @@ identity_manager->HasPrimaryAccount(signin::ConsentLevel::kSync)); AccountInfo account_info = environment.MakeAccountAvailable(kPrimaryAccountEmail); - EXPECT_TRUE(primary_account_mutator->SetPrimaryAccount( - account_info.account_id, signin::ConsentLevel::kSync)); + signin::PrimaryAccountMutator::PrimaryAccountError setPrimaryAccountResult = + primary_account_mutator->SetPrimaryAccount(account_info.account_id, + signin::ConsentLevel::kSync); + EXPECT_EQ(signin::PrimaryAccountMutator::PrimaryAccountError::kNoError, + setPrimaryAccountResult); EXPECT_TRUE(identity_manager->HasPrimaryAccount(signin::ConsentLevel::kSync)); EXPECT_TRUE(identity_manager->HasPrimaryAccountWithRefreshToken( signin::ConsentLevel::kSync)); @@ -269,8 +272,11 @@ EXPECT_FALSE(environment.identity_manager()->HasPrimaryAccount( signin::ConsentLevel::kSync)); - EXPECT_TRUE(primary_account_mutator->SetPrimaryAccount( - account_info.account_id, signin::ConsentLevel::kSync)); + signin::PrimaryAccountMutator::PrimaryAccountError setPrimaryAccountResult = + primary_account_mutator->SetPrimaryAccount(account_info.account_id, + signin::ConsentLevel::kSync); + EXPECT_EQ(signin::PrimaryAccountMutator::PrimaryAccountError::kNoError, + setPrimaryAccountResult); EXPECT_TRUE(identity_manager->HasPrimaryAccount(signin::ConsentLevel::kSync)); EXPECT_EQ(identity_manager->GetPrimaryAccountId(signin::ConsentLevel::kSync), @@ -300,8 +306,12 @@ EXPECT_FALSE( identity_manager->HasPrimaryAccount(signin::ConsentLevel::kSync)); - EXPECT_FALSE(primary_account_mutator->SetPrimaryAccount( - CoreAccountId(kUnknownAccountId), signin::ConsentLevel::kSync)); + signin::PrimaryAccountMutator::PrimaryAccountError setPrimaryAccountResult = + primary_account_mutator->SetPrimaryAccount( + CoreAccountId(kUnknownAccountId), signin::ConsentLevel::kSync); + EXPECT_EQ( + signin::PrimaryAccountMutator::PrimaryAccountError::kAccountInfoEmpty, + setPrimaryAccountResult); } // Checks that setting the primary account fails if the account is unknown. @@ -323,8 +333,12 @@ EXPECT_FALSE( identity_manager->HasPrimaryAccount(signin::ConsentLevel::kSync)); - EXPECT_FALSE(primary_account_mutator->SetPrimaryAccount( - CoreAccountId(kUnknownAccountId), signin::ConsentLevel::kSync)); + signin::PrimaryAccountMutator::PrimaryAccountError setPrimaryAccountResult = + primary_account_mutator->SetPrimaryAccount( + CoreAccountId(kUnknownAccountId), signin::ConsentLevel::kSync); + EXPECT_EQ( + signin::PrimaryAccountMutator::PrimaryAccountError::kAccountInfoEmpty, + setPrimaryAccountResult); } // Checks that trying to set the primary account fails when there is already a @@ -349,12 +363,18 @@ EXPECT_FALSE( identity_manager->HasPrimaryAccount(signin::ConsentLevel::kSync)); - EXPECT_TRUE(primary_account_mutator->SetPrimaryAccount( - primary_account_info.account_id, signin::ConsentLevel::kSync)); + signin::PrimaryAccountMutator::PrimaryAccountError setPrimaryAccountResult = + primary_account_mutator->SetPrimaryAccount( + primary_account_info.account_id, signin::ConsentLevel::kSync); + EXPECT_EQ(signin::PrimaryAccountMutator::PrimaryAccountError::kNoError, + setPrimaryAccountResult); EXPECT_TRUE(identity_manager->HasPrimaryAccount(signin::ConsentLevel::kSync)); - EXPECT_FALSE(primary_account_mutator->SetPrimaryAccount( - another_account_info.account_id, signin::ConsentLevel::kSync)); + setPrimaryAccountResult = primary_account_mutator->SetPrimaryAccount( + another_account_info.account_id, signin::ConsentLevel::kSync); + EXPECT_EQ(signin::PrimaryAccountMutator::PrimaryAccountError:: + kSyncConsentAlreadySet, + setPrimaryAccountResult); EXPECT_EQ(identity_manager->GetPrimaryAccountId(signin::ConsentLevel::kSync), primary_account_info.account_id); @@ -388,8 +408,12 @@ EXPECT_FALSE( identity_manager->HasPrimaryAccount(signin::ConsentLevel::kSync)); - EXPECT_FALSE(primary_account_mutator->SetPrimaryAccount( - primary_account_info.account_id, signin::ConsentLevel::kSync)); + signin::PrimaryAccountMutator::PrimaryAccountError setPrimaryAccountResult = + primary_account_mutator->SetPrimaryAccount( + primary_account_info.account_id, signin::ConsentLevel::kSync); + EXPECT_EQ( + signin::PrimaryAccountMutator::PrimaryAccountError::kSigninNotAllowed, + setPrimaryAccountResult); } #endif // !BUILDFLAG(IS_CHROMEOS_LACROS)
diff --git a/components/sync_device_info/fake_device_info_tracker.cc b/components/sync_device_info/fake_device_info_tracker.cc index 2197021..a10fde1 100644 --- a/components/sync_device_info/fake_device_info_tracker.cc +++ b/components/sync_device_info/fake_device_info_tracker.cc
@@ -4,6 +4,8 @@ #include "components/sync_device_info/fake_device_info_tracker.h" +#include <algorithm> + #include "base/check.h" #include "base/notreached.h" #include "components/sync_device_info/device_info.h" @@ -85,6 +87,16 @@ observer.OnDeviceInfoChange(); } +void FakeDeviceInfoTracker::Replace(const DeviceInfo* old_device, + const DeviceInfo* new_device) { + std::vector<const DeviceInfo*>::iterator it = + std::find(devices_.begin(), devices_.end(), old_device); + DCHECK(devices_.end() != it) << "Tracker doesn't contain device"; + *it = new_device; + for (auto& observer : observers_) + observer.OnDeviceInfoChange(); +} + void FakeDeviceInfoTracker::OverrideActiveDeviceCount(int count) { active_device_count_ = count; for (auto& observer : observers_)
diff --git a/components/sync_device_info/fake_device_info_tracker.h b/components/sync_device_info/fake_device_info_tracker.h index 692f2c7..acd0ca6 100644 --- a/components/sync_device_info/fake_device_info_tracker.h +++ b/components/sync_device_info/fake_device_info_tracker.h
@@ -42,6 +42,10 @@ // Adds a new DeviceInfo entry to |devices_|. void Add(const DeviceInfo* device); + // Replaces |old_device| with |new_device|. |old_device| must be present in + // the tracker. + void Replace(const DeviceInfo* old_device, const DeviceInfo* new_device); + // Overrides the result of CountActiveDevices() to |count| instead of the // actual number of devices in |devices_|. void OverrideActiveDeviceCount(int count);
diff --git a/components/viz/common/viz_utils.cc b/components/viz/common/viz_utils.cc index fd78c7e..8d3aa5c4 100644 --- a/components/viz/common/viz_utils.cc +++ b/components/viz/common/viz_utils.cc
@@ -4,6 +4,9 @@ #include "components/viz/common/viz_utils.h" +#include <algorithm> +#include <vector> + #include "base/command_line.h" #include "base/system/sys_info.h" #include "ui/gfx/geometry/rect.h" @@ -16,6 +19,11 @@ #include "base/android/build_info.h" #endif +#if defined(OS_POSIX) +#include <poll.h> +#include <sys/resource.h> +#endif + namespace viz { bool PreferRGB565ResourcesForDisplay() { @@ -103,4 +111,41 @@ return true; } +bool GatherFDStats(base::TimeDelta* delta_time_taken, + int* fd_max, + int* active_fd_count, + int* rlim_cur) { +#if !defined(OS_POSIX) + return false; +#else // defined(OS_POSIX) + // https://stackoverflow.com/questions/7976769/ + // getting-count-of-current-used-file-descriptors-from-c-code + base::ElapsedTimer timer; + rlimit limit_data; + getrlimit(RLIMIT_NOFILE, &limit_data); + std::vector<pollfd> poll_data; + constexpr int kMaxNumFDTested = 1 << 16; + // |rlim_cur| is the soft max but is likely the value we can rely on instead + // of the real max. + *rlim_cur = static_cast<int>(limit_data.rlim_cur); + *fd_max = std::max(1, std::min(*rlim_cur, kMaxNumFDTested)); + poll_data.resize(*fd_max); + for (size_t i = 0; i < poll_data.size(); i++) { + auto& each = poll_data[i]; + each.fd = static_cast<int>(i); + each.events = 0; + each.revents = 0; + } + + poll(poll_data.data(), poll_data.size(), 0); + *active_fd_count = 0; + for (auto&& each : poll_data) { + if (each.revents != POLLNVAL) + (*active_fd_count)++; + } + *delta_time_taken = timer.Elapsed(); + return true; +#endif // defined(OS_POSIX) +} + } // namespace viz
diff --git a/components/viz/common/viz_utils.h b/components/viz/common/viz_utils.h index be7ea5e5..b0ef766 100644 --- a/components/viz/common/viz_utils.h +++ b/components/viz/common/viz_utils.h
@@ -5,6 +5,7 @@ #ifndef COMPONENTS_VIZ_COMMON_VIZ_UTILS_H_ #define COMPONENTS_VIZ_COMMON_VIZ_UTILS_H_ +#include "base/timer/elapsed_timer.h" #include "components/viz/common/viz_common_export.h" #include "build/build_config.h" @@ -39,6 +40,14 @@ const gfx::QuadF* clip, float uvs[8]); +// Returns File Descriptor (FD) stats for current process. +// Rendering resources can consume FDs. This this function can be used to +// determine if the process is low on FDs or find an FD leak. +VIZ_COMMON_EXPORT bool GatherFDStats(base::TimeDelta* delta_time_taken, + int* fd_max, + int* active_fd_count, + int* rlim_cur); + } // namespace viz #endif // COMPONENTS_VIZ_COMMON_VIZ_UTILS_H_
diff --git a/components/viz/service/display/overlay_processor_delegated.cc b/components/viz/service/display/overlay_processor_delegated.cc index f31d94de..f055f44 100644 --- a/components/viz/service/display/overlay_processor_delegated.cc +++ b/components/viz/service/display/overlay_processor_delegated.cc
@@ -20,6 +20,8 @@ #include "build/chromeos_buildflags.h" #include "components/viz/common/features.h" #include "components/viz/common/quads/solid_color_draw_quad.h" +#include "components/viz/common/quads/texture_draw_quad.h" +#include "components/viz/common/viz_utils.h" #include "components/viz/service/debugger/viz_debugger.h" #include "components/viz/service/display/display_resource_provider.h" #include "components/viz/service/display/output_surface.h" @@ -36,7 +38,47 @@ #include "ui/gfx/geometry/transform.h" #include "ui/gfx/geometry/vector2d_f.h" -#include "components/viz/common/quads/texture_draw_quad.h" +namespace { +DBG_FLAG_FBOOL("delegated.fd.usage", usage_every_frame) + +void RecordFDUsageUMA() { + static uint64_t sReportUsageFrameCounter = 0; + sReportUsageFrameCounter++; + constexpr uint32_t kReportEveryNFrames = 60 * 60 * 5; + if (((sReportUsageFrameCounter % kReportEveryNFrames) != 0) && + !usage_every_frame()) { + return; + } + + base::TimeDelta delta_time_taken; + int fd_max; + int active_fd_count; + int rlim_cur; + + if (!viz::GatherFDStats(&delta_time_taken, &fd_max, &active_fd_count, + &rlim_cur)) + return; + + static constexpr base::TimeDelta kHistogramMinTime = + base::TimeDelta::FromMicroseconds(5); + static constexpr base::TimeDelta kHistogramMaxTime = + base::TimeDelta::FromMilliseconds(10); + static constexpr int kHistogramTimeBuckets = 50; + int percentage_usage_int = (active_fd_count * 100) / fd_max; + UMA_HISTOGRAM_PERCENTAGE("Viz.FileDescriptorTracking.PercentageUsed", + percentage_usage_int); + UMA_HISTOGRAM_COUNTS_100000("Viz.FileDescriptorTracking.NumActive", + active_fd_count); + UMA_HISTOGRAM_COUNTS_100000("Viz.FileDescriptorTracking.NumSoftMax", + rlim_cur); + UMA_HISTOGRAM_CUSTOM_MICROSECONDS_TIMES( + "Viz.FileDescriptorTracking.TimeToCompute", delta_time_taken, + kHistogramMinTime, kHistogramMaxTime, kHistogramTimeBuckets); + + DBG_LOG("delegated.fd.usage", "FD usage: %d / %d - time us: %f", + active_fd_count, fd_max, delta_time_taken.InMicrosecondsF()); +} +} // namespace namespace viz { @@ -189,6 +231,9 @@ DCHECK(candidates->empty()); auto* render_pass = render_passes->back().get(); bool success = false; +#if !defined(OS_APPLE) + RecordFDUsageUMA(); +#endif DBG_DRAW_RECT("delegated.incoming.damage", (*damage_rect)); for (auto&& each : surface_damage_rect_list) {
diff --git a/components/viz/service/display/overlay_processor_using_strategy.cc b/components/viz/service/display/overlay_processor_using_strategy.cc index 2a38d96..bd0c247 100644 --- a/components/viz/service/display/overlay_processor_using_strategy.cc +++ b/components/viz/service/display/overlay_processor_using_strategy.cc
@@ -149,8 +149,6 @@ DBG_DRAW_RECT("overlay.incoming.damage", (*damage_rect)); for (auto&& each : surface_damage_rect_list) { DBG_DRAW_RECT("overlay.surface.damage", each); - // TODO(petermcneeley) : Check is temporary to isolate b/191414141. - CHECK(each.size().GetCheckedArea().IsValid()); } // If we have any copy requests, we can't remove any quads for overlays or
diff --git a/components/viz/service/display/surface_aggregator.cc b/components/viz/service/display/surface_aggregator.cc index ae15e03..1bfdef68 100644 --- a/components/viz/service/display/surface_aggregator.cc +++ b/components/viz/service/display/surface_aggregator.cc
@@ -399,8 +399,6 @@ damage_rect_in_root_target_space.Intersect(root_clip_rect); } - // TODO(petermcneeley) : Check is temporary to isolate b/191414141. - CHECK(damage_rect_in_root_target_space.size().GetCheckedArea().IsValid()); surface_damage_rect_list_->push_back(damage_rect_in_root_target_space); } @@ -465,8 +463,6 @@ surface_damage_rect_list_->push_back(gfx::Rect()); } - // TODO(petermcneeley) : Check is temporary to isolate b/191414141. - CHECK(!surface_damage_rect_list_->empty()); // The latest surface damage rect. *overlay_damage_index = surface_damage_rect_list_->size() - 1; @@ -1190,8 +1186,6 @@ AddSurfaceDamageToDamageList(damage_rect_in_target_space.value(), target_transform, {}, dest_pass, /*resolved_frame=*/nullptr); - // TODO(petermcneeley) : Check is temporary to isolate b/191414141. - CHECK_GE(surface_damage_rect_list_->size(), 1u); } else if (quad == quad_with_overlay_damage_index) { dest_shared_quad_state->overlay_damage_index = overlay_damage_index; }
diff --git a/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.cc b/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.cc index d862fb2..f2d24a90 100644 --- a/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.cc +++ b/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.cc
@@ -72,7 +72,9 @@ std::unique_ptr<SyntheticBeginFrameSource> synthetic_begin_frame_source; ExternalBeginFrameSourceMojo* external_begin_frame_source_mojo = nullptr; bool hw_support_for_multiple_refresh_rates = false; +#if !defined(OS_APPLE) bool wants_vsync_updates = false; +#endif if (params->external_begin_frame_controller) { auto owned_external_begin_frame_source_mojo = @@ -103,7 +105,9 @@ #endif // Vsync updates are required to update the FrameRateDecider with // supported refresh rates. +#if !defined(OS_APPLE) wants_vsync_updates = params->use_preferred_interval_for_video; +#endif external_begin_frame_source = std::make_unique<GpuVSyncBeginFrameSource>( restart_id, output_surface.get()); } else {
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn index 656f9ee..592551f 100644 --- a/content/browser/BUILD.gn +++ b/content/browser/BUILD.gn
@@ -438,6 +438,8 @@ "attribution_reporting/attribution_host_utils.h", "attribution_reporting/attribution_internals_handler_impl.cc", "attribution_reporting/attribution_internals_handler_impl.h", + "attribution_reporting/attribution_internals_ui.cc", + "attribution_reporting/attribution_internals_ui.h", "attribution_reporting/attribution_manager.h", "attribution_reporting/attribution_manager_impl.cc", "attribution_reporting/attribution_manager_impl.h", @@ -463,8 +465,6 @@ "attribution_reporting/attribution_storage_sql_migrations.h", "attribution_reporting/attribution_utils.cc", "attribution_reporting/attribution_utils.h", - "attribution_reporting/conversion_internals_ui.cc", - "attribution_reporting/conversion_internals_ui.h", "attribution_reporting/rate_limit_table.cc", "attribution_reporting/rate_limit_table.h", "attribution_reporting/sent_report_info.cc",
diff --git a/content/browser/accessibility/browser_accessibility_manager_android.cc b/content/browser/accessibility/browser_accessibility_manager_android.cc index 1388bb5..62f5fd3 100644 --- a/content/browser/accessibility/browser_accessibility_manager_android.cc +++ b/content/browser/accessibility/browser_accessibility_manager_android.cc
@@ -535,6 +535,15 @@ ClearNodeInfoCacheForGivenId(android_node->unique_id()); + // When a node will be deleted, clear its parent from the cache as well, or + // the parent could erroneously report the cleared node as a child later on. + BrowserAccessibilityAndroid* parent_node = + static_cast<BrowserAccessibilityAndroid*>( + android_node->PlatformGetParent()); + if (parent_node != nullptr) { + ClearNodeInfoCacheForGivenId(parent_node->unique_id()); + } + BrowserAccessibilityManager::OnNodeWillBeDeleted(tree, node); }
diff --git a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc index 2a12bea..2431476 100644 --- a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc +++ b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
@@ -2777,14 +2777,8 @@ RunHtmlTest(FILE_PATH_LITERAL("svg-symbol-with-role.html")); } -// On ChromeOS, SVG <g> elements are included. -#if defined(OS_CHROMEOS) -#define AccessibilitySvgG_TestFile FILE_PATH_LITERAL("svg-g-for-cros.html") -#else -#define AccessibilitySvgG_TestFile FILE_PATH_LITERAL("svg-g.html") -#endif IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, AccessibilitySvgG) { - RunHtmlTest(AccessibilitySvgG_TestFile); + RunHtmlTest(FILE_PATH_LITERAL("svg-g.html")); } IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest,
diff --git a/content/browser/appcache/appcache_request_handler.cc b/content/browser/appcache/appcache_request_handler.cc index 3d24d68..7248016 100644 --- a/content/browser/appcache/appcache_request_handler.cc +++ b/content/browser/appcache/appcache_request_handler.cc
@@ -645,18 +645,8 @@ absl::optional<SubresourceLoaderParams> AppCacheRequestHandler::MaybeCreateSubresourceLoaderParams() { - if (!should_create_subresource_loader_) - return absl::nullopt; - - // The factory is destroyed when the renderer drops the connection. - mojo::PendingRemote<network::mojom::URLLoaderFactory> factory_remote; - - AppCacheSubresourceURLFactory::CreateURLLoaderFactory( - appcache_host_, factory_remote.InitWithNewPipeAndPassReceiver()); - - SubresourceLoaderParams params; - params.pending_appcache_loader_factory = std::move(factory_remote); - return absl::optional<SubresourceLoaderParams>(std::move(params)); + // TODO(enne): remove the rest of this file. + return absl::nullopt; } void AppCacheRequestHandler::MaybeCreateSubresourceLoader(
diff --git a/content/browser/attribution_reporting/BUILD.gn b/content/browser/attribution_reporting/BUILD.gn index 4dd227e..3c76eb8 100644 --- a/content/browser/attribution_reporting/BUILD.gn +++ b/content/browser/attribution_reporting/BUILD.gn
@@ -5,7 +5,7 @@ import("//mojo/public/tools/bindings/mojom.gni") mojom("mojo_bindings") { - sources = [ "conversion_internals.mojom" ] + sources = [ "attribution_internals.mojom" ] public_deps = [ "//url/mojom:url_mojom_origin" ] webui_module_path = "/" }
diff --git a/content/browser/attribution_reporting/conversion_internals.mojom b/content/browser/attribution_reporting/attribution_internals.mojom similarity index 98% rename from content/browser/attribution_reporting/conversion_internals.mojom rename to content/browser/attribution_reporting/attribution_internals.mojom index 84388fe..997077e 100644 --- a/content/browser/attribution_reporting/conversion_internals.mojom +++ b/content/browser/attribution_reporting/attribution_internals.mojom
@@ -53,7 +53,7 @@ // Mojo interface for the conversion internals WebUI to communicate with the // storage layer. -interface ConversionInternalsHandler { +interface AttributionInternalsHandler { // Returns whether conversion measurement and the debug mode are enabled in // the browsing context the WebUI is in. IsMeasurementEnabled() => (bool enabled, bool debug_mode);
diff --git a/content/browser/attribution_reporting/attribution_internals_browsertest.cc b/content/browser/attribution_reporting/attribution_internals_browsertest.cc index 7a2effc..42df253 100644 --- a/content/browser/attribution_reporting/attribution_internals_browsertest.cc +++ b/content/browser/attribution_reporting/attribution_internals_browsertest.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "content/browser/attribution_reporting/conversion_internals_ui.h" +#include "content/browser/attribution_reporting/attribution_internals_ui.h" #include "base/strings/utf_string_conversions.h" #include "base/time/time.h" @@ -29,7 +29,7 @@ using CreateReportStatus = ::content::AttributionStorage::CreateReportResult::Status; -const char kConversionInternalsUrl[] = "chrome://conversion-internals/"; +const char kAttributionInternalsUrl[] = "chrome://conversion-internals/"; const std::u16string kCompleteTitle = u"Complete"; const std::u16string kCompleteTitle2 = u"Complete2"; @@ -40,9 +40,9 @@ } // namespace -class ConversionInternalsWebUiBrowserTest : public ContentBrowserTest { +class AttributionInternalsWebUiBrowserTest : public ContentBrowserTest { public: - ConversionInternalsWebUiBrowserTest() = default; + AttributionInternalsWebUiBrowserTest() = default; void ClickRefreshButton() { EXPECT_TRUE(ExecJsInWebUI("document.getElementById('refresh').click();")); @@ -59,12 +59,12 @@ void OverrideWebUIAttributionManager(AttributionManager* manager) { content::WebUI* web_ui = shell()->web_contents()->GetWebUI(); - // Performs a safe downcast to the concrete ConversionInternalsUI subclass. - ConversionInternalsUI* conversion_internals_ui = - web_ui ? web_ui->GetController()->GetAs<ConversionInternalsUI>() + // Performs a safe downcast to the concrete AttributionInternalsUI subclass. + AttributionInternalsUI* attribution_internals_ui = + web_ui ? web_ui->GetController()->GetAs<AttributionInternalsUI>() : nullptr; - EXPECT_TRUE(conversion_internals_ui); - conversion_internals_ui->SetAttributionManagerProviderForTesting( + EXPECT_TRUE(attribution_internals_ui); + attribution_internals_ui->SetAttributionManagerProviderForTesting( std::make_unique<TestManagerProvider>(manager)); } @@ -88,9 +88,9 @@ ConversionDisallowingContentBrowserClient disallowed_browser_client_; }; -IN_PROC_BROWSER_TEST_F(ConversionInternalsWebUiBrowserTest, +IN_PROC_BROWSER_TEST_F(AttributionInternalsWebUiBrowserTest, NavigationUrl_ResolvedToWebUI) { - EXPECT_TRUE(NavigateToURL(shell(), GURL(kConversionInternalsUrl))); + EXPECT_TRUE(NavigateToURL(shell(), GURL(kAttributionInternalsUrl))); // Execute script to ensure the page has loaded correctly, executing similarly // to ExecJsInWebUI(). @@ -100,9 +100,9 @@ EXECUTE_SCRIPT_DEFAULT_OPTIONS, /*world_id=*/1)); } -IN_PROC_BROWSER_TEST_F(ConversionInternalsWebUiBrowserTest, +IN_PROC_BROWSER_TEST_F(AttributionInternalsWebUiBrowserTest, WebUIShownWithManager_MeasurementConsideredEnabled) { - EXPECT_TRUE(NavigateToURL(shell(), GURL(kConversionInternalsUrl))); + EXPECT_TRUE(NavigateToURL(shell(), GURL(kAttributionInternalsUrl))); TestAttributionManager manager; OverrideWebUIAttributionManager(&manager); @@ -125,11 +125,11 @@ EXPECT_EQ(kCompleteTitle, title_watcher.WaitAndGetTitle()); } -IN_PROC_BROWSER_TEST_F(ConversionInternalsWebUiBrowserTest, +IN_PROC_BROWSER_TEST_F(AttributionInternalsWebUiBrowserTest, DisabledByEmbedder_MeasurementConsideredDisabled) { ContentBrowserClient* old_browser_client = SetBrowserClientForTesting(&disallowed_browser_client_); - EXPECT_TRUE(NavigateToURL(shell(), GURL(kConversionInternalsUrl))); + EXPECT_TRUE(NavigateToURL(shell(), GURL(kAttributionInternalsUrl))); TestAttributionManager manager; OverrideWebUIAttributionManager(&manager); @@ -154,9 +154,9 @@ } IN_PROC_BROWSER_TEST_F( - ConversionInternalsWebUiBrowserTest, + AttributionInternalsWebUiBrowserTest, WebUIShownWithNoActiveImpression_NoImpressionsDisplayed) { - EXPECT_TRUE(NavigateToURL(shell(), GURL(kConversionInternalsUrl))); + EXPECT_TRUE(NavigateToURL(shell(), GURL(kAttributionInternalsUrl))); TestAttributionManager manager; OverrideWebUIAttributionManager(&manager); @@ -178,9 +178,9 @@ EXPECT_EQ(kCompleteTitle, title_watcher.WaitAndGetTitle()); } -IN_PROC_BROWSER_TEST_F(ConversionInternalsWebUiBrowserTest, +IN_PROC_BROWSER_TEST_F(AttributionInternalsWebUiBrowserTest, WebUIShownWithActiveImpression_ImpressionsDisplayed) { - EXPECT_TRUE(NavigateToURL(shell(), GURL(kConversionInternalsUrl))); + EXPECT_TRUE(NavigateToURL(shell(), GURL(kAttributionInternalsUrl))); // We use the max values of `uint64_t` and `int64_t` here to ensure that they // are properly handled as `bigint` values in JS and don't run into issues @@ -224,9 +224,9 @@ EXPECT_EQ(kCompleteTitle, title_watcher.WaitAndGetTitle()); } -IN_PROC_BROWSER_TEST_F(ConversionInternalsWebUiBrowserTest, +IN_PROC_BROWSER_TEST_F(AttributionInternalsWebUiBrowserTest, WebUIShownWithNoReports_NoReportsDisplayed) { - EXPECT_TRUE(NavigateToURL(shell(), GURL(kConversionInternalsUrl))); + EXPECT_TRUE(NavigateToURL(shell(), GURL(kAttributionInternalsUrl))); TestAttributionManager manager; OverrideWebUIAttributionManager(&manager); @@ -237,9 +237,9 @@ EXPECT_EQ(kCompleteTitle, title_watcher.WaitAndGetTitle()); } -IN_PROC_BROWSER_TEST_F(ConversionInternalsWebUiBrowserTest, +IN_PROC_BROWSER_TEST_F(AttributionInternalsWebUiBrowserTest, WebUIShownWithManager_DebugModeDisabled) { - EXPECT_TRUE(NavigateToURL(shell(), GURL(kConversionInternalsUrl))); + EXPECT_TRUE(NavigateToURL(shell(), GURL(kAttributionInternalsUrl))); TestAttributionManager manager; OverrideWebUIAttributionManager(&manager); @@ -262,12 +262,12 @@ EXPECT_EQ(kCompleteTitle, title_watcher.WaitAndGetTitle()); } -IN_PROC_BROWSER_TEST_F(ConversionInternalsWebUiBrowserTest, +IN_PROC_BROWSER_TEST_F(AttributionInternalsWebUiBrowserTest, WebUIShownWithManager_DebugModeEnabled) { base::CommandLine::ForCurrentProcess()->AppendSwitch( switches::kConversionsDebugMode); - EXPECT_TRUE(NavigateToURL(shell(), GURL(kConversionInternalsUrl))); + EXPECT_TRUE(NavigateToURL(shell(), GURL(kAttributionInternalsUrl))); TestAttributionManager manager; OverrideWebUIAttributionManager(&manager); @@ -290,9 +290,9 @@ EXPECT_EQ(kCompleteTitle, title_watcher.WaitAndGetTitle()); } -IN_PROC_BROWSER_TEST_F(ConversionInternalsWebUiBrowserTest, +IN_PROC_BROWSER_TEST_F(AttributionInternalsWebUiBrowserTest, WebUIShownWithPendingReports_ReportsDisplayed) { - EXPECT_TRUE(NavigateToURL(shell(), GURL(kConversionInternalsUrl))); + EXPECT_TRUE(NavigateToURL(shell(), GURL(kAttributionInternalsUrl))); const base::Time now = base::Time::Now(); @@ -425,9 +425,9 @@ } } -IN_PROC_BROWSER_TEST_F(ConversionInternalsWebUiBrowserTest, +IN_PROC_BROWSER_TEST_F(AttributionInternalsWebUiBrowserTest, WebUIWithPendingReportsClearStorage_ReportsRemoved) { - EXPECT_TRUE(NavigateToURL(shell(), GURL(kConversionInternalsUrl))); + EXPECT_TRUE(NavigateToURL(shell(), GURL(kAttributionInternalsUrl))); const base::Time now = base::Time::Now(); @@ -473,9 +473,9 @@ // TODO(johnidel): Use a real AttributionManager here and verify that the // reports are actually sent. -IN_PROC_BROWSER_TEST_F(ConversionInternalsWebUiBrowserTest, +IN_PROC_BROWSER_TEST_F(AttributionInternalsWebUiBrowserTest, WebUISendReports_ReportsRemoved) { - EXPECT_TRUE(NavigateToURL(shell(), GURL(kConversionInternalsUrl))); + EXPECT_TRUE(NavigateToURL(shell(), GURL(kAttributionInternalsUrl))); TestAttributionManager manager; AttributionReport report( @@ -512,9 +512,9 @@ EXPECT_EQ(kSentTitle, sent_title_watcher.WaitAndGetTitle()); } -IN_PROC_BROWSER_TEST_F(ConversionInternalsWebUiBrowserTest, +IN_PROC_BROWSER_TEST_F(AttributionInternalsWebUiBrowserTest, MojoJsBindingsCorrectlyScoped) { - EXPECT_TRUE(NavigateToURL(shell(), GURL(kConversionInternalsUrl))); + EXPECT_TRUE(NavigateToURL(shell(), GURL(kAttributionInternalsUrl))); const std::u16string passed_title = u"passed";
diff --git a/content/browser/attribution_reporting/attribution_internals_handler_impl.cc b/content/browser/attribution_reporting/attribution_internals_handler_impl.cc index e035b52..27e0f1c 100644 --- a/content/browser/attribution_reporting/attribution_internals_handler_impl.cc +++ b/content/browser/attribution_reporting/attribution_internals_handler_impl.cc
@@ -45,7 +45,7 @@ } void ForwardImpressionsToWebUI( - mojom::ConversionInternalsHandler::GetActiveImpressionsCallback + mojom::AttributionInternalsHandler::GetActiveImpressionsCallback web_ui_callback, std::vector<StorableSource> stored_impressions) { std::vector<mojom::WebUIImpressionPtr> web_ui_impressions; @@ -81,7 +81,7 @@ } void ForwardReportsToWebUI( - mojom::ConversionInternalsHandler::GetReportsCallback web_ui_callback, + mojom::AttributionInternalsHandler::GetReportsCallback web_ui_callback, std::vector<mojom::WebUIConversionReportPtr> web_ui_reports, std::vector<AttributionReport> pending_reports) { web_ui_reports.reserve(web_ui_reports.capacity() + pending_reports.size()); @@ -100,7 +100,7 @@ AttributionInternalsHandlerImpl::AttributionInternalsHandlerImpl( WebUI* web_ui, - mojo::PendingReceiver<mojom::ConversionInternalsHandler> receiver) + mojo::PendingReceiver<mojom::AttributionInternalsHandler> receiver) : web_ui_(web_ui), manager_provider_(std::make_unique<AttributionManagerProviderImpl>()), receiver_(this, std::move(receiver)) {} @@ -108,7 +108,7 @@ AttributionInternalsHandlerImpl::~AttributionInternalsHandlerImpl() = default; void AttributionInternalsHandlerImpl::IsMeasurementEnabled( - mojom::ConversionInternalsHandler::IsMeasurementEnabledCallback callback) { + mojom::AttributionInternalsHandler::IsMeasurementEnabledCallback callback) { content::WebContents* contents = web_ui_->GetWebContents(); bool measurement_enabled = manager_provider_->GetManager(contents) && @@ -123,7 +123,7 @@ } void AttributionInternalsHandlerImpl::GetActiveImpressions( - mojom::ConversionInternalsHandler::GetActiveImpressionsCallback callback) { + mojom::AttributionInternalsHandler::GetActiveImpressionsCallback callback) { if (AttributionManager* manager = manager_provider_->GetManager(web_ui_->GetWebContents())) { manager->GetActiveImpressionsForWebUI( @@ -134,7 +134,7 @@ } void AttributionInternalsHandlerImpl::GetReports( - mojom::ConversionInternalsHandler::GetReportsCallback callback) { + mojom::AttributionInternalsHandler::GetReportsCallback callback) { if (AttributionManager* manager = manager_provider_->GetManager(web_ui_->GetWebContents())) { const AttributionSessionStorage& session_storage = @@ -185,7 +185,7 @@ } void AttributionInternalsHandlerImpl::SendPendingReports( - mojom::ConversionInternalsHandler::SendPendingReportsCallback callback) { + mojom::AttributionInternalsHandler::SendPendingReportsCallback callback) { if (AttributionManager* manager = manager_provider_->GetManager(web_ui_->GetWebContents())) { manager->SendReportsForWebUI(std::move(callback)); @@ -195,7 +195,7 @@ } void AttributionInternalsHandlerImpl::ClearStorage( - mojom::ConversionInternalsHandler::ClearStorageCallback callback) { + mojom::AttributionInternalsHandler::ClearStorageCallback callback) { if (AttributionManager* manager = manager_provider_->GetManager(web_ui_->GetWebContents())) { manager->ClearData(base::Time::Min(), base::Time::Max(),
diff --git a/content/browser/attribution_reporting/attribution_internals_handler_impl.h b/content/browser/attribution_reporting/attribution_internals_handler_impl.h index 5dc8d981..92501421 100644 --- a/content/browser/attribution_reporting/attribution_internals_handler_impl.h +++ b/content/browser/attribution_reporting/attribution_internals_handler_impl.h
@@ -5,8 +5,8 @@ #ifndef CONTENT_BROWSER_ATTRIBUTION_REPORTING_ATTRIBUTION_INTERNALS_HANDLER_IMPL_H_ #define CONTENT_BROWSER_ATTRIBUTION_REPORTING_ATTRIBUTION_INTERNALS_HANDLER_IMPL_H_ +#include "content/browser/attribution_reporting/attribution_internals.mojom.h" #include "content/browser/attribution_reporting/attribution_manager.h" -#include "content/browser/attribution_reporting/conversion_internals.mojom.h" #include "mojo/public/cpp/bindings/pending_receiver.h" #include "mojo/public/cpp/bindings/receiver.h" @@ -16,13 +16,13 @@ // Implements the mojo endpoint for the Conversion WebUI which proxies calls to // the AttributionManager to get information about stored conversion data. Owned -// by ConversionInternalsUI. +// by AttributionInternalsUI. class AttributionInternalsHandlerImpl - : public mojom::ConversionInternalsHandler { + : public mojom::AttributionInternalsHandler { public: AttributionInternalsHandlerImpl( WebUI* web_ui, - mojo::PendingReceiver<mojom::ConversionInternalsHandler> receiver); + mojo::PendingReceiver<mojom::AttributionInternalsHandler> receiver); AttributionInternalsHandlerImpl( const AttributionInternalsHandlerImpl& other) = delete; AttributionInternalsHandlerImpl& operator=( @@ -33,19 +33,19 @@ AttributionInternalsHandlerImpl&& other) = delete; ~AttributionInternalsHandlerImpl() override; - // mojom::ConversionInternalsHandler overrides: + // mojom::AttributionInternalsHandler overrides: void IsMeasurementEnabled( - mojom::ConversionInternalsHandler::IsMeasurementEnabledCallback callback) + mojom::AttributionInternalsHandler::IsMeasurementEnabledCallback callback) override; void GetActiveImpressions( - mojom::ConversionInternalsHandler::GetActiveImpressionsCallback callback) + mojom::AttributionInternalsHandler::GetActiveImpressionsCallback callback) override; void GetReports( - mojom::ConversionInternalsHandler::GetReportsCallback callback) override; + mojom::AttributionInternalsHandler::GetReportsCallback callback) override; void SendPendingReports( - mojom::ConversionInternalsHandler::SendPendingReportsCallback callback) + mojom::AttributionInternalsHandler::SendPendingReportsCallback callback) override; - void ClearStorage(mojom::ConversionInternalsHandler::ClearStorageCallback + void ClearStorage(mojom::AttributionInternalsHandler::ClearStorageCallback callback) override; void SetAttributionManagerProviderForTesting( @@ -55,7 +55,7 @@ WebUI* web_ui_; std::unique_ptr<AttributionManager::Provider> manager_provider_; - mojo::Receiver<mojom::ConversionInternalsHandler> receiver_; + mojo::Receiver<mojom::AttributionInternalsHandler> receiver_; }; } // namespace content
diff --git a/content/browser/attribution_reporting/conversion_internals_ui.cc b/content/browser/attribution_reporting/attribution_internals_ui.cc similarity index 63% rename from content/browser/attribution_reporting/conversion_internals_ui.cc rename to content/browser/attribution_reporting/attribution_internals_ui.cc index 00657c65..ea26d3e 100644 --- a/content/browser/attribution_reporting/conversion_internals_ui.cc +++ b/content/browser/attribution_reporting/attribution_internals_ui.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "content/browser/attribution_reporting/conversion_internals_ui.h" +#include "content/browser/attribution_reporting/attribution_internals_ui.h" #include "content/browser/attribution_reporting/attribution_internals_handler_impl.h" #include "content/browser/renderer_host/render_frame_host_impl.h" @@ -17,44 +17,44 @@ namespace content { -ConversionInternalsUI::ConversionInternalsUI(WebUI* web_ui) +AttributionInternalsUI::AttributionInternalsUI(WebUI* web_ui) : WebUIController(web_ui) { // Initialize the UI with no bindings. Mojo bindings will be separately // granted to frames within this WebContents. web_ui->SetBindings(BINDINGS_POLICY_NONE); WebUIDataSource* source = - WebUIDataSource::Create(kChromeUIConversionInternalsHost); + WebUIDataSource::Create(kChromeUIAttributionInternalsHost); - source->AddResourcePath("conversion_internals.mojom-webui.js", - IDR_CONVERSION_INTERNALS_MOJOM_JS); - source->AddResourcePath("conversion_internals.js", - IDR_CONVERSION_INTERNALS_JS); - source->AddResourcePath("conversion_internals.css", - IDR_CONVERSION_INTERNALS_CSS); - source->SetDefaultResource(IDR_CONVERSION_INTERNALS_HTML); + source->AddResourcePath("attribution_internals.mojom-webui.js", + IDR_ATTRIBUTION_INTERNALS_MOJOM_JS); + source->AddResourcePath("attribution_internals.js", + IDR_ATTRIBUTION_INTERNALS_JS); + source->AddResourcePath("attribution_internals.css", + IDR_ATTRIBUTION_INTERNALS_CSS); + source->SetDefaultResource(IDR_ATTRIBUTION_INTERNALS_HTML); source->OverrideContentSecurityPolicy( network::mojom::CSPDirectiveName::TrustedTypes, "trusted-types static-types;"); WebUIDataSource::Add(web_ui->GetWebContents()->GetBrowserContext(), source); } -WEB_UI_CONTROLLER_TYPE_IMPL(ConversionInternalsUI) +WEB_UI_CONTROLLER_TYPE_IMPL(AttributionInternalsUI) -ConversionInternalsUI::~ConversionInternalsUI() = default; +AttributionInternalsUI::~AttributionInternalsUI() = default; -void ConversionInternalsUI::WebUIRenderFrameCreated(RenderFrameHost* rfh) { +void AttributionInternalsUI::WebUIRenderFrameCreated(RenderFrameHost* rfh) { // Enable the JavaScript Mojo bindings in the renderer process, so the JS // code can call the Mojo APIs exposed by this WebUI. static_cast<RenderFrameHostImpl*>(rfh)->EnableMojoJsBindings(); } -void ConversionInternalsUI::BindInterface( - mojo::PendingReceiver<mojom::ConversionInternalsHandler> receiver) { +void AttributionInternalsUI::BindInterface( + mojo::PendingReceiver<mojom::AttributionInternalsHandler> receiver) { ui_handler_ = std::make_unique<AttributionInternalsHandlerImpl>( web_ui(), std::move(receiver)); } -void ConversionInternalsUI::SetAttributionManagerProviderForTesting( +void AttributionInternalsUI::SetAttributionManagerProviderForTesting( std::unique_ptr<AttributionManager::Provider> manager_provider) { ui_handler_->SetAttributionManagerProviderForTesting( std::move(manager_provider));
diff --git a/content/browser/attribution_reporting/attribution_internals_ui.h b/content/browser/attribution_reporting/attribution_internals_ui.h new file mode 100644 index 0000000..8f4770f --- /dev/null +++ b/content/browser/attribution_reporting/attribution_internals_ui.h
@@ -0,0 +1,49 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_BROWSER_ATTRIBUTION_REPORTING_ATTRIBUTION_INTERNALS_UI_H_ +#define CONTENT_BROWSER_ATTRIBUTION_REPORTING_ATTRIBUTION_INTERNALS_UI_H_ + +#include <memory> + +#include "content/browser/attribution_reporting/attribution_internals.mojom.h" +#include "content/browser/attribution_reporting/attribution_manager.h" +#include "content/common/content_export.h" +#include "content/public/browser/web_contents_observer.h" +#include "content/public/browser/web_ui_controller.h" +#include "mojo/public/cpp/bindings/pending_receiver.h" + +namespace content { + +class AttributionInternalsHandlerImpl; + +// WebUI which handles serving the chrome://conversion-internals page. +class CONTENT_EXPORT AttributionInternalsUI : public WebUIController { + public: + explicit AttributionInternalsUI(WebUI* web_ui); + AttributionInternalsUI(const AttributionInternalsUI& other) = delete; + AttributionInternalsUI& operator=(const AttributionInternalsUI& other) = + delete; + AttributionInternalsUI(AttributionInternalsUI&& other) = delete; + AttributionInternalsUI& operator=(AttributionInternalsUI&& other) = delete; + ~AttributionInternalsUI() override; + + // WebUIController overrides: + void WebUIRenderFrameCreated(RenderFrameHost* render_frame_host) override; + + void BindInterface( + mojo::PendingReceiver<mojom::AttributionInternalsHandler> receiver); + + void SetAttributionManagerProviderForTesting( + std::unique_ptr<AttributionManager::Provider> manager_provider); + + private: + std::unique_ptr<AttributionInternalsHandlerImpl> ui_handler_; + + WEB_UI_CONTROLLER_TYPE_DECL(); +}; + +} // namespace content + +#endif // CONTENT_BROWSER_ATTRIBUTION_REPORTING_ATTRIBUTION_INTERNALS_UI_H_
diff --git a/content/browser/attribution_reporting/conversion_internals_ui.h b/content/browser/attribution_reporting/conversion_internals_ui.h deleted file mode 100644 index 7f22abb..0000000 --- a/content/browser/attribution_reporting/conversion_internals_ui.h +++ /dev/null
@@ -1,48 +0,0 @@ -// Copyright 2020 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CONTENT_BROWSER_ATTRIBUTION_REPORTING_CONVERSION_INTERNALS_UI_H_ -#define CONTENT_BROWSER_ATTRIBUTION_REPORTING_CONVERSION_INTERNALS_UI_H_ - -#include <memory> - -#include "content/browser/attribution_reporting/attribution_manager.h" -#include "content/browser/attribution_reporting/conversion_internals.mojom.h" -#include "content/common/content_export.h" -#include "content/public/browser/web_contents_observer.h" -#include "content/public/browser/web_ui_controller.h" -#include "mojo/public/cpp/bindings/pending_receiver.h" - -namespace content { - -class AttributionInternalsHandlerImpl; - -// WebUI which handles serving the chrome://conversion-internals page. -class CONTENT_EXPORT ConversionInternalsUI : public WebUIController { - public: - explicit ConversionInternalsUI(WebUI* web_ui); - ConversionInternalsUI(const ConversionInternalsUI& other) = delete; - ConversionInternalsUI& operator=(const ConversionInternalsUI& other) = delete; - ConversionInternalsUI(ConversionInternalsUI&& other) = delete; - ConversionInternalsUI& operator=(ConversionInternalsUI&& other) = delete; - ~ConversionInternalsUI() override; - - // WebUIController overrides: - void WebUIRenderFrameCreated(RenderFrameHost* render_frame_host) override; - - void BindInterface( - mojo::PendingReceiver<mojom::ConversionInternalsHandler> receiver); - - void SetAttributionManagerProviderForTesting( - std::unique_ptr<AttributionManager::Provider> manager_provider); - - private: - std::unique_ptr<AttributionInternalsHandlerImpl> ui_handler_; - - WEB_UI_CONTROLLER_TYPE_DECL(); -}; - -} // namespace content - -#endif // CONTENT_BROWSER_ATTRIBUTION_REPORTING_CONVERSION_INTERNALS_UI_H_
diff --git a/content/browser/browser_interface_binders.cc b/content/browser/browser_interface_binders.cc index 5ba624e..b6c3c73 100644 --- a/content/browser/browser_interface_binders.cc +++ b/content/browser/browser_interface_binders.cc
@@ -13,8 +13,8 @@ #include "build/build_config.h" #include "build/chromeos_buildflags.h" #include "cc/base/switches.h" -#include "content/browser/attribution_reporting/conversion_internals.mojom.h" -#include "content/browser/attribution_reporting/conversion_internals_ui.h" +#include "content/browser/attribution_reporting/attribution_internals.mojom.h" +#include "content/browser/attribution_reporting/attribution_internals_ui.h" #include "content/browser/background_fetch/background_fetch_service_impl.h" #include "content/browser/bad_message.h" #include "content/browser/browser_main_loop.h" @@ -254,19 +254,19 @@ web_contents->OnColorChooserFactoryReceiver(std::move(receiver)); } -void BindConversionInternalsHandler( +void BindAttributionInternalsHandler( content::RenderFrameHost* host, - mojo::PendingReceiver<mojom::ConversionInternalsHandler> receiver) { + mojo::PendingReceiver<mojom::AttributionInternalsHandler> receiver) { content::WebUI* web_ui = host->GetWebUI(); - // Performs a safe downcast to the concrete ConversionInternalsUI subclass. - ConversionInternalsUI* conversion_internals_ui = - web_ui ? web_ui->GetController()->GetAs<ConversionInternalsUI>() + // Performs a safe downcast to the concrete AttributionInternalsUI subclass. + AttributionInternalsUI* attribution_internals_ui = + web_ui ? web_ui->GetController()->GetAs<AttributionInternalsUI>() : nullptr; // This is expected to be called only for main frames and for the right WebUI // pages matching the same WebUI associated to the RenderFrameHost. - if (host->GetParent() || !conversion_internals_ui) { + if (host->GetParent() || !attribution_internals_ui) { ReceivedBadMessage( host->GetProcess(), bad_message::BadMessageReason::RFH_INVALID_WEB_UI_CONTROLLER); @@ -274,10 +274,10 @@ } DCHECK_EQ(host->GetLastCommittedURL().host_piece(), - kChromeUIConversionInternalsHost); + kChromeUIAttributionInternalsHost); DCHECK(host->GetLastCommittedURL().SchemeIs(kChromeUIScheme)); - conversion_internals_ui->BindInterface(std::move(receiver)); + attribution_internals_ui->BindInterface(std::move(receiver)); } void BindPrerenderInternalsHandler( @@ -1032,8 +1032,8 @@ map->Add<device::mojom::VRService>( base::BindRepeating(&EmptyBinderForFrame<device::mojom::VRService>)); #endif - map->Add<mojom::ConversionInternalsHandler>( - base::BindRepeating(&BindConversionInternalsHandler)); + map->Add<mojom::AttributionInternalsHandler>( + base::BindRepeating(&BindAttributionInternalsHandler)); map->Add<mojom::PrerenderInternalsHandler>( base::BindRepeating(&BindPrerenderInternalsHandler)); map->Add<::mojom::ProcessInternalsHandler>(
diff --git a/content/browser/cookie_store/cookie_store_manager.cc b/content/browser/cookie_store/cookie_store_manager.cc index d44113c..b9707a3 100644 --- a/content/browser/cookie_store/cookie_store_manager.cc +++ b/content/browser/cookie_store/cookie_store_manager.cc
@@ -204,6 +204,8 @@ } for (const auto& mojo_subscription : mojo_subscriptions) { + // TODO(crbug.com/1246549): This validation step should consider the storage + // key. if (!blink::ServiceWorkerScopeMatches(service_worker_registration->scope(), mojo_subscription->url)) { // Blink should have validated subscription URLs against the service
diff --git a/content/browser/navigation_subresource_loader_params.cc b/content/browser/navigation_subresource_loader_params.cc index 0f92d78..1fc76c4 100644 --- a/content/browser/navigation_subresource_loader_params.cc +++ b/content/browser/navigation_subresource_loader_params.cc
@@ -16,8 +16,6 @@ SubresourceLoaderParams& SubresourceLoaderParams::operator=( SubresourceLoaderParams&& other) { - pending_appcache_loader_factory = - std::move(other.pending_appcache_loader_factory); controller_service_worker_info = std::move(other.controller_service_worker_info); controller_service_worker_object_host =
diff --git a/content/browser/navigation_subresource_loader_params.h b/content/browser/navigation_subresource_loader_params.h index 62c18479..c6180b8 100644 --- a/content/browser/navigation_subresource_loader_params.h +++ b/content/browser/navigation_subresource_loader_params.h
@@ -27,12 +27,6 @@ SubresourceLoaderParams(SubresourceLoaderParams&& other); SubresourceLoaderParams& operator=(SubresourceLoaderParams&& other); - // For AppCache. - // Subresource loader factory info for appcache, that is to be used to - // create a subresource loader in the renderer. - mojo::PendingRemote<network::mojom::URLLoaderFactory> - pending_appcache_loader_factory; - // For ServiceWorkers. // The controller service worker, non-null if the frame is to be // controlled by the service worker.
diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc index 754d634..a2c0654f 100644 --- a/content/browser/renderer_host/render_frame_host_impl.cc +++ b/content/browser/renderer_host/render_frame_host_impl.cc
@@ -7783,40 +7783,6 @@ .GetTupleOrPrecursorTupleIfOpaque() .scheme(); - // NOTE: On Network Service navigations, we want to ensure that a frame is - // given everything it will need to load any accessible subresources. We - // however only do this for cross-document navigations, because the - // alternative would be redundant effort. - if (subresource_loader_params && - subresource_loader_params->pending_appcache_loader_factory.is_valid()) { - // If the caller has supplied a factory for AppCache, use it. - mojo::Remote<network::mojom::URLLoaderFactory> appcache_remote(std::move( - subresource_loader_params->pending_appcache_loader_factory)); - - mojo::PendingRemote<network::mojom::URLLoaderFactory> - appcache_proxied_remote; - auto appcache_proxied_receiver = - appcache_proxied_remote.InitWithNewPipeAndPassReceiver(); - bool use_proxy = - GetContentClient()->browser()->WillCreateURLLoaderFactory( - browser_context, this, GetProcess()->GetID(), - ContentBrowserClient::URLLoaderFactoryType::kDocumentSubResource, - subresource_loader_factories_config.origin(), - /*navigation_id=*/absl::nullopt, - subresource_loader_factories_config.ukm_source_id(), - &appcache_proxied_receiver, /*header_client=*/nullptr, - /*bypass_redirect_checks=*/nullptr, - /*disable_secure_dns=*/nullptr, /*factory_override=*/nullptr); - if (use_proxy) { - appcache_remote->Clone(std::move(appcache_proxied_receiver)); - appcache_remote.reset(); - appcache_remote.Bind(std::move(appcache_proxied_remote)); - } - - subresource_loader_factories->pending_appcache_factory() = - appcache_remote.Unbind(); - } - ContentBrowserClient::NonNetworkURLLoaderFactoryMap non_network_factories; // Set up the default factory.
diff --git a/content/browser/resources/attribution_reporting/BUILD.gn b/content/browser/resources/attribution_reporting/BUILD.gn index 40950f0..fbdeee4 100644 --- a/content/browser/resources/attribution_reporting/BUILD.gn +++ b/content/browser/resources/attribution_reporting/BUILD.gn
@@ -11,10 +11,10 @@ "$root_gen_dir/mojom-webui/content/browser/attribution_reporting", root_build_dir), ] - deps = [ ":conversion_internals" ] + deps = [ ":attribution_internals" ] } -js_library("conversion_internals") { +js_library("attribution_internals") { deps = [ "//content/browser/attribution_reporting:mojo_bindings_webui_js", "//ui/webui/resources/js:assert.m",
diff --git a/content/browser/resources/attribution_reporting/conversion_internals.css b/content/browser/resources/attribution_reporting/attribution_internals.css similarity index 100% rename from content/browser/resources/attribution_reporting/conversion_internals.css rename to content/browser/resources/attribution_reporting/attribution_internals.css
diff --git a/content/browser/resources/attribution_reporting/conversion_internals.html b/content/browser/resources/attribution_reporting/attribution_internals.html similarity index 90% rename from content/browser/resources/attribution_reporting/conversion_internals.html rename to content/browser/resources/attribution_reporting/attribution_internals.html index c6fcc91..72c1457 100644 --- a/content/browser/resources/attribution_reporting/conversion_internals.html +++ b/content/browser/resources/attribution_reporting/attribution_internals.html
@@ -8,8 +8,8 @@ <link rel="stylesheet" href="chrome://resources/css/text_defaults.css"> <link rel="stylesheet" href="chrome://resources/css/roboto.css"> - <link rel="stylesheet" href="conversion_internals.css"> - <script type="module" src="conversion_internals.js"></script> + <link rel="stylesheet" href="attribution_internals.css"> + <script type="module" src="attribution_internals.js"></script> <title>Attribution Reporting API Internals</title> </head> <body>
diff --git a/content/browser/resources/attribution_reporting/conversion_internals.js b/content/browser/resources/attribution_reporting/attribution_internals.js similarity index 97% rename from content/browser/resources/attribution_reporting/conversion_internals.js rename to content/browser/resources/attribution_reporting/attribution_internals.js index fd7de09..a45b765f 100644 --- a/content/browser/resources/attribution_reporting/conversion_internals.js +++ b/content/browser/resources/attribution_reporting/attribution_internals.js
@@ -7,7 +7,7 @@ import {$, getRequiredElement} from 'chrome://resources/js/util.m.js'; import {Origin} from 'chrome://resources/mojo/url/mojom/origin.mojom-webui.js'; -import {ConversionInternalsHandler, ConversionInternalsHandlerRemote, SourceType, WebUIConversionReport, WebUIConversionReport_Status, WebUIImpression,} from './conversion_internals.mojom-webui.js'; +import {AttributionInternalsHandler, AttributionInternalsHandlerRemote, SourceType, WebUIConversionReport, WebUIConversionReport_Status, WebUIImpression,} from './attribution_internals.mojom-webui.js'; /** * @template T @@ -396,7 +396,7 @@ /** * Reference to the backend providing all the data. - * @type {?ConversionInternalsHandlerRemote} + * @type {?AttributionInternalsHandlerRemote} */ let pageHandler = null; @@ -495,7 +495,7 @@ document.addEventListener('DOMContentLoaded', function() { // Setup the mojo interface. - pageHandler = ConversionInternalsHandler.getRemote(); + pageHandler = AttributionInternalsHandler.getRemote(); $('refresh').addEventListener('click', updatePageData); $('clear-data').addEventListener('click', clearStorage);
diff --git a/content/browser/service_worker/service_worker_container_host.cc b/content/browser/service_worker/service_worker_container_host.cc index f2c8652d..5625c08 100644 --- a/content/browser/service_worker/service_worker_container_host.cc +++ b/content/browser/service_worker/service_worker_container_host.cc
@@ -480,6 +480,7 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(blink::ServiceWorkerScopeMatches(registration->scope(), GetUrlForScopeMatch())); + DCHECK(registration->key() == key()); if (!IsEligibleForServiceWorkerController()) return; size_t key = registration->scope().spec().size(); @@ -1199,7 +1200,7 @@ const auto& registrations = context_->GetLiveRegistrations(); for (const auto& key_registration : registrations) { ServiceWorkerRegistration* registration = key_registration.second; - if (!registration->is_uninstalled() && + if (!registration->is_uninstalled() && registration->key() == key() && blink::ServiceWorkerScopeMatches(registration->scope(), GetUrlForScopeMatch())) { AddMatchingRegistration(registration);
diff --git a/content/browser/service_worker/service_worker_container_host.h b/content/browser/service_worker/service_worker_container_host.h index 2378d100..a68dd80 100644 --- a/content/browser/service_worker/service_worker_container_host.h +++ b/content/browser/service_worker/service_worker_container_host.h
@@ -680,8 +680,8 @@ using ServiceWorkerRegistrationMap = std::map<size_t, scoped_refptr<ServiceWorkerRegistration>>; // Contains all living registrations whose scope this client's URL starts - // with, used for .ready and claim(). It is empty if - // IsEligibleForServiceWorkerController() is false. See also + // with and whose keys match this client's key, used for .ready and claim(). + // It is empty if IsEligibleForServiceWorkerController() is false. See also // AddMatchingRegistration(). ServiceWorkerRegistrationMap matching_registrations_;
diff --git a/content/browser/service_worker/service_worker_register_job.cc b/content/browser/service_worker/service_worker_register_job.cc index b90a5515..fd709dde 100644 --- a/content/browser/service_worker/service_worker_register_job.cc +++ b/content/browser/service_worker/service_worker_register_job.cc
@@ -848,7 +848,8 @@ !it->IsAtEnd(); it->Advance()) { ServiceWorkerContainerHost* container_host = it->GetContainerHost(); DCHECK(container_host->IsContainerForClient()); - if (!blink::ServiceWorkerScopeMatches( + if (container_host->key() != registration->key() || + !blink::ServiceWorkerScopeMatches( registration->scope(), container_host->GetUrlForScopeMatch())) { continue; }
diff --git a/content/browser/storage_partition_impl.cc b/content/browser/storage_partition_impl.cc index 0740b988..3fb3b4a 100644 --- a/content/browser/storage_partition_impl.cc +++ b/content/browser/storage_partition_impl.cc
@@ -31,7 +31,7 @@ #include "build/build_config.h" #include "build/chromeos_buildflags.h" #include "components/leveldb_proto/public/proto_database_provider.h" -#include "components/services/storage/public/cpp/buckets/bucket_info.h" +#include "components/services/storage/public/cpp/buckets/bucket_locator.h" #include "components/services/storage/public/cpp/constants.h" #include "components/services/storage/public/cpp/filesystem/filesystem_impl.h" #include "components/services/storage/public/mojom/filesystem/directory.mojom.h" @@ -257,7 +257,7 @@ } } -void OnQuotaManagedBucketDeleted(const storage::BucketInfo& bucket, +void OnQuotaManagedBucketDeleted(const storage::BucketLocator& bucket, size_t* deletion_task_count, base::OnceClosure callback, blink::mojom::QuotaStatusCode status) { @@ -265,9 +265,10 @@ DCHECK_GT(*deletion_task_count, 0u); if (status != blink::mojom::QuotaStatusCode::kOk) { DLOG(ERROR) << "Couldn't remove data type " << static_cast<int>(bucket.type) - << " for bucket " << bucket.name << " with storage key " - << bucket.storage_key.GetDebugString() << " and bucket id " - << bucket.id << ". Status: " << static_cast<int>(status); + << " for bucket with storage key " + << bucket.storage_key.GetDebugString() << " is_default " + << bucket.is_default << " and bucket id " << bucket.id + << ". Status: " << static_cast<int>(status); } (*deletion_task_count)--; @@ -893,7 +894,7 @@ StoragePartition::OriginMatcherFunction origin_matcher, bool perform_storage_cleanup, base::OnceClosure callback, - const std::set<storage::BucketInfo>& buckets, + const std::set<storage::BucketLocator>& buckets, blink::mojom::StorageType quota_storage_type); private: @@ -2208,7 +2209,7 @@ StoragePartition::OriginMatcherFunction origin_matcher, bool perform_storage_cleanup, base::OnceClosure callback, - const std::set<storage::BucketInfo>& buckets, + const std::set<storage::BucketLocator>& buckets, blink::mojom::StorageType quota_storage_type) { // The QuotaManager manages all storage other than cookies, LocalStorage, // and SessionStorage. This loop wipes out most HTML5 storage for the given
diff --git a/content/browser/webrtc/resources/peer_connection_update_table.js b/content/browser/webrtc/resources/peer_connection_update_table.js index 33ad19b9..688e194 100644 --- a/content/browser/webrtc/resources/peer_connection_update_table.js +++ b/content/browser/webrtc/resources/peer_connection_update_table.js
@@ -4,6 +4,7 @@ import {$} from 'chrome://resources/js/util.m.js'; +const MAX_NUMBER_OF_STATE_CHANGES_DISPLAYED = 10; /** * The data of a peer connection update. * @param {number} pid The id of the renderer. @@ -101,42 +102,6 @@ return; } - if (update.type === 'onIceCandidate' || update.type === 'addIceCandidate') { - // extract ICE candidate type from the field following typ. - const candidateType = update.value.match(/(?: typ )(host|srflx|relay)/); - if (candidateType) { - type += ' (' + candidateType[1] + ')'; - } - } else if ( - update.type === 'createOfferOnSuccess' || - update.type === 'createAnswerOnSuccess') { - this.setLastOfferAnswer_(tableElement, update); - } else if (update.type === 'setLocalDescription') { - if (update.value !== this.getLastOfferAnswer_(tableElement)) { - type += ' (munged)'; - } - } else if (update.type === 'setConfiguration') { - // Update the configuration that is displayed at the top. - peerConnectionElement.firstChild.children[2].textContent = update.value; - } - - const summaryItem = $('summary-template').content.cloneNode(true); - const summary = summaryItem.querySelector('summary'); - summary.textContent = type; - row.appendChild(summaryItem); - - const valueContainer = document.createElement('pre'); - const details = row.cells[1].childNodes[0]; - details.appendChild(valueContainer); - - // Highlight ICE failures and failure callbacks. - if ((update.type === 'iceConnectionStateChange' && - update.value === 'ICEConnectionStateFailed') || - update.type.indexOf('OnFailure') !== -1 || - update.type === 'addIceCandidateFailed') { - valueContainer.parentElement.classList.add('update-log-failure'); - } - let {value} = update; // map internal names and values to names and events from the // specification. This is a display change which shall not @@ -171,6 +136,57 @@ value; } + if (update.type === 'onIceCandidate' || update.type === 'addIceCandidate') { + // extract ICE candidate type from the field following typ. + const candidateType = update.value.match(/(?: typ )(host|srflx|relay)/); + if (candidateType) { + type += ' (' + candidateType[1] + ')'; + } + } else if ( + update.type === 'createOfferOnSuccess' || + update.type === 'createAnswerOnSuccess') { + this.setLastOfferAnswer_(tableElement, update); + } else if (update.type === 'setLocalDescription') { + if (update.value !== this.getLastOfferAnswer_(tableElement)) { + type += ' (munged)'; + } + } else if (update.type === 'setConfiguration') { + // Update the configuration that is displayed at the top. + peerConnectionElement.firstChild.children[2].textContent = update.value; + } else if (['iceConnectionStateChange', 'connectionStateChange', + 'signalingStateChange'].includes(update.type)) { + const fieldName = { + 'iceConnectionStateChange' : 'iceconnectionstate', + 'connectionStateChange' : 'connectionstate', + 'signalingStateChange' : 'signalingstate', + }[update.type]; + const el = peerConnectionElement.getElementsByClassName(fieldName)[0]; + const numberOfEvents = el.textContent.split(' => ').length; + if (numberOfEvents < MAX_NUMBER_OF_STATE_CHANGES_DISPLAYED) { + el.textContent += ' => ' + value; + } else if (numberOfEvents === MAX_NUMBER_OF_STATE_CHANGES_DISPLAYED) { + el.textContent += ' ...'; + } + } + + const summaryItem = $('summary-template').content.cloneNode(true); + const summary = summaryItem.querySelector('summary'); + summary.textContent = type; + row.appendChild(summaryItem); + + const valueContainer = document.createElement('pre'); + const details = row.cells[1].childNodes[0]; + details.appendChild(valueContainer); + + // Highlight ICE failures and failure callbacks. + if ((update.type === 'iceConnectionStateChange' && + update.value === 'ICEConnectionStateFailed') || + update.type.indexOf('OnFailure') !== -1 || + update.type === 'addIceCandidateFailed') { + valueContainer.parentElement.classList.add('update-log-failure'); + } + + // RTCSessionDescription is serialized as 'type: <type>, sdp:' if (update.value.indexOf(', sdp:') !== -1) { const [type, sdp] = update.value.substr(6).split(', sdp: ');
diff --git a/content/browser/webrtc/resources/webrtc_internals.js b/content/browser/webrtc/resources/webrtc_internals.js index 1ea6d3f..341edb51 100644 --- a/content/browser/webrtc/resources/webrtc_internals.js +++ b/content/browser/webrtc/resources/webrtc_internals.js
@@ -374,6 +374,21 @@ } peerConnectionElement.appendChild(deprecationNotices); + const iceConnectionStates = document.createElement('div'); + iceConnectionStates.textContent = 'ICE connection state: new'; + iceConnectionStates.className = 'iceconnectionstate'; + peerConnectionElement.appendChild(iceConnectionStates); + + const connectionStates = document.createElement('div'); + connectionStates.textContent = 'Connection state: new'; + connectionStates.className = 'connectionstate'; + peerConnectionElement.appendChild(connectionStates); + + const signalingStates = document.createElement('div'); + signalingStates.textContent = 'Signaling state: new'; + signalingStates.className = 'signalingstate'; + peerConnectionElement.appendChild(signalingStates); + return peerConnectionElement; }
diff --git a/content/browser/webui/content_web_ui_controller_factory.cc b/content/browser/webui/content_web_ui_controller_factory.cc index daf6c25..349e128 100644 --- a/content/browser/webui/content_web_ui_controller_factory.cc +++ b/content/browser/webui/content_web_ui_controller_factory.cc
@@ -6,7 +6,7 @@ #include "build/build_config.h" #include "content/browser/appcache/appcache_internals_ui.h" -#include "content/browser/attribution_reporting/conversion_internals_ui.h" +#include "content/browser/attribution_reporting/attribution_internals_ui.h" #include "content/browser/gpu/gpu_internals_ui.h" #include "content/browser/indexed_db/indexed_db_internals_ui.h" #include "content/browser/media/media_internals_ui.h" @@ -46,7 +46,7 @@ url.host_piece() == kChromeUINetworkErrorsListingHost || url.host_piece() == kChromeUIPrerenderInternalsHost || url.host_piece() == kChromeUIProcessInternalsHost || - url.host_piece() == kChromeUIConversionInternalsHost || + url.host_piece() == kChromeUIAttributionInternalsHost || url.host_piece() == kChromeUIUkmHost) { return const_cast<ContentWebUIControllerFactory*>(this); } @@ -87,8 +87,8 @@ return std::make_unique<PrerenderInternalsUI>(web_ui); if (url.host_piece() == kChromeUIProcessInternalsHost) return std::make_unique<ProcessInternalsUI>(web_ui); - if (url.host_piece() == kChromeUIConversionInternalsHost) - return std::make_unique<ConversionInternalsUI>(web_ui); + if (url.host_piece() == kChromeUIAttributionInternalsHost) + return std::make_unique<AttributionInternalsUI>(web_ui); if (url.host_piece() == kChromeUIUkmHost) return std::make_unique<UkmInternalsUI>(web_ui); if (url.host_piece() == kChromeUIMediaInternalsHost) {
diff --git a/content/browser/worker_host/dedicated_worker_host.cc b/content/browser/worker_host/dedicated_worker_host.cc index a396957..99e67ee 100644 --- a/content/browser/worker_host/dedicated_worker_host.cc +++ b/content/browser/worker_host/dedicated_worker_host.cc
@@ -722,7 +722,8 @@ return; if (!blink::ServiceWorkerScopeMatches(container_host->controller()->scope(), - script_url)) { + script_url) || + container_host->key() != storage_key_) { // Count the number of dedicated workers that 1) are controlled by a service // worker that is inherited from a controlled document, and 2) will not be // controlled by that service worker after PlzDedicatedWorker is enabled. @@ -775,7 +776,8 @@ // one of service workers registered for the origin. The scope matched // service worker may be different from the one that controls the ancestor // frame. - if (blink::ServiceWorkerScopeMatches(registration->scope(), script_url)) + if (blink::ServiceWorkerScopeMatches(registration->scope(), script_url) && + registration->key() == storage_key_) return; }
diff --git a/content/browser/worker_host/shared_worker_host_unittest.cc b/content/browser/worker_host/shared_worker_host_unittest.cc index bb03db51..3d77662 100644 --- a/content/browser/worker_host/shared_worker_host_unittest.cc +++ b/content/browser/worker_host/shared_worker_host_unittest.cc
@@ -113,8 +113,6 @@ mojo::PendingRemote<network::mojom::URLLoaderFactory> loader_factory_remote = network::NotImplementedURLLoaderFactory::Create(); - subresource_loader_params->pending_appcache_loader_factory = - std::move(loader_factory_remote); // Set up for service worker. auto service_worker_handle =
diff --git a/content/browser/worker_host/worker_script_fetcher.cc b/content/browser/worker_host/worker_script_fetcher.cc index f635246d..c00b61c 100644 --- a/content/browser/worker_host/worker_script_fetcher.cc +++ b/content/browser/worker_host/worker_script_fetcher.cc
@@ -114,13 +114,6 @@ bool success) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - // If a URLLoaderFactory for AppCache is supplied, use that. - if (subresource_loader_params && - subresource_loader_params->pending_appcache_loader_factory) { - subresource_loader_factories->pending_appcache_factory() = - std::move(subresource_loader_params->pending_appcache_loader_factory); - } - // Prepare the controller service worker info to pass to the renderer. blink::mojom::ControllerServiceWorkerInfoPtr controller; base::WeakPtr<ServiceWorkerObjectHost> controller_service_worker_object_host;
diff --git a/content/dev_ui_content_resources.grd b/content/dev_ui_content_resources.grd index b9c7b262..21a8da02 100644 --- a/content/dev_ui_content_resources.grd +++ b/content/dev_ui_content_resources.grd
@@ -18,10 +18,10 @@ <include name="IDR_APPCACHE_INTERNALS_HTML" file="browser/resources/appcache/appcache_internals.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" /> <include name="IDR_APPCACHE_INTERNALS_JS" file="browser/resources/appcache/appcache_internals.js" flattenhtml="false" type="BINDATA" /> <include name="IDR_APPCACHE_INTERNALS_CSS" file="browser/resources/appcache/appcache_internals.css" type="BINDATA" /> - <include name="IDR_CONVERSION_INTERNALS_HTML" file="browser/resources/attribution_reporting/conversion_internals.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" /> - <include name="IDR_CONVERSION_INTERNALS_JS" file="browser/resources/attribution_reporting/conversion_internals.js" type="BINDATA" /> - <include name="IDR_CONVERSION_INTERNALS_CSS" file="browser/resources/attribution_reporting/conversion_internals.css" type="BINDATA" /> - <include name="IDR_CONVERSION_INTERNALS_MOJOM_JS" file="${root_gen_dir}/mojom-webui/content/browser/attribution_reporting/conversion_internals.mojom-webui.js" use_base_dir="false" type="BINDATA" /> + <include name="IDR_ATTRIBUTION_INTERNALS_HTML" file="browser/resources/attribution_reporting/attribution_internals.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" /> + <include name="IDR_ATTRIBUTION_INTERNALS_JS" file="browser/resources/attribution_reporting/attribution_internals.js" type="BINDATA" /> + <include name="IDR_ATTRIBUTION_INTERNALS_CSS" file="browser/resources/attribution_reporting/attribution_internals.css" type="BINDATA" /> + <include name="IDR_ATTRIBUTION_INTERNALS_MOJOM_JS" file="${root_gen_dir}/mojom-webui/content/browser/attribution_reporting/attribution_internals.mojom-webui.js" use_base_dir="false" type="BINDATA" /> <include name="IDR_GPU_BROWSER_BRIDGE_JS" file="browser/resources/gpu/browser_bridge.js" type="BINDATA" /> <include name="IDR_GPU_INFO_VIEW_JS" file="browser/resources/gpu/info_view.js" type="BINDATA" /> <include name="IDR_GPU_INTERNALS_HTML" file="browser/resources/gpu/gpu_internals.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" />
diff --git a/content/public/android/java/src/org/chromium/content/browser/ChildProcessLauncherHelperImpl.java b/content/public/android/java/src/org/chromium/content/browser/ChildProcessLauncherHelperImpl.java index 903f72c..366eab47 100644 --- a/content/public/android/java/src/org/chromium/content/browser/ChildProcessLauncherHelperImpl.java +++ b/content/public/android/java/src/org/chromium/content/browser/ChildProcessLauncherHelperImpl.java
@@ -251,6 +251,14 @@ Log.d(TAG, "Encountered the first usable RELRO bundle."); sZygotePid = connection.getZygotePid(); sZygoteBundle = zygoteBundle; + + // Use the RELRO FD in the current process. Some nontrivial CPU cycles are consumed because + // it needs an mmap+memcmp(5 megs)+mmap+munmap. This happens on the process launcher thread, + // will work correctly on any thread. + LibraryLoader.getInstance().getMediator().takeSharedRelrosFromBundle(zygoteBundle); + + // Use the RELRO FD for all processes launched up to now. Non-blocking 'oneway' IPCs are + // used. The CPU time costs in the child process are the same. sendPreviouslySeenZygoteBundleToExistingConnections(connection.getPid()); }
diff --git a/content/public/common/url_constants.cc b/content/public/common/url_constants.cc index efe3bd7..dfc5dc4 100644 --- a/content/public/common/url_constants.cc +++ b/content/public/common/url_constants.cc
@@ -26,10 +26,10 @@ const char kGoogleChromeScheme[] = "googlechrome"; const char kChromeUIAppCacheInternalsHost[] = "appcache-internals"; +const char kChromeUIAttributionInternalsHost[] = "conversion-internals"; const char kChromeUIIndexedDBInternalsHost[] = "indexeddb-internals"; const char kChromeUIBlobInternalsHost[] = "blob-internals"; const char kChromeUIBrowserCrashHost[] = "inducebrowsercrashforrealz"; -const char kChromeUIConversionInternalsHost[] = "conversion-internals"; const char kChromeUIDinoHost[] = "dino"; const char kChromeUIGpuHost[] = "gpu"; const char kChromeUIHistogramHost[] = "histograms";
diff --git a/content/public/common/url_constants.h b/content/public/common/url_constants.h index f3f67fb8..e59c9a7 100644 --- a/content/public/common/url_constants.h +++ b/content/public/common/url_constants.h
@@ -36,9 +36,9 @@ CONTENT_EXPORT extern const char kChromeUIAccessibilityHost[]; CONTENT_EXPORT extern const char kChromeUIAppCacheInternalsHost[]; +CONTENT_EXPORT extern const char kChromeUIAttributionInternalsHost[]; CONTENT_EXPORT extern const char kChromeUIBlobInternalsHost[]; CONTENT_EXPORT extern const char kChromeUIBrowserCrashHost[]; -CONTENT_EXPORT extern const char kChromeUIConversionInternalsHost[]; CONTENT_EXPORT extern const char kChromeUIDinoHost[]; CONTENT_EXPORT extern const char kChromeUIGpuHost[]; CONTENT_EXPORT extern const char kChromeUIHistogramHost[];
diff --git a/content/public/test/dump_accessibility_test_helper.cc b/content/public/test/dump_accessibility_test_helper.cc index c2e0781..e385a99c 100644 --- a/content/public/test/dump_accessibility_test_helper.cc +++ b/content/public/test/dump_accessibility_test_helper.cc
@@ -358,6 +358,14 @@ FILE_PATH_LITERAL(".txt"); } #endif +#if defined(OS_CHROMEOS) + if (expectation_type_ == "blink") { + FilePath::StringType suffix; + if (!expectations_qualifier.empty()) + suffix = FILE_PATH_LITERAL("-") + expectations_qualifier; + return suffix + FILE_PATH_LITERAL("-expected-blink-cros.txt"); + } +#endif return FILE_PATH_LITERAL(""); }
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc index 0117157..c70c1a4 100644 --- a/content/renderer/render_frame_impl.cc +++ b/content/renderer/render_frame_impl.cc
@@ -2887,7 +2887,7 @@ this, std::move(container_info), std::move(controller_service_worker_info), network::SharedURLLoaderFactory::Create( - new_loader_factories->CloneWithoutAppCacheFactory())); + new_loader_factories->Clone())); } WebString subresource_filter = navigation_params->response.HttpHeaderField( @@ -3363,7 +3363,7 @@ blink::WebDedicatedOrSharedWorkerFetchContext::Create( provider->context(), GetWebView()->GetRendererPreferences(), std::move(watcher_receiver), GetLoaderFactoryBundle()->Clone(), - GetLoaderFactoryBundle()->CloneWithoutAppCacheFactory(), + GetLoaderFactoryBundle()->Clone(), /*pending_subresource_loader_updater=*/mojo::NullReceiver(), web_cors_exempt_header_list, std::move(pending_resource_load_info_notifier));
diff --git a/content/renderer/worker/dedicated_worker_host_factory_client.cc b/content/renderer/worker/dedicated_worker_host_factory_client.cc index d2197eed..c322ecf 100644 --- a/content/renderer/worker/dedicated_worker_host_factory_client.cc +++ b/content/renderer/worker/dedicated_worker_host_factory_client.cc
@@ -83,8 +83,7 @@ ->CloneForNestedWorker( service_worker_provider_context_.get(), subresource_loader_factory_bundle_->Clone(), - subresource_loader_factory_bundle_ - ->CloneWithoutAppCacheFactory(), + subresource_loader_factory_bundle_->Clone(), std::move(pending_subresource_loader_updater_), std::move(task_runner)); } else { @@ -119,7 +118,7 @@ service_worker_provider_context_.get(), renderer_preference, std::move(watcher_receiver), subresource_loader_factory_bundle_->Clone(), - subresource_loader_factory_bundle_->CloneWithoutAppCacheFactory(), + subresource_loader_factory_bundle_->Clone(), std::move(pending_subresource_loader_updater_), web_cors_exempt_header_list, std::move(pending_resource_load_info_notifier));
diff --git a/content/renderer/worker/embedded_shared_worker_stub.cc b/content/renderer/worker/embedded_shared_worker_stub.cc index ebb5b2c5..5e851e7 100644 --- a/content/renderer/worker/embedded_shared_worker_stub.cc +++ b/content/renderer/worker/embedded_shared_worker_stub.cc
@@ -150,10 +150,9 @@ mojo::PendingReceiver<blink::mojom::RendererPreferenceWatcher> preference_watcher_receiver, const std::vector<std::string>& cors_exempt_header_list) { - // Make the factory used for service worker network fallback (that should - // skip AppCache if it is provided). + // Make the factory used for service worker network fallback. std::unique_ptr<network::PendingSharedURLLoaderFactory> fallback_factory = - subresource_loader_factory_bundle_->CloneWithoutAppCacheFactory(); + subresource_loader_factory_bundle_->Clone(); blink::WebVector<blink::WebString> web_cors_exempt_header_list( cors_exempt_header_list.size());
diff --git a/content/test/data/accessibility/html/input-date-with-popup-open-expected-auralinux.txt b/content/test/data/accessibility/html/input-date-with-popup-open-expected-auralinux.txt index 81c55c17..c8d08ce 100644 --- a/content/test/data/accessibility/html/input-date-with-popup-open-expected-auralinux.txt +++ b/content/test/data/accessibility/html/input-date-with-popup-open-expected-auralinux.txt
@@ -16,11 +16,11 @@ ++++++++++++++[section] ++++++++++++++++[push button] name='Show month selection panel' ++++++++++++++++++[static] name='September 2008' -++++++++++++++++++[document frame] +++++++++++++++++++[image] ++++++++++++++[push button] name='Show previous month' -++++++++++++++++[document frame] +++++++++++++++++[image] ++++++++++++++[push button] name='Show next month' -++++++++++++++++[document frame] +++++++++++++++++[image] ++++++++++++++[table] cols=7 headers=(NONE); rows=6 headers=(NONE); caption=false; spans=(all: 1x1) ++++++++++++++++[section] ++++++++++++++++++[section]
diff --git a/content/test/data/accessibility/html/input-date-with-popup-open-expected-blink.txt b/content/test/data/accessibility/html/input-date-with-popup-open-expected-blink.txt index f064a28..bdb6069 100644 --- a/content/test/data/accessibility/html/input-date-with-popup-open-expected-blink.txt +++ b/content/test/data/accessibility/html/input-date-with-popup-open-expected-blink.txt
@@ -27,11 +27,11 @@ ++++++++++++++++++++genericContainer ++++++++++++++++++++++button name='Show month selection panel' ++++++++++++++++++++++++staticText -++++++++++++++++++++++++svgRoot +++++++++++++++++++++++++image ++++++++++++++++++++button name='Show previous month' -++++++++++++++++++++++svgRoot +++++++++++++++++++++++image ++++++++++++++++++++button name='Show next month' -++++++++++++++++++++++svgRoot +++++++++++++++++++++++image ++++++++++++++++++grid activedescendantId=cell ++++++++++++++++++++genericContainer ++++++++++++++++++++++genericContainer
diff --git a/content/test/data/accessibility/html/input-date-with-popup-open-expected-mac.txt b/content/test/data/accessibility/html/input-date-with-popup-open-expected-mac.txt index 3077f35..caa575b 100644 --- a/content/test/data/accessibility/html/input-date-with-popup-open-expected-mac.txt +++ b/content/test/data/accessibility/html/input-date-with-popup-open-expected-mac.txt
@@ -16,11 +16,11 @@ ++++++++++++++AXGroup AXRoleDescription='group' ++++++++++++++++AXButton AXDescription='Show month selection panel' AXRoleDescription='button' ++++++++++++++++++AXStaticText AXRoleDescription='text' AXValue='September 2008' -++++++++++++++++++AXGroup AXRoleDescription='group' +++++++++++++++++++AXImage AXRoleDescription='image' ++++++++++++++AXButton AXDescription='Show previous month' AXRoleDescription='button' -++++++++++++++++AXGroup +++++++++++++++++AXImage ++++++++++++++AXButton AXDescription='Show next month' AXRoleDescription='button' -++++++++++++++++AXGroup +++++++++++++++++AXImage ++++++++++++++AXTable AXRoleDescription='table' ++++++++++++++++AXGroup AXRoleDescription='group' ++++++++++++++++++AXGroup AXRoleDescription='group'
diff --git a/content/test/data/accessibility/html/input-date-with-popup-open-expected-win.txt b/content/test/data/accessibility/html/input-date-with-popup-open-expected-win.txt index 42fbda0..e01204a2d 100644 --- a/content/test/data/accessibility/html/input-date-with-popup-open-expected-win.txt +++ b/content/test/data/accessibility/html/input-date-with-popup-open-expected-win.txt
@@ -16,11 +16,11 @@ ++++++++++++++IA2_ROLE_SECTION ia2_hypertext='<obj0>' ++++++++++++++++ROLE_SYSTEM_PUSHBUTTON name='Show month selection panel' FOCUSABLE ++++++++++++++++++ROLE_SYSTEM_STATICTEXT -++++++++++++++++++ROLE_SYSTEM_GRAPHIC +++++++++++++++++++ROLE_SYSTEM_GRAPHIC READONLY ++++++++++++++ROLE_SYSTEM_PUSHBUTTON name='Show previous month' FOCUSABLE ia2_hypertext='<obj0>' -++++++++++++++++ROLE_SYSTEM_GRAPHIC +++++++++++++++++ROLE_SYSTEM_GRAPHIC READONLY ++++++++++++++ROLE_SYSTEM_PUSHBUTTON name='Show next month' FOCUSABLE ia2_hypertext='<obj0>' -++++++++++++++++ROLE_SYSTEM_GRAPHIC +++++++++++++++++ROLE_SYSTEM_GRAPHIC READONLY ++++++++++++++ROLE_SYSTEM_TABLE FOCUSABLE ia2_hypertext='<obj0><obj1><obj2><obj3>' ++++++++++++++++IA2_ROLE_SECTION ia2_hypertext='<obj0><obj1><obj2><obj3><obj4><obj5><obj6>' ++++++++++++++++++IA2_ROLE_SECTION ia2_hypertext='Su'
diff --git a/content/test/data/accessibility/html/svg-and-math-elements-expected-auralinux.txt b/content/test/data/accessibility/html/svg-and-math-elements-expected-auralinux.txt index 5331e41bb..c70e2b6 100644 --- a/content/test/data/accessibility/html/svg-and-math-elements-expected-auralinux.txt +++ b/content/test/data/accessibility/html/svg-and-math-elements-expected-auralinux.txt
@@ -1,6 +1,6 @@ [document web] tag:#document ++[section] class:svg-container tag:div -++++[document frame] name='original' tag:svg +++++[image] name='original' tag:svg ++++[section] name='created' class:html-namespace tag:svg ++++[section] name='created' class:custom-namespace tag:svg ++[section] class:math-container tag:div
diff --git a/content/test/data/accessibility/html/svg-and-math-elements-expected-blink.txt b/content/test/data/accessibility/html/svg-and-math-elements-expected-blink.txt index 6ffd49f..78affaf 100644 --- a/content/test/data/accessibility/html/svg-and-math-elements-expected-blink.txt +++ b/content/test/data/accessibility/html/svg-and-math-elements-expected-blink.txt
@@ -2,7 +2,7 @@ ++genericContainer ignored htmlTag='html' ++++genericContainer ignored htmlTag='body' ++++++genericContainer className='svg-container' htmlTag='div' -++++++++svgRoot htmlTag='svg' name='original' +++++++++image htmlTag='svg' name='original' ++++++++genericContainer className='html-namespace' htmlTag='svg' name='created' ++++++++genericContainer className='custom-namespace' htmlTag='svg' name='created' ++++++genericContainer className='math-container' htmlTag='div'
diff --git a/content/test/data/accessibility/html/svg-child-of-button-expected-auralinux.txt b/content/test/data/accessibility/html/svg-child-of-button-expected-auralinux.txt index 03788b2..1f8660d0 100644 --- a/content/test/data/accessibility/html/svg-child-of-button-expected-auralinux.txt +++ b/content/test/data/accessibility/html/svg-child-of-button-expected-auralinux.txt
@@ -1,4 +1,4 @@ [document web] tag:#document ++[section] tag:body ++++[push button] name='Search' tag:button -++++++[document frame] class:button-child-icon tag:svg +++++++[image] class:button-child-icon tag:svg
diff --git a/content/test/data/accessibility/html/svg-child-of-button-expected-blink.txt b/content/test/data/accessibility/html/svg-child-of-button-expected-blink.txt index 3898396..d682ab56 100644 --- a/content/test/data/accessibility/html/svg-child-of-button-expected-blink.txt +++ b/content/test/data/accessibility/html/svg-child-of-button-expected-blink.txt
@@ -2,4 +2,4 @@ ++genericContainer ignored htmlTag='html' ++++genericContainer htmlTag='body' ++++++button htmlTag='button' name='Search' -++++++++svgRoot className='button-child-icon' htmlTag='svg' +++++++++image className='button-child-icon' htmlTag='svg'
diff --git a/content/test/data/accessibility/html/svg-elements-not-mapped-expected-auralinux.txt b/content/test/data/accessibility/html/svg-elements-not-mapped-expected-auralinux.txt index 74aa0fc..66f79e82 100644 --- a/content/test/data/accessibility/html/svg-elements-not-mapped-expected-auralinux.txt +++ b/content/test/data/accessibility/html/svg-elements-not-mapped-expected-auralinux.txt
@@ -1,45 +1,45 @@ [document web] tag:#document ++[section] tag:body -++++[document frame] name='animate should not be exposed' tag:svg -++++[document frame] name='animateMotion should not be exposed' tag:svg -++++[document frame] name='animateTransform should not be exposed' tag:svg -++++[document frame] name='clipPath should not be exposed' tag:svg -++++[document frame] name='cursor should not be exposed' tag:svg -++++[document frame] name='defs should not be exposed' tag:svg -++++[document frame] name='discard should not be exposed' tag:svg -++++[document frame] name='filter and filter effect elements should not be exposed' tag:svg -++++[document frame] name='hatch should not be exposed' tag:svg -++++[document frame] name='hatchpath should not be exposed' tag:svg -++++[document frame] name='image which lacks criteria for inclusion should not be exposed' tag:svg -++++[document frame] name='linearGradient should not be exposed' tag:svg -++++[document frame] name='marker should not be exposed' tag:svg -++++[document frame] name='mask should not be exposed' tag:svg -++++[document frame] name='metadata should not be exposed' tag:svg -++++[document frame] name='mpath should not be exposed' tag:svg -++++[document frame] name='pattern should not be exposed' tag:svg -++++[document frame] name='radialGradient should not be exposed' tag:svg -++++[document frame] name='solidColor should not be exposed' tag:svg -++++[document frame] name='stop should not be exposed' tag:svg +++++[image] name='animate should not be exposed' tag:svg +++++[image] name='animateMotion should not be exposed' tag:svg +++++[image] name='animateTransform should not be exposed' tag:svg +++++[image] name='clipPath should not be exposed' tag:svg +++++[image] name='cursor should not be exposed' tag:svg +++++[image] name='defs should not be exposed' tag:svg +++++[image] name='discard should not be exposed' tag:svg +++++[image] name='filter and filter effect elements should not be exposed' tag:svg +++++[image] name='hatch should not be exposed' tag:svg +++++[image] name='hatchpath should not be exposed' tag:svg +++++[image] name='image which lacks criteria for inclusion should not be exposed' tag:svg +++++[image] name='linearGradient should not be exposed' tag:svg +++++[image] name='marker should not be exposed' tag:svg +++++[image] name='mask should not be exposed' tag:svg +++++[image] name='metadata should not be exposed' tag:svg +++++[image] name='mpath should not be exposed' tag:svg +++++[image] name='pattern should not be exposed' tag:svg +++++[image] name='radialGradient should not be exposed' tag:svg +++++[image] name='solidColor should not be exposed' tag:svg +++++[image] name='stop should not be exposed' tag:svg ++++[document frame] name='style and set should not be exposed' tag:svg ++++++[image] id:clickable tag:rect ++++[document frame] name='switch should not be exposed' tag:svg ++++++[section] tag:text ++++++++[static] name='Hey!' -++++[document frame] name='view should not be exposed' tag:svg -++++[document frame] name='desc should not be exposed as accessible object' tag:svg -++++[document frame] name='title should not be exposed as accessible object' tag:svg -++++[document frame] name='circle which lacks criteria for inclusion should not be exposed' tag:svg -++++[document frame] name='ellipse which lacks criteria for inclusion should not be exposed' tag:svg +++++[image] name='view should not be exposed' tag:svg +++++[image] name='desc should not be exposed as accessible object' tag:svg +++++[image] name='title should not be exposed as accessible object' tag:svg +++++[image] name='circle which lacks criteria for inclusion should not be exposed' tag:svg +++++[image] name='ellipse which lacks criteria for inclusion should not be exposed' tag:svg ++++[document frame] name='foreignObject which lacks criteria for inclusion should not be exposed' tag:svg ++++++[paragraph] tag:p ++++++++[static] name='Hello world' -++++[document frame] name='group which lacks criteria for inclusion should not be exposed' tag:svg -++++[document frame] name='line which lacks criteria for inclusion should not be exposed' tag:svg -++++[document frame] name='path which lacks criteria for inclusion should not be exposed' tag:svg -++++[document frame] name='polygon which lacks criteria for inclusion should not be exposed' tag:svg -++++[document frame] name='polyline which lacks criteria for inclusion should not be exposed' tag:svg -++++[document frame] name='rect which lacks criteria for inclusion should not be exposed' tag:svg -++++[document frame] name='symbol which lacks criteria for inclusion should not be exposed' tag:svg +++++[image] name='group which lacks criteria for inclusion should not be exposed' tag:svg +++++[image] name='line which lacks criteria for inclusion should not be exposed' tag:svg +++++[image] name='path which lacks criteria for inclusion should not be exposed' tag:svg +++++[image] name='polygon which lacks criteria for inclusion should not be exposed' tag:svg +++++[image] name='polyline which lacks criteria for inclusion should not be exposed' tag:svg +++++[image] name='rect which lacks criteria for inclusion should not be exposed' tag:svg +++++[image] name='symbol which lacks criteria for inclusion should not be exposed' tag:svg ++++[document frame] name='textPath which lacks criteria for inclusion should not be exposed' tag:svg ++++++[section] tag:text ++++++++[static] name='Hello'
diff --git a/content/test/data/accessibility/html/svg-elements-not-mapped-expected-blink-cros.txt b/content/test/data/accessibility/html/svg-elements-not-mapped-expected-blink-cros.txt new file mode 100644 index 0000000..bfc13f0 --- /dev/null +++ b/content/test/data/accessibility/html/svg-elements-not-mapped-expected-blink-cros.txt
@@ -0,0 +1,69 @@ +rootWebArea htmlTag='#document' +++genericContainer ignored htmlTag='html' +++++genericContainer htmlTag='body' +++++++image htmlTag='svg' name='animate should not be exposed' +++++++image htmlTag='svg' name='animateMotion should not be exposed' +++++++image htmlTag='svg' name='animateTransform should not be exposed' +++++++image htmlTag='svg' name='clipPath should not be exposed' +++++++image htmlTag='svg' name='cursor should not be exposed' +++++++image htmlTag='svg' name='defs should not be exposed' +++++++++genericContainer ignored invisible htmlTag='solidcolor' +++++++image htmlTag='svg' name='discard should not be exposed' +++++++svgRoot htmlTag='svg' name='filter and filter effect elements should not be exposed' +++++++++group htmlTag='g' +++++++++++group htmlTag='g' +++++++image htmlTag='svg' name='hatch should not be exposed' +++++++image htmlTag='svg' name='hatchpath should not be exposed' +++++++image htmlTag='svg' name='image which lacks criteria for inclusion should not be exposed' +++++++image htmlTag='svg' name='linearGradient should not be exposed' +++++++image htmlTag='svg' name='marker should not be exposed' +++++++image htmlTag='svg' name='mask should not be exposed' +++++++image htmlTag='svg' name='metadata should not be exposed' +++++++image htmlTag='svg' name='mpath should not be exposed' +++++++image htmlTag='svg' name='pattern should not be exposed' +++++++image htmlTag='svg' name='radialGradient should not be exposed' +++++++image htmlTag='svg' name='solidColor should not be exposed' +++++++image htmlTag='svg' name='stop should not be exposed' +++++++svgRoot htmlTag='svg' name='style and set should not be exposed' +++++++++graphicsSymbol htmlTag='rect' +++++++svgRoot htmlTag='svg' name='switch should not be exposed' +++++++++genericContainer htmlTag='text' +++++++++++staticText name='Hey!' +++++++++++++inlineTextBox name='Hey!' +++++++image htmlTag='svg' name='view should not be exposed' +++++++++genericContainer ignored invisible htmlTag='view' +++++++++genericContainer ignored invisible htmlTag='view' +++++++image htmlTag='svg' name='desc should not be exposed as accessible object' +++++++image htmlTag='svg' name='title should not be exposed as accessible object' +++++++image htmlTag='svg' name='circle which lacks criteria for inclusion should not be exposed' +++++++image htmlTag='svg' name='ellipse which lacks criteria for inclusion should not be exposed' +++++++svgRoot htmlTag='svg' name='foreignObject which lacks criteria for inclusion should not be exposed' +++++++++group ignored htmlTag='foreignobject' +++++++++++paragraph htmlTag='p' +++++++++++++staticText name='Hello world' +++++++++++++++inlineTextBox name='Hello ' +++++++++++++++inlineTextBox name='world' +++++++svgRoot htmlTag='svg' name='group which lacks criteria for inclusion should not be exposed' +++++++++group htmlTag='g' +++++++image htmlTag='svg' name='line which lacks criteria for inclusion should not be exposed' +++++++image htmlTag='svg' name='path which lacks criteria for inclusion should not be exposed' +++++++image htmlTag='svg' name='polygon which lacks criteria for inclusion should not be exposed' +++++++image htmlTag='svg' name='polyline which lacks criteria for inclusion should not be exposed' +++++++image htmlTag='svg' name='rect which lacks criteria for inclusion should not be exposed' +++++++image htmlTag='svg' name='symbol which lacks criteria for inclusion should not be exposed' +++++++svgRoot htmlTag='svg' name='textPath which lacks criteria for inclusion should not be exposed' +++++++++genericContainer htmlTag='text' +++++++++++staticText name='Hello' +++++++++++++inlineTextBox name='H' +++++++++++++inlineTextBox name='e' +++++++++++++inlineTextBox name='l' +++++++++++++inlineTextBox name='l' +++++++++++++inlineTextBox name='o' +++++++svgRoot htmlTag='svg' name='tspan which lacks criteria for inclusion should not be exposed' +++++++++genericContainer htmlTag='text' +++++++++++staticText name='Hello ' +++++++++++++inlineTextBox name='Hello ' +++++++++++staticText name='world' +++++++++++++inlineTextBox name='world' +++++++++++staticText name='!' +++++++++++++inlineTextBox name='!' \ No newline at end of file
diff --git a/content/test/data/accessibility/html/svg-elements-not-mapped-expected-blink.txt b/content/test/data/accessibility/html/svg-elements-not-mapped-expected-blink.txt index bb61771..06654af 100644 --- a/content/test/data/accessibility/html/svg-elements-not-mapped-expected-blink.txt +++ b/content/test/data/accessibility/html/svg-elements-not-mapped-expected-blink.txt
@@ -1,56 +1,56 @@ rootWebArea htmlTag='#document' -++genericContainer htmlTag='html' +++genericContainer ignored htmlTag='html' ++++genericContainer htmlTag='body' -++++++svgRoot htmlTag='svg' name='animate should not be exposed' -++++++svgRoot htmlTag='svg' name='animateMotion should not be exposed' -++++++svgRoot htmlTag='svg' name='animateTransform should not be exposed' -++++++svgRoot htmlTag='svg' name='clipPath should not be exposed' -++++++svgRoot htmlTag='svg' name='cursor should not be exposed' -++++++svgRoot htmlTag='svg' name='defs should not be exposed' -++++++++genericContainer invisible htmlTag='solidcolor' -++++++svgRoot htmlTag='svg' name='discard should not be exposed' -++++++svgRoot htmlTag='svg' name='filter and filter effect elements should not be exposed' -++++++++group htmlTag='g' -++++++++++group htmlTag='g' -++++++svgRoot htmlTag='svg' name='hatch should not be exposed' -++++++svgRoot htmlTag='svg' name='hatchpath should not be exposed' -++++++svgRoot htmlTag='svg' name='image which lacks criteria for inclusion should not be exposed' -++++++svgRoot htmlTag='svg' name='linearGradient should not be exposed' -++++++svgRoot htmlTag='svg' name='marker should not be exposed' -++++++svgRoot htmlTag='svg' name='mask should not be exposed' -++++++svgRoot htmlTag='svg' name='metadata should not be exposed' -++++++svgRoot htmlTag='svg' name='mpath should not be exposed' -++++++svgRoot htmlTag='svg' name='pattern should not be exposed' -++++++svgRoot htmlTag='svg' name='radialGradient should not be exposed' -++++++svgRoot htmlTag='svg' name='solidColor should not be exposed' -++++++svgRoot htmlTag='svg' name='stop should not be exposed' +++++++image htmlTag='svg' name='animate should not be exposed' +++++++image htmlTag='svg' name='animateMotion should not be exposed' +++++++image htmlTag='svg' name='animateTransform should not be exposed' +++++++image htmlTag='svg' name='clipPath should not be exposed' +++++++image htmlTag='svg' name='cursor should not be exposed' +++++++image htmlTag='svg' name='defs should not be exposed' +++++++++genericContainer ignored invisible htmlTag='solidcolor' +++++++image htmlTag='svg' name='discard should not be exposed' +++++++image htmlTag='svg' name='filter and filter effect elements should not be exposed' +++++++++group ignored htmlTag='g' +++++++++++group ignored htmlTag='g' +++++++image htmlTag='svg' name='hatch should not be exposed' +++++++image htmlTag='svg' name='hatchpath should not be exposed' +++++++image htmlTag='svg' name='image which lacks criteria for inclusion should not be exposed' +++++++image htmlTag='svg' name='linearGradient should not be exposed' +++++++image htmlTag='svg' name='marker should not be exposed' +++++++image htmlTag='svg' name='mask should not be exposed' +++++++image htmlTag='svg' name='metadata should not be exposed' +++++++image htmlTag='svg' name='mpath should not be exposed' +++++++image htmlTag='svg' name='pattern should not be exposed' +++++++image htmlTag='svg' name='radialGradient should not be exposed' +++++++image htmlTag='svg' name='solidColor should not be exposed' +++++++image htmlTag='svg' name='stop should not be exposed' ++++++svgRoot htmlTag='svg' name='style and set should not be exposed' ++++++++graphicsSymbol htmlTag='rect' ++++++svgRoot htmlTag='svg' name='switch should not be exposed' ++++++++genericContainer htmlTag='text' ++++++++++staticText name='Hey!' ++++++++++++inlineTextBox name='Hey!' -++++++svgRoot htmlTag='svg' name='view should not be exposed' -++++++++genericContainer invisible htmlTag='view' -++++++++genericContainer invisible htmlTag='view' -++++++svgRoot htmlTag='svg' name='desc should not be exposed as accessible object' -++++++svgRoot htmlTag='svg' name='title should not be exposed as accessible object' -++++++svgRoot htmlTag='svg' name='circle which lacks criteria for inclusion should not be exposed' -++++++svgRoot htmlTag='svg' name='ellipse which lacks criteria for inclusion should not be exposed' +++++++image htmlTag='svg' name='view should not be exposed' +++++++++genericContainer ignored invisible htmlTag='view' +++++++++genericContainer ignored invisible htmlTag='view' +++++++image htmlTag='svg' name='desc should not be exposed as accessible object' +++++++image htmlTag='svg' name='title should not be exposed as accessible object' +++++++image htmlTag='svg' name='circle which lacks criteria for inclusion should not be exposed' +++++++image htmlTag='svg' name='ellipse which lacks criteria for inclusion should not be exposed' ++++++svgRoot htmlTag='svg' name='foreignObject which lacks criteria for inclusion should not be exposed' -++++++++group htmlTag='foreignobject' +++++++++group ignored htmlTag='foreignobject' ++++++++++paragraph htmlTag='p' ++++++++++++staticText name='Hello world' ++++++++++++++inlineTextBox name='Hello ' ++++++++++++++inlineTextBox name='world' -++++++svgRoot htmlTag='svg' name='group which lacks criteria for inclusion should not be exposed' -++++++++group htmlTag='g' -++++++svgRoot htmlTag='svg' name='line which lacks criteria for inclusion should not be exposed' -++++++svgRoot htmlTag='svg' name='path which lacks criteria for inclusion should not be exposed' -++++++svgRoot htmlTag='svg' name='polygon which lacks criteria for inclusion should not be exposed' -++++++svgRoot htmlTag='svg' name='polyline which lacks criteria for inclusion should not be exposed' -++++++svgRoot htmlTag='svg' name='rect which lacks criteria for inclusion should not be exposed' -++++++svgRoot htmlTag='svg' name='symbol which lacks criteria for inclusion should not be exposed' +++++++image htmlTag='svg' name='group which lacks criteria for inclusion should not be exposed' +++++++++group ignored htmlTag='g' +++++++image htmlTag='svg' name='line which lacks criteria for inclusion should not be exposed' +++++++image htmlTag='svg' name='path which lacks criteria for inclusion should not be exposed' +++++++image htmlTag='svg' name='polygon which lacks criteria for inclusion should not be exposed' +++++++image htmlTag='svg' name='polyline which lacks criteria for inclusion should not be exposed' +++++++image htmlTag='svg' name='rect which lacks criteria for inclusion should not be exposed' +++++++image htmlTag='svg' name='symbol which lacks criteria for inclusion should not be exposed' ++++++svgRoot htmlTag='svg' name='textPath which lacks criteria for inclusion should not be exposed' ++++++++genericContainer htmlTag='text' ++++++++++staticText name='Hello'
diff --git a/content/test/data/accessibility/html/svg-elements-not-mapped.html b/content/test/data/accessibility/html/svg-elements-not-mapped.html index 6432e49..38ccc21 100644 --- a/content/test/data/accessibility/html/svg-elements-not-mapped.html +++ b/content/test/data/accessibility/html/svg-elements-not-mapped.html
@@ -2,9 +2,6 @@ @AURALINUX-ALLOW:id:* @AURALINUX-ALLOW:tag:* @BLINK-ALLOW:htmlTag* - -For compatibility with cros which always includes <g> -@BLINK-DENY:ignored --> <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> <html>
diff --git a/content/test/data/accessibility/html/svg-g-for-cros-expected-blink.txt b/content/test/data/accessibility/html/svg-g-expected-blink-cros.txt similarity index 100% rename from content/test/data/accessibility/html/svg-g-for-cros-expected-blink.txt rename to content/test/data/accessibility/html/svg-g-expected-blink-cros.txt
diff --git a/content/test/data/accessibility/html/svg-g-for-cros.html b/content/test/data/accessibility/html/svg-g-for-cros.html deleted file mode 100644 index a4f8f25..0000000 --- a/content/test/data/accessibility/html/svg-g-for-cros.html +++ /dev/null
@@ -1,19 +0,0 @@ -<!-- -@BLINK-ALLOW:htmlTag='g' ---> -<!DOCTYPE html> -<html> -<body> - -<svg aria-label="svg"> - <g> - <text x="10" y="10" fill="red">Group 1 Text 1</text> - <text x="10" y="100" fill="red">Group 1 Text 2</text> - </g> - <g> - <text x="200" y="10" fill="red">Group 2 Text 1</text> - </g> -</svg> - -</body> -</html>
diff --git a/content/test/data/accessibility/readme.md b/content/test/data/accessibility/readme.md index 8430215d..a9dd0af 100644 --- a/content/test/data/accessibility/readme.md +++ b/content/test/data/accessibility/readme.md
@@ -82,6 +82,8 @@ * `auralinux-trusty` -- expected Linux ATK output (Version Specific Expected File) * `auralinux-xenial` -- expected Linux ATK output (Version Specific Expected File) * `blink` -- representation of internal accessibility tree +* `blink-cros` -- representation of internal accessibility tree + (Version Specific Expected File for Chrome OS and Lacros) * `mac` -- expected Mac NSAccessibility output * `win` -- expected Win IAccessible/IAccessible2 output * `uia-win` -- expected Win UIA output @@ -132,6 +134,13 @@ At the present time there is no version-specific support for Bionic Beaver, which is the current version run on "linux-rel". +The need for a version-specific expectations file on Chrome OS / Lacros is +extremely rare. However, there can be occasional differences in the internal +accessibility tree. For instance, the SVG `g` element is always included +in order to support select-to-speak functionality. If `foo.html` has a +`foo-expected-blink.txt` file which works on all platforms except the Chrome OS +and Lacros bots, create `foo-expected-blink-cros.txt`. + ## Directives Directives allow you to control test flow and test output. The directives are
diff --git a/google_apis/gaia/gaia_constants.cc b/google_apis/gaia/gaia_constants.cc index 8d77b6d1..1713f4b 100644 --- a/google_apis/gaia/gaia_constants.cc +++ b/google_apis/gaia/gaia_constants.cc
@@ -63,10 +63,18 @@ const char kGoogleUserInfoProfile[] = "https://www.googleapis.com/auth/userinfo.profile"; +// OAuth2 scope for access to the parent approval widget. +const char kParentApprovalOAuth2Scope[] = + "https://www.googleapis.com/auth/kids.parentapproval"; + // OAuth2 scope for access to the people API (read-only). const char kPeopleApiReadOnlyOAuth2Scope[] = "https://www.googleapis.com/auth/peopleapi.readonly"; +// OAuth2 scope for access to the programmatic challenge API (read-only). +const char kProgrammaticChallengeOAuth2Scope[] = + "https://www.googleapis.com/auth/accounts.programmaticchallenge"; + // OAuth2 scope for access to the Reauth flow. const char kAccountsReauthOAuth2Scope[] = "https://www.googleapis.com/auth/accounts.reauth";
diff --git a/google_apis/gaia/gaia_constants.h b/google_apis/gaia/gaia_constants.h index 491c23a..e6db05e 100644 --- a/google_apis/gaia/gaia_constants.h +++ b/google_apis/gaia/gaia_constants.h
@@ -34,7 +34,9 @@ extern const char kGoogleTalkOAuth2Scope[]; extern const char kGoogleUserInfoEmail[]; extern const char kGoogleUserInfoProfile[]; +extern const char kParentApprovalOAuth2Scope[]; extern const char kPeopleApiReadOnlyOAuth2Scope[]; +extern const char kProgrammaticChallengeOAuth2Scope[]; extern const char kAccountsReauthOAuth2Scope[]; extern const char kAuditRecordingOAuth2Scope[]; extern const char kClearCutOAuth2Scope[];
diff --git a/gpu/command_buffer/service/shared_image_backing_gl_image.cc b/gpu/command_buffer/service/shared_image_backing_gl_image.cc index 8f36b8a..1113d21 100644 --- a/gpu/command_buffer/service/shared_image_backing_gl_image.cc +++ b/gpu/command_buffer/service/shared_image_backing_gl_image.cc
@@ -294,6 +294,40 @@ /////////////////////////////////////////////////////////////////////////////// // SharedImageBackingGLImage +// static +std::unique_ptr<SharedImageBackingGLImage> +SharedImageBackingGLImage::CreateFromGLTexture( + scoped_refptr<gl::GLImage> image, + const Mailbox& mailbox, + viz::ResourceFormat format, + const gfx::Size& size, + const gfx::ColorSpace& color_space, + GrSurfaceOrigin surface_origin, + SkAlphaType alpha_type, + uint32_t usage, + GLenum texture_target, + scoped_refptr<gles2::TexturePassthrough> wrapped_gl_texture) { + DCHECK(!!wrapped_gl_texture); + + // We don't expect the backing to allocate a new + // texture but it does need to know the texture target so we supply that + // one param. + InitializeGLTextureParams params; + params.target = texture_target; + UnpackStateAttribs attribs; + + auto shared_image = std::make_unique<SharedImageBackingGLImage>( + std::move(image), mailbox, format, size, color_space, surface_origin, + alpha_type, usage, params, attribs, true); + + shared_image->passthrough_texture_ = std::move(wrapped_gl_texture); + shared_image->gl_texture_retained_for_legacy_mailbox_ = true; + shared_image->gl_texture_retain_count_ = 1; + shared_image->image_bind_or_copy_needed_ = false; + + return shared_image; +} + SharedImageBackingGLImage::SharedImageBackingGLImage( scoped_refptr<gl::GLImage> image, const Mailbox& mailbox,
diff --git a/gpu/command_buffer/service/shared_image_backing_gl_image.h b/gpu/command_buffer/service/shared_image_backing_gl_image.h index e3727be..b08451b 100644 --- a/gpu/command_buffer/service/shared_image_backing_gl_image.h +++ b/gpu/command_buffer/service/shared_image_backing_gl_image.h
@@ -167,6 +167,21 @@ : public SharedImageBacking, public SharedImageRepresentationGLTextureClient { public: + // Used when SharedImageBackingGLImage is serving as a temporary SharedImage + // wrapper to an already-allocated texture. The returned backing will not + // create any new textures. + static std::unique_ptr<SharedImageBackingGLImage> CreateFromGLTexture( + scoped_refptr<gl::GLImage> image, + const Mailbox& mailbox, + viz::ResourceFormat format, + const gfx::Size& size, + const gfx::ColorSpace& color_space, + GrSurfaceOrigin surface_origin, + SkAlphaType alpha_type, + uint32_t usage, + GLenum texture_target, + scoped_refptr<gles2::TexturePassthrough> wrapped_gl_texture); + SharedImageBackingGLImage( scoped_refptr<gl::GLImage> image, const Mailbox& mailbox,
diff --git a/headless/BUILD.gn b/headless/BUILD.gn index e84bbee..5420dafb 100644 --- a/headless/BUILD.gn +++ b/headless/BUILD.gn
@@ -529,15 +529,13 @@ # Normally set to false (see build/args/headless.gn), but we can optionally # use external v8 startup data too. - if ((is_win && is_component_build) || !is_win) { - if (v8_use_external_startup_data) { - public_deps += [ "//v8" ] - if (use_v8_context_snapshot) { - data += [ "$root_out_dir/$v8_context_snapshot_filename" ] - data_deps += [ "//tools/v8_context_snapshot" ] - } else { - data += [ "$root_out_dir/snapshot_blob.bin" ] - } + if ((!is_win || is_component_build) && v8_use_external_startup_data) { + public_deps += [ "//v8" ] + if (use_v8_context_snapshot) { + data += [ "$root_out_dir/$v8_context_snapshot_filename" ] + data_deps += [ "//tools/v8_context_snapshot" ] + } else { + data += [ "$root_out_dir/snapshot_blob.bin" ] } }
diff --git a/ios/chrome/app/strings/ios_chromium_strings.grd b/ios/chrome/app/strings/ios_chromium_strings.grd index e91643a..2e95c878 100644 --- a/ios/chrome/app/strings/ios_chromium_strings.grd +++ b/ios/chrome/app/strings/ios_chromium_strings.grd
@@ -235,12 +235,12 @@ <message name="IDS_IOS_ENTERPRISE_FORCED_SIGNIN_MESSAGE" desc="Text displayed in the popover to inform the user that the browser is managed by Enterprise policies. (Force Sign In) [iOS only]"> Your organization requires you to sign in to use Chromium. </message> + <message name="IDS_IOS_ENTERPRISE_FORCED_SIGNIN_MESSAGE_WITH_LEARN_MORE" desc="Text to inform the user about the forced sign-in policy with a Learn More link that redirects to a page that gives more details. (Force Sign In) [iOS only]"> + Your organization requires you to sign in to use Chromium. <ph name="BEGIN_LINK">BEGIN_LINK</ph>Learn More<ph name="END_LINK">END_LINK</ph> + </message> <message name="IDS_IOS_ENTERPRISE_FORCED_SIGNIN_SIGNOUT_DIALOG_TITLE" desc="The signout dialog title when forced sign-in is enabled. (Force Sign In) [iOS only]"> Sign out of Chromium? </message> - <message name="IDS_IOS_ENTERPRISE_FORCED_SIGNIN_SYNC_SETTINGS_SIGNOUT_FOOTER" desc="The informational footer below the sign-out button item in sync settings when the forced sign-in policy is enabled. (Force Sign In) [iOS only]"> - Your organization requires you to sign in to use Chromium. <ph name="BEGIN_LINK">BEGIN_LINK</ph>Learn More<ph name="END_LINK">END_LINK</ph>. - </message> <message name="IDS_IOS_ENTERPRISE_SIGNED_OUT_SUBTEXT" desc="Text displayed in an alert when the user is signed out due to browser sign-in becoming disabled by policy. [iOS only]"> Your administrator requires you to sign in with an organization account. Accounts that are restricted by your administrator are hidden. </message>
diff --git a/ios/chrome/app/strings/ios_chromium_strings_grd/IDS_IOS_ENTERPRISE_FORCED_SIGNIN_MESSAGE_WITH_LEARN_MORE.png.sha1 b/ios/chrome/app/strings/ios_chromium_strings_grd/IDS_IOS_ENTERPRISE_FORCED_SIGNIN_MESSAGE_WITH_LEARN_MORE.png.sha1 new file mode 100644 index 0000000..c5cb9b5 --- /dev/null +++ b/ios/chrome/app/strings/ios_chromium_strings_grd/IDS_IOS_ENTERPRISE_FORCED_SIGNIN_MESSAGE_WITH_LEARN_MORE.png.sha1
@@ -0,0 +1 @@ +ce4d8ddebb71283ce2f41e96c8bb8a7dc90a2d83 \ No newline at end of file
diff --git a/ios/chrome/app/strings/ios_chromium_strings_grd/IDS_IOS_ENTERPRISE_FORCED_SIGNIN_SYNC_SETTINGS_SIGNOUT_FOOTER.png.sha1 b/ios/chrome/app/strings/ios_chromium_strings_grd/IDS_IOS_ENTERPRISE_FORCED_SIGNIN_SYNC_SETTINGS_SIGNOUT_FOOTER.png.sha1 deleted file mode 100644 index b44d688..0000000 --- a/ios/chrome/app/strings/ios_chromium_strings_grd/IDS_IOS_ENTERPRISE_FORCED_SIGNIN_SYNC_SETTINGS_SIGNOUT_FOOTER.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -657f06214030efcbec1bbfe8c460f13a4ed00078 \ No newline at end of file
diff --git a/ios/chrome/app/strings/ios_google_chrome_strings.grd b/ios/chrome/app/strings/ios_google_chrome_strings.grd index c79342d..4fb59e6 100644 --- a/ios/chrome/app/strings/ios_google_chrome_strings.grd +++ b/ios/chrome/app/strings/ios_google_chrome_strings.grd
@@ -235,12 +235,12 @@ <message name="IDS_IOS_ENTERPRISE_FORCED_SIGNIN_MESSAGE" desc="Text displayed in the popover to inform the user that the browser is managed by Enterprise policies. (Force Sign In) [iOS only]"> Your organization requires you to sign in to use Chrome. </message> + <message name="IDS_IOS_ENTERPRISE_FORCED_SIGNIN_MESSAGE_WITH_LEARN_MORE" desc="Text to inform the user about the forced sign-in policy with a Learn More link that redirects to a page that gives more details. (Force Sign In) [iOS only]"> + Your organization requires you to sign in to use Chrome. <ph name="BEGIN_LINK">BEGIN_LINK</ph>Learn More<ph name="END_LINK">END_LINK</ph> + </message> <message name="IDS_IOS_ENTERPRISE_FORCED_SIGNIN_SIGNOUT_DIALOG_TITLE" desc="The signout dialog title when forced sign-in is enabled. (Force Sign In) [iOS only]"> Sign out of Chrome? </message> - <message name="IDS_IOS_ENTERPRISE_FORCED_SIGNIN_SYNC_SETTINGS_SIGNOUT_FOOTER" desc="The informational footer below the sign-out button item in sync settings when the forced sign-in policy is enabled. (Force Sign In) [iOS only]"> - Your organization requires you to sign in to use Chrome. <ph name="BEGIN_LINK">BEGIN_LINK</ph>Learn More<ph name="END_LINK">END_LINK</ph>. - </message> <message name="IDS_IOS_ENTERPRISE_SIGNED_OUT_SUBTEXT" desc="Text displayed in an alert when the user is signed out due to browser sign-in becoming disabled by policy. [iOS only]"> Your administrator requires you to sign in with an organization account. Accounts that are restricted by your administrator are hidden. </message>
diff --git a/ios/chrome/app/strings/ios_google_chrome_strings_grd/IDS_IOS_ENTERPRISE_FORCED_SIGNIN_MESSAGE_WITH_LEARN_MORE.png.sha1 b/ios/chrome/app/strings/ios_google_chrome_strings_grd/IDS_IOS_ENTERPRISE_FORCED_SIGNIN_MESSAGE_WITH_LEARN_MORE.png.sha1 new file mode 100644 index 0000000..ac3fbc8 --- /dev/null +++ b/ios/chrome/app/strings/ios_google_chrome_strings_grd/IDS_IOS_ENTERPRISE_FORCED_SIGNIN_MESSAGE_WITH_LEARN_MORE.png.sha1
@@ -0,0 +1 @@ +b31a17f97e2f4430f5ea20ba6a4e3f0c76442b48 \ No newline at end of file
diff --git a/ios/chrome/app/strings/ios_google_chrome_strings_grd/IDS_IOS_ENTERPRISE_FORCED_SIGNIN_SYNC_SETTINGS_SIGNOUT_FOOTER.png.sha1 b/ios/chrome/app/strings/ios_google_chrome_strings_grd/IDS_IOS_ENTERPRISE_FORCED_SIGNIN_SYNC_SETTINGS_SIGNOUT_FOOTER.png.sha1 deleted file mode 100644 index 77ce7bb3..0000000 --- a/ios/chrome/app/strings/ios_google_chrome_strings_grd/IDS_IOS_ENTERPRISE_FORCED_SIGNIN_SYNC_SETTINGS_SIGNOUT_FOOTER.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -089477b1c8cfde04c8be0ec43b6f5039994e8433 \ No newline at end of file
diff --git a/ios/chrome/app/strings/ios_strings.grd b/ios/chrome/app/strings/ios_strings.grd index 37cf7a7..97e9d271 100644 --- a/ios/chrome/app/strings/ios_strings.grd +++ b/ios/chrome/app/strings/ios_strings.grd
@@ -1766,9 +1766,6 @@ <message name="IDS_IOS_READING_LIST_EDIT_BUTTON" desc="Label of the button to edit the reading list entries (delete, mark as read/unread) [Length: 20em]" meaning="Start editing the reading list entries. [Length: 20em]"> Edit </message> - <message name="IDS_IOS_READING_LIST_EMPTY_MESSAGE" desc="Message to explain to the user how to add entries to the reading list" meaning="[Length: unlimited]"> - Your reading list is available offline. To add a page to your reading list, tap <ph name="SHARE_OPENING_ICON">SHARE_OPENING_ICON<ex>(menu icon)</ex></ph> then <ph name="ADD_TO_READING_LIST_TEXT">ADD_TO_READING_LIST_TEXT<ex>Add to Reading List</ex></ph>. - </message> <message name="IDS_IOS_READING_LIST_JUST_NOW" desc="String indicating that an event (adding item, distillation) happened less than one minute ago. [Length: 25em]"> Just now </message>
diff --git a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_READING_LIST_EMPTY_MESSAGE.png.sha1 b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_READING_LIST_EMPTY_MESSAGE.png.sha1 deleted file mode 100644 index 2f34ef5..0000000 --- a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_READING_LIST_EMPTY_MESSAGE.png.sha1 +++ /dev/null
@@ -1 +0,0 @@ -29f386f254b404325613ff749da1a707fa8d2ca0 \ No newline at end of file
diff --git a/ios/chrome/browser/flags/about_flags.mm b/ios/chrome/browser/flags/about_flags.mm index 243ff4b..1ea04f99 100644 --- a/ios/chrome/browser/flags/about_flags.mm +++ b/ios/chrome/browser/flags/about_flags.mm
@@ -787,6 +787,13 @@ flag_descriptions::kEnableDiscoverFeedShorterCacheName, flag_descriptions::kEnableDiscoverFeedShorterCacheDescription, flags_ui::kOsIos, FEATURE_VALUE_TYPE(kEnableDiscoverFeedShorterCache)}, + {"shared-highlighting-v2", flag_descriptions::kIOSSharedHighlightingV2Name, + flag_descriptions::kIOSSharedHighlightingV2Description, flags_ui::kOsIos, + FEATURE_VALUE_TYPE(shared_highlighting::kSharedHighlightingV2)}, + {"shared-highlighting-amp", + flag_descriptions::kIOSSharedHighlightingAmpName, + flag_descriptions::kIOSSharedHighlightingAmpDescription, flags_ui::kOsIos, + FEATURE_VALUE_TYPE(shared_highlighting::kSharedHighlightingAmp)}, }; bool SkipConditionalFeatureEntry(const flags_ui::FeatureEntry& entry) {
diff --git a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc index 825e980d..ca6536d 100644 --- a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc +++ b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc
@@ -323,6 +323,15 @@ "Changes the Shared Highlighting color of the text fragment" "away from the default yellow in iOS. Works with #scroll-to-text-ios flag."; +const char kIOSSharedHighlightingAmpName[] = "Shared Highlighting on AMP pages"; +const char kIOSSharedHighlightingAmpDescription[] = + "Enables the Create Link option on AMP pages."; + +const char kIOSSharedHighlightingV2Name[] = "Text Fragments UI improvements"; +const char kIOSSharedHighlightingV2Description[] = + "Enables improvements to text fragments UI, including a menu for removing " + "or resharing a highlight."; + const char kSharedHighlightingUseBlocklistIOSName[] = "Shared Highlighting blocklist"; const char kSharedHighlightingUseBlocklistIOSDescription[] =
diff --git a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h index 450fbeb5..cbf9867 100644 --- a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h +++ b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h
@@ -280,6 +280,16 @@ extern const char kIOSSharedHighlightingColorChangeName[]; extern const char kIOSSharedHighlightingColorChangeDescription[]; +// Title and description for the flag to enable Shared Highlighting on AMP pages +// in iOS. +extern const char kIOSSharedHighlightingAmpName[]; +extern const char kIOSSharedHighlightingAmpDescription[]; + +// Title and description for the flag to enable browser-layer improvements to +// the text fragments UI. +extern const char kIOSSharedHighlightingV2Name[]; +extern const char kIOSSharedHighlightingV2Description[]; + // Title and description for the flag to lock the bottom toolbar into place. extern const char kLockBottomToolbarName[]; extern const char kLockBottomToolbarDescription[];
diff --git a/ios/chrome/browser/passwords/password_controller_unittest.mm b/ios/chrome/browser/passwords/password_controller_unittest.mm index 2de0a2b..22b42875 100644 --- a/ios/chrome/browser/passwords/password_controller_unittest.mm +++ b/ios/chrome/browser/passwords/password_controller_unittest.mm
@@ -2227,12 +2227,10 @@ "password", 3, "pw", nullptr, nullptr, false, &form_data); __block BOOL block_was_called = NO; - __block BOOL return_value = NO; [passwordController_.sharedPasswordController fillPasswordForm:form_data completionHandler:^(BOOL success) { block_was_called = YES; - return_value = success; }]; EXPECT_TRUE(WaitUntilConditionOrTimeout(kWaitForJSCompletionTimeout, ^bool() { return block_was_called;
diff --git a/ios/chrome/browser/policy/reporting/browser_report_generator_ios.h b/ios/chrome/browser/policy/reporting/browser_report_generator_ios.h index d740fad..24df871 100644 --- a/ios/chrome/browser/policy/reporting/browser_report_generator_ios.h +++ b/ios/chrome/browser/policy/reporting/browser_report_generator_ios.h
@@ -34,15 +34,14 @@ // BrowserReportGenerator::Delegate implementation. std::string GetExecutablePath() override; version_info::Channel GetChannel() override; - std::vector<BrowserReportGenerator::ReportedProfileData> GetReportedProfiles( - ReportType report_type) override; + std::vector<BrowserReportGenerator::ReportedProfileData> GetReportedProfiles() + override; bool IsExtendedStableChannel() override; void GenerateBuildStateInfo( enterprise_management::BrowserReport* report) override; void GeneratePluginsIfNeeded( ReportCallback callback, std::unique_ptr<enterprise_management::BrowserReport> report) override; - void OnProfileInfoGenerated(ReportType report_type) override; }; } // namespace enterprise_reporting
diff --git a/ios/chrome/browser/policy/reporting/browser_report_generator_ios.mm b/ios/chrome/browser/policy/reporting/browser_report_generator_ios.mm index 1c3e82b5..4cc9a2c1 100644 --- a/ios/chrome/browser/policy/reporting/browser_report_generator_ios.mm +++ b/ios/chrome/browser/policy/reporting/browser_report_generator_ios.mm
@@ -35,7 +35,7 @@ } std::vector<BrowserReportGenerator::ReportedProfileData> -BrowserReportGeneratorIOS::GetReportedProfiles(ReportType report_type) { +BrowserReportGeneratorIOS::GetReportedProfiles() { std::vector<BrowserReportGenerator::ReportedProfileData> reportedProfileData; for (const auto* entry : GetApplicationContext() ->GetChromeBrowserStateManager() @@ -69,8 +69,4 @@ std::move(callback).Run(std::move(report)); } -void BrowserReportGeneratorIOS::OnProfileInfoGenerated(ReportType report_type) { - // Not used on iOS because there is no throttling profiles. -} - } // namespace enterprise_reporting
diff --git a/ios/chrome/browser/policy/reporting/browser_report_generator_ios_unittest.mm b/ios/chrome/browser/policy/reporting/browser_report_generator_ios_unittest.mm index d9f384c7..5b294be 100644 --- a/ios/chrome/browser/policy/reporting/browser_report_generator_ios_unittest.mm +++ b/ios/chrome/browser/policy/reporting/browser_report_generator_ios_unittest.mm
@@ -48,7 +48,6 @@ void GenerateAndVerify() { base::RunLoop run_loop; generator_.Generate( - ReportType::kFull, base::BindLambdaForTesting( [&run_loop](std::unique_ptr<em::BrowserReport> report) { EXPECT_TRUE(report.get());
diff --git a/ios/chrome/browser/policy/reporting/profile_report_generator_ios_unittest.mm b/ios/chrome/browser/policy/reporting/profile_report_generator_ios_unittest.mm index 9d70bc2..94f8522 100644 --- a/ios/chrome/browser/policy/reporting/profile_report_generator_ios_unittest.mm +++ b/ios/chrome/browser/policy/reporting/profile_report_generator_ios_unittest.mm
@@ -106,8 +106,7 @@ std::unique_ptr<em::ChromeUserProfileInfo> GenerateReport() { std::unique_ptr<em::ChromeUserProfileInfo> report = generator_.MaybeGenerate(kProfilePath, - kProfilePath.BaseName().AsUTF8Unsafe(), - ReportType::kFull); + kProfilePath.BaseName().AsUTF8Unsafe()); if (!report) return nullptr;
diff --git a/ios/chrome/browser/safe_browsing/chrome_password_protection_service.h b/ios/chrome/browser/safe_browsing/chrome_password_protection_service.h index 5671780f..2d93fc6 100644 --- a/ios/chrome/browser/safe_browsing/chrome_password_protection_service.h +++ b/ios/chrome/browser/safe_browsing/chrome_password_protection_service.h
@@ -134,6 +134,9 @@ AccountInfo GetAccountInfo() const override; + safe_browsing::ChromeUserPopulation::UserPopulation GetUserPopulationPref() + const override; + AccountInfo GetAccountInfoForUsername( const std::string& username) const override;
diff --git a/ios/chrome/browser/safe_browsing/chrome_password_protection_service.mm b/ios/chrome/browser/safe_browsing/chrome_password_protection_service.mm index 644fb89..05489002 100644 --- a/ios/chrome/browser/safe_browsing/chrome_password_protection_service.mm +++ b/ios/chrome/browser/safe_browsing/chrome_password_protection_service.mm
@@ -378,6 +378,11 @@ identity_manager->GetPrimaryAccountInfo(signin::ConsentLevel::kSync)); } +safe_browsing::ChromeUserPopulation::UserPopulation +ChromePasswordProtectionService::GetUserPopulationPref() const { + return ::GetUserPopulationPref(browser_state_); +} + AccountInfo ChromePasswordProtectionService::GetAccountInfoForUsername( const std::string& username) const { auto* identity_manager =
diff --git a/ios/chrome/browser/safe_browsing/user_population.h b/ios/chrome/browser/safe_browsing/user_population.h index 5961b861..8c566a93 100644 --- a/ios/chrome/browser/safe_browsing/user_population.h +++ b/ios/chrome/browser/safe_browsing/user_population.h
@@ -9,6 +9,10 @@ class ChromeBrowserState; +// Returns the UserPopulation enum for the given |browser_state|. +safe_browsing::ChromeUserPopulation::UserPopulation GetUserPopulationPref( + ChromeBrowserState* browser_state); + // Creates a ChromeUserPopulation proto for the given |browser_state|. safe_browsing::ChromeUserPopulation GetUserPopulation( ChromeBrowserState* browser_state);
diff --git a/ios/chrome/browser/safe_browsing/user_population.mm b/ios/chrome/browser/safe_browsing/user_population.mm index 547cd9ca..81d64a6 100644 --- a/ios/chrome/browser/safe_browsing/user_population.mm +++ b/ios/chrome/browser/safe_browsing/user_population.mm
@@ -21,18 +21,27 @@ using safe_browsing::ChromeUserPopulation; -ChromeUserPopulation GetUserPopulation(ChromeBrowserState* browser_state) { - ChromeUserPopulation population; +ChromeUserPopulation::UserPopulation GetUserPopulationPref( + ChromeBrowserState* browser_state) { if (browser_state->GetPrefs()) { const PrefService& prefs = *browser_state->GetPrefs(); if (safe_browsing::IsEnhancedProtectionEnabled(prefs)) { - population.set_user_population(ChromeUserPopulation::ENHANCED_PROTECTION); + return ChromeUserPopulation::ENHANCED_PROTECTION; } else if (safe_browsing::IsExtendedReportingEnabled(prefs)) { - population.set_user_population(ChromeUserPopulation::EXTENDED_REPORTING); + return ChromeUserPopulation::EXTENDED_REPORTING; } else if (safe_browsing::IsSafeBrowsingEnabled(prefs)) { - population.set_user_population(ChromeUserPopulation::SAFE_BROWSING); + return ChromeUserPopulation::SAFE_BROWSING; } + } + return ChromeUserPopulation::UNKNOWN_USER_POPULATION; +} + +ChromeUserPopulation GetUserPopulation(ChromeBrowserState* browser_state) { + ChromeUserPopulation population; + population.set_user_population(GetUserPopulationPref(browser_state)); + if (browser_state->GetPrefs()) { + const PrefService& prefs = *browser_state->GetPrefs(); population.set_is_mbb_enabled(prefs.GetBoolean( unified_consent::prefs::kUrlKeyedAnonymizedDataCollectionEnabled)); }
diff --git a/ios/chrome/browser/signin/authentication_service.mm b/ios/chrome/browser/signin/authentication_service.mm index 0f64eaf..aabdb49 100644 --- a/ios/chrome/browser/signin/authentication_service.mm +++ b/ios/chrome/browser/signin/authentication_service.mm
@@ -331,11 +331,12 @@ CHECK(!account_info.IsEmpty()); CHECK(!account_info.hosted_domain.empty()); - const bool success = + const signin::PrimaryAccountMutator::PrimaryAccountError error = identity_manager_->GetPrimaryAccountMutator()->SetPrimaryAccount( account_id, signin::ConsentLevel::kSync); - CHECK(success); + CHECK_EQ(signin::PrimaryAccountMutator::PrimaryAccountError::kNoError, error) + << "SetPrimaryAccount error: " << static_cast<int>(error); CHECK_EQ(account_id, identity_manager_->GetPrimaryAccountId(signin::ConsentLevel::kSync));
diff --git a/ios/chrome/browser/ui/browser_view/browser_view_controller.mm b/ios/chrome/browser/ui/browser_view/browser_view_controller.mm index 481e977..9bcf935 100644 --- a/ios/chrome/browser/ui/browser_view/browser_view_controller.mm +++ b/ios/chrome/browser/ui/browser_view/browser_view_controller.mm
@@ -3430,6 +3430,12 @@ completionHandler(configuration); } +- (void)webState:(web::WebState*)webState + contextMenuWillCommitWithAnimator: + (id<UIContextMenuInteractionCommitAnimating>)animator { + [self.contextMenuProvider commitPreview]; +} + - (id<CRWResponderInputView>)webStateInputViewProvider: (web::WebState*)webState { return self.inputViewProvider;
diff --git a/ios/chrome/browser/ui/context_menu/context_menu_configuration_provider.h b/ios/chrome/browser/ui/context_menu/context_menu_configuration_provider.h index ff9462eb..d8ae2dc 100644 --- a/ios/chrome/browser/ui/context_menu/context_menu_configuration_provider.h +++ b/ios/chrome/browser/ui/context_menu/context_menu_configuration_provider.h
@@ -28,6 +28,9 @@ params:(web::ContextMenuParams)params baseViewController:(UIViewController*)baseViewController; +// Called when the user commits the preview (taps on it). +- (void)commitPreview; + // DEPRECATED. // Displays a context menu using an action sheet on |baseViewController|. // |params| is copied in order to be used in blocks.
diff --git a/ios/chrome/browser/ui/context_menu/context_menu_configuration_provider.mm b/ios/chrome/browser/ui/context_menu/context_menu_configuration_provider.mm index 0fae521..eb63d97 100644 --- a/ios/chrome/browser/ui/context_menu/context_menu_configuration_provider.mm +++ b/ios/chrome/browser/ui/context_menu/context_menu_configuration_provider.mm
@@ -134,6 +134,7 @@ contextMenuConfigurationForWebState:(web::WebState*)webState params:(web::ContextMenuParams)params baseViewController:(UIViewController*)baseViewController { + self.linkPreview = nil; // Prevent context menu from displaying for a tab which is no longer the // current one. if (webState != self.currentWebState) { @@ -417,6 +418,10 @@ actionProvider:actionProvider]; } +- (void)commitPreview { + [self.linkPreview handlePreviewAction]; +} + - (void)showLegacyContextMenuForWebState:(web::WebState*)webState params:(web::ContextMenuParams)params baseViewController:(UIViewController*)baseViewController {
diff --git a/ios/chrome/browser/ui/passwords/OWNERS b/ios/chrome/browser/ui/passwords/OWNERS index 93ecef3..b6c914d 100644 --- a/ios/chrome/browser/ui/passwords/OWNERS +++ b/ios/chrome/browser/ui/passwords/OWNERS
@@ -1 +1,2 @@ javierrobles@chromium.org +vsemeniuk@google.com
diff --git a/ios/chrome/browser/ui/reading_list/BUILD.gn b/ios/chrome/browser/ui/reading_list/BUILD.gn index e31a150..58097d21 100644 --- a/ios/chrome/browser/ui/reading_list/BUILD.gn +++ b/ios/chrome/browser/ui/reading_list/BUILD.gn
@@ -150,8 +150,6 @@ source_set("reading_list_ui") { configs += [ "//build/config/compiler:enable_arc" ] sources = [ - "empty_reading_list_message_util.h", - "empty_reading_list_message_util.mm", "number_badge_view.h", "number_badge_view.mm", "reading_list_data_sink.h", @@ -176,7 +174,6 @@ ":reading_list_constants", "resources:reading_list_empty", "resources:reading_list_empty_state", - "resources:reading_list_tools_icon", "//base", "//base:i18n", "//components/prefs",
diff --git a/ios/chrome/browser/ui/reading_list/empty_reading_list_message_util.h b/ios/chrome/browser/ui/reading_list/empty_reading_list_message_util.h deleted file mode 100644 index 0838b702..0000000 --- a/ios/chrome/browser/ui/reading_list/empty_reading_list_message_util.h +++ /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. - -#ifndef IOS_CHROME_BROWSER_UI_READING_LIST_EMPTY_READING_LIST_MESSAGE_UTIL_H_ -#define IOS_CHROME_BROWSER_UI_READING_LIST_EMPTY_READING_LIST_MESSAGE_UTIL_H_ - -#import <UIKit/UIKit.h> - -// Returns the attributed message to use for the empty Reading List background -// view. -NSAttributedString* GetReadingListEmptyMessage(); - -// Returns the accessibility label to use for the label displaying the text -// returned by GetReadingListEmptyMessage(). -NSString* GetReadingListEmptyMessageA11yLabel(); - -#endif // IOS_CHROME_BROWSER_UI_READING_LIST_EMPTY_READING_LIST_MESSAGE_UTIL_H_
diff --git a/ios/chrome/browser/ui/reading_list/empty_reading_list_message_util.mm b/ios/chrome/browser/ui/reading_list/empty_reading_list_message_util.mm deleted file mode 100644 index 62731e10..0000000 --- a/ios/chrome/browser/ui/reading_list/empty_reading_list_message_util.mm +++ /dev/null
@@ -1,157 +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. - -#import "ios/chrome/browser/ui/reading_list/empty_reading_list_message_util.h" - -#include "base/check.h" -#include "ios/chrome/browser/system_flags.h" -#include "ios/chrome/browser/ui/util/rtl_geometry.h" -#import "ios/chrome/browser/ui/util/uikit_ui_util.h" -#import "ios/chrome/common/ui/colors/semantic_color_names.h" -#include "ios/chrome/grit/ios_strings.h" -#include "ui/base/l10n/l10n_util_mac.h" - -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - -namespace { - -// Images name. -NSString* const kToolsIcon = @"reading_list_tools_icon"; - -// Tag in string. -NSString* const kOpenShareMarker = @"SHARE_OPENING_ICON"; -NSString* const kAddToReadingListTextMarker = @"ADD_TO_READING_LIST_TEXT"; - -// Background view constants. -const CGFloat kLineSpacing = 4; - -// Returns the font to use for the message text. -UIFont* GetMessageFont() { - return [UIFont preferredFontForTextStyle:UIFontTextStyleBody]; -} - -// Returns the attributes to use for the message text. -NSMutableDictionary* GetMessageAttributes() { - NSMutableDictionary* attributes = [NSMutableDictionary dictionary]; - UIFont* font = GetMessageFont(); - attributes[NSFontAttributeName] = font; - attributes[NSForegroundColorAttributeName] = - [UIColor colorNamed:kTextSecondaryColor]; - NSMutableParagraphStyle* paragraph_style = - [[NSMutableParagraphStyle alloc] init]; - paragraph_style.lineBreakMode = NSLineBreakByWordWrapping; - paragraph_style.alignment = NSTextAlignmentCenter; - // If the line wrapping occurs that one of the icons is the first character on - // a new line, the default line spacing will result in uneven line heights. - // Manually setting the line spacing here prevents that from occurring. - paragraph_style.lineSpacing = kLineSpacing; - attributes[NSParagraphStyleAttributeName] = paragraph_style; - return attributes; -} - -// Returns the attributes to use for the instructions on how to reach the "Read -// Later" option. -NSMutableDictionary* GetInstructionAttributes() { - NSMutableDictionary* attributes = GetMessageAttributes(); - attributes[NSFontAttributeName] = - [UIFont preferredFontForTextStyle:UIFontTextStyleHeadline]; - return attributes; -} - -// Returns the "Add to Reading List" text to appear at the end of the string, -// with correct styling. -NSAttributedString* GetReadLaterString() { - NSString* add_to_reading_list_text = - l10n_util::GetNSString(IDS_IOS_SHARE_MENU_READING_LIST_ACTION); - return [[NSAttributedString alloc] initWithString:add_to_reading_list_text - attributes:GetInstructionAttributes()]; -} - -// Appends the tools icon to |text|. Spacer text that is added by this function -// is formatted with |attributes|. -void AppendToolsIcon(NSMutableAttributedString* text, - NSDictionary* attributes) { - - // The icon bounds must be offset to be vertically centered with the message - // text. - UIImage* icon = [UIImage imageNamed:kToolsIcon]; - CGRect icon_bounds = CGRectZero; - icon_bounds.size = icon.size; - icon_bounds.origin.y = (GetMessageFont().xHeight - icon.size.height) / 2.0; - - // Attach the icon image. - NSTextAttachment* attachment = [[NSTextAttachment alloc] init]; - attachment.image = - [icon imageWithTintColor:attributes[NSForegroundColorAttributeName]]; - attachment.bounds = icon_bounds; - NSAttributedString* attachment_string = - [NSAttributedString attributedStringWithAttachment:attachment]; - [text appendAttributedString:attachment_string]; -} - -// Returns the string to use to describe the buttons needed to access the "Read -// Later" option. -NSAttributedString* GetInstructionIconString() { - NSDictionary* attributes = GetInstructionAttributes(); - NSMutableAttributedString* icon_string = - [[NSMutableAttributedString alloc] init]; - AppendToolsIcon(icon_string, attributes); - return icon_string; -} - -// Returns the icon string in an accessible format. -NSAttributedString* GetAccessibleInstructionIconString() { - NSDictionary* attributes = GetInstructionAttributes(); - NSMutableAttributedString* icon_string = - [[NSMutableAttributedString alloc] initWithString:@":" - attributes:attributes]; - NSString* tools_text = [NSString - stringWithFormat:@"%@, ", - l10n_util::GetNSString(IDS_IOS_TOOLBAR_SETTINGS)]; - [icon_string appendAttributedString:[[NSAttributedString alloc] - initWithString:tools_text - attributes:attributes]]; - return icon_string; -} - -// Returns the attributed text to use for the message. If |use_icons| is true, -// icon images are added to the text; otherwise accessible text versions of the -// instructions are used. -NSAttributedString* GetReadingListEmptyMessage(bool use_icons) { - NSString* raw_text = - l10n_util::GetNSString(IDS_IOS_READING_LIST_EMPTY_MESSAGE); - NSMutableAttributedString* message = - [[NSMutableAttributedString alloc] initWithString:raw_text - attributes:GetMessageAttributes()]; - NSAttributedString* instruction_icon_string = - use_icons ? GetInstructionIconString() - : GetAccessibleInstructionIconString(); - NSAttributedString* read_later_string = GetReadLaterString(); - // Two replacements must be made in the text: - // - kOpenShareMarker should be replaced with |instruction_icon_string| - // - kAddToReadingListTextMarker should be replaced with - // |add_to_reading_list_text| - NSRange icon_range = [message.string rangeOfString:kOpenShareMarker]; - DCHECK(icon_range.location != NSNotFound); - [message replaceCharactersInRange:icon_range - withAttributedString:instruction_icon_string]; - - NSRange read_later_range = - [message.string rangeOfString:kAddToReadingListTextMarker]; - DCHECK(read_later_range.location != NSNotFound); - [message replaceCharactersInRange:read_later_range - withAttributedString:read_later_string]; - return message; -} -} // namespace - -NSAttributedString* GetReadingListEmptyMessage() { - return GetReadingListEmptyMessage(true); -} - -NSString* GetReadingListEmptyMessageA11yLabel() { - return GetReadingListEmptyMessage(false).string; -}
diff --git a/ios/chrome/browser/ui/reading_list/reading_list_table_view_controller.mm b/ios/chrome/browser/ui/reading_list/reading_list_table_view_controller.mm index 80061d96..f0d2d12 100644 --- a/ios/chrome/browser/ui/reading_list/reading_list_table_view_controller.mm +++ b/ios/chrome/browser/ui/reading_list/reading_list_table_view_controller.mm
@@ -23,7 +23,6 @@ #import "ios/chrome/browser/ui/alert_coordinator/action_sheet_coordinator.h" #import "ios/chrome/browser/ui/list_model/list_item+Controller.h" #import "ios/chrome/browser/ui/list_model/list_item.h" -#import "ios/chrome/browser/ui/reading_list/empty_reading_list_message_util.h" #import "ios/chrome/browser/ui/reading_list/reading_list_constants.h" #import "ios/chrome/browser/ui/reading_list/reading_list_data_sink.h" #import "ios/chrome/browser/ui/reading_list/reading_list_data_source.h"
diff --git a/ios/chrome/browser/ui/reading_list/resources/BUILD.gn b/ios/chrome/browser/ui/reading_list/resources/BUILD.gn index 931edbb..d7f959f 100644 --- a/ios/chrome/browser/ui/reading_list/resources/BUILD.gn +++ b/ios/chrome/browser/ui/reading_list/resources/BUILD.gn
@@ -30,12 +30,3 @@ "reading_list_empty_state.imageset/reading_list_empty_state@3x.png", ] } - -imageset("reading_list_tools_icon") { - sources = [ - "reading_list_tools_icon.imageset/Contents.json", - "reading_list_tools_icon.imageset/reading_list_tools_icon.png", - "reading_list_tools_icon.imageset/reading_list_tools_icon@2x.png", - "reading_list_tools_icon.imageset/reading_list_tools_icon@3x.png", - ] -}
diff --git a/ios/chrome/browser/ui/reading_list/resources/reading_list_tools_icon.imageset/Contents.json b/ios/chrome/browser/ui/reading_list/resources/reading_list_tools_icon.imageset/Contents.json deleted file mode 100644 index a6af62e..0000000 --- a/ios/chrome/browser/ui/reading_list/resources/reading_list_tools_icon.imageset/Contents.json +++ /dev/null
@@ -1,23 +0,0 @@ -{ - "images": [ - { - "idiom": "universal", - "scale": "1x", - "filename": "reading_list_tools_icon.png" - }, - { - "idiom": "universal", - "scale": "2x", - "filename": "reading_list_tools_icon@2x.png" - }, - { - "idiom": "universal", - "scale": "3x", - "filename": "reading_list_tools_icon@3x.png" - } - ], - "info": { - "version": 1, - "author": "xcode" - } -}
diff --git a/ios/chrome/browser/ui/reading_list/resources/reading_list_tools_icon.imageset/reading_list_tools_icon.png b/ios/chrome/browser/ui/reading_list/resources/reading_list_tools_icon.imageset/reading_list_tools_icon.png deleted file mode 100644 index f4f4b8d..0000000 --- a/ios/chrome/browser/ui/reading_list/resources/reading_list_tools_icon.imageset/reading_list_tools_icon.png +++ /dev/null Binary files differ
diff --git a/ios/chrome/browser/ui/reading_list/resources/reading_list_tools_icon.imageset/reading_list_tools_icon@2x.png b/ios/chrome/browser/ui/reading_list/resources/reading_list_tools_icon.imageset/reading_list_tools_icon@2x.png deleted file mode 100644 index 701b35a..0000000 --- a/ios/chrome/browser/ui/reading_list/resources/reading_list_tools_icon.imageset/reading_list_tools_icon@2x.png +++ /dev/null Binary files differ
diff --git a/ios/chrome/browser/ui/reading_list/resources/reading_list_tools_icon.imageset/reading_list_tools_icon@3x.png b/ios/chrome/browser/ui/reading_list/resources/reading_list_tools_icon.imageset/reading_list_tools_icon@3x.png deleted file mode 100644 index 981187c6..0000000 --- a/ios/chrome/browser/ui/reading_list/resources/reading_list_tools_icon.imageset/reading_list_tools_icon@3x.png +++ /dev/null Binary files differ
diff --git a/ios/chrome/browser/ui/settings/google_services/manage_sync_settings_mediator.mm b/ios/chrome/browser/ui/settings/google_services/manage_sync_settings_mediator.mm index 9e2731f..aefe720 100644 --- a/ios/chrome/browser/ui/settings/google_services/manage_sync_settings_mediator.mm +++ b/ios/chrome/browser/ui/settings/google_services/manage_sync_settings_mediator.mm
@@ -359,7 +359,7 @@ [[TableViewLinkHeaderFooterItem alloc] initWithType:SignOutItemFooterType]; footerItem.text = l10n_util::GetNSString( - IDS_IOS_ENTERPRISE_FORCED_SIGNIN_SYNC_SETTINGS_SIGNOUT_FOOTER); + IDS_IOS_ENTERPRISE_FORCED_SIGNIN_MESSAGE_WITH_LEARN_MORE); footerItem.urls = std::vector<GURL>{GURL("chrome://management/")}; [model setFooter:footerItem forSectionWithIdentifier:SignOutSectionIdentifier];
diff --git a/ios/chrome/browser/ui/sharing/sharing_coordinator_unittest.mm b/ios/chrome/browser/ui/sharing/sharing_coordinator_unittest.mm index 74970a9..98613c57 100644 --- a/ios/chrome/browser/ui/sharing/sharing_coordinator_unittest.mm +++ b/ios/chrome/browser/ui/sharing/sharing_coordinator_unittest.mm
@@ -134,15 +134,11 @@ params:params originView:fake_origin_view_]; - // Pointer to allow us to grab the VC instance in our validation callback. - __block UIActivityViewController* activityViewController; - id vc_partial_mock = OCMPartialMock(base_view_controller_); [[vc_partial_mock expect] presentViewController:[OCMArg checkWithBlock:^BOOL( UIViewController* viewController) { if ([viewController isKindOfClass:[UIActivityViewController class]]) { - activityViewController = (UIActivityViewController*)viewController; return YES; } return NO; @@ -208,15 +204,11 @@ params:params originView:fake_origin_view_]; - // Pointer to allow us to grab the VC instance in our validation callback. - __block UIActivityViewController* activityViewController; - id vc_partial_mock = OCMPartialMock(base_view_controller_); [[vc_partial_mock expect] presentViewController:[OCMArg checkWithBlock:^BOOL( UIViewController* viewController) { if ([viewController isKindOfClass:[UIActivityViewController class]]) { - activityViewController = (UIActivityViewController*)viewController; return YES; } return NO;
diff --git a/ios/chrome/browser/widget_kit/OWNERS b/ios/chrome/browser/widget_kit/OWNERS index 93ecef3..c2536df3 100644 --- a/ios/chrome/browser/widget_kit/OWNERS +++ b/ios/chrome/browser/widget_kit/OWNERS
@@ -1 +1,2 @@ javierrobles@chromium.org +rkgibson@google.com
diff --git a/ios/net/crn_http_protocol_handler.mm b/ios/net/crn_http_protocol_handler.mm index 78abb76..6a81e59 100644 --- a/ios/net/crn_http_protocol_handler.mm +++ b/ios/net/crn_http_protocol_handler.mm
@@ -478,9 +478,7 @@ DCHECK_EQ(net_request_, request); // Read data from the socket until no bytes left to read. - uint64_t total_bytes_read = 0; while (bytes_read > 0) { - total_bytes_read += bytes_read; // The NSData will take the ownership of |read_buffer_|. NSData* data = [NSData dataWithBytesNoCopy:read_buffer_.release() length:bytes_read];
diff --git a/ios/web/public/web_state_delegate.h b/ios/web/public/web_state_delegate.h index 10850ff..b2a97a0 100644 --- a/ios/web/public/web_state_delegate.h +++ b/ios/web/public/web_state_delegate.h
@@ -80,26 +80,17 @@ // nil. virtual UIView* GetWebViewContainer(WebState* source); - // Called when iOS13+ context menu is triggered and now it is required to + // Called when the context menu is triggered and now it is required to // provide a UIContextMenuConfiguration to |completion_handler| to generate // the context menu. virtual void ContextMenuConfiguration( WebState* source, const ContextMenuParams& params, - void (^completion_handler)(UIContextMenuConfiguration*)) - API_AVAILABLE(ios(13.0)); - // Called when iOS13+ context menu is ready to be showed. - virtual void ContextMenuDidEnd(WebState* source, const GURL& link_url) - API_AVAILABLE(ios(13.0)); - // Called when iOS13+ context menu will commit with animator. + void (^completion_handler)(UIContextMenuConfiguration*)); + // Called when the context menu will commit with animator. virtual void ContextMenuWillCommitWithAnimator( WebState* source, - const GURL& link_url, - id<UIContextMenuInteractionCommitAnimating> animator) - API_AVAILABLE(ios(13.0)); - // Called when iOS13+ context menu will present. - virtual void ContextMenuWillPresent(WebState* source, const GURL& link_url) - API_AVAILABLE(ios(13.0)); + id<UIContextMenuInteractionCommitAnimating> animator); // UIResponder Form Input APIs, consult Apple's UIResponder documentation for // more info.
diff --git a/ios/web/public/web_state_delegate_bridge.h b/ios/web/public/web_state_delegate_bridge.h index f80000d..5a6cc6d 100644 --- a/ios/web/public/web_state_delegate_bridge.h +++ b/ios/web/public/web_state_delegate_bridge.h
@@ -65,31 +65,18 @@ // Called to know the size of the view containing the WebView. - (UIView*)webViewContainerForWebState:(web::WebState*)webState; -// Called when iOS13+ context menu is triggered and now it is required to -// provide a UIContextMenuConfiguration to |completion_handler| to generate the -// context menu. +// Called when the context menu is triggered and now it is required to provide a +// UIContextMenuConfiguration to |completion_handler| to generate the context +// menu. - (void)webState:(web::WebState*)webState contextMenuConfigurationForParams:(const web::ContextMenuParams&)params - completionHandler: - (void (^)(UIContextMenuConfiguration*))completionHandler - API_AVAILABLE(ios(13.0)); + completionHandler:(void (^)(UIContextMenuConfiguration*)) + completionHandler; -// Called when iOS13+ context menu is ready to be showed. +// Called when the context menu will commit with animator. - (void)webState:(web::WebState*)webState - contextMenuWillPresentForLinkWithURL:(const GURL&)linkURL - API_AVAILABLE(ios(13.0)); - -// Called when iOS13+ context menu will commit with animator. -- (void)webState:(web::WebState*)webState - contextMenuForLinkWithURL:(const GURL&)linkURL - willCommitWithAnimator: - (id<UIContextMenuInteractionCommitAnimating>)animator - API_AVAILABLE(ios(13.0)); - -// Called when iOS13+ context menu will present. -- (void)webState:(web::WebState*)webState - contextMenuDidEndForLinkWithURL:(const GURL&)linkURL - API_AVAILABLE(ios(13.0)); + contextMenuWillCommitWithAnimator: + (id<UIContextMenuInteractionCommitAnimating>)animator; // This API can be used to show custom input views in the web view. - (id<CRWResponderInputView>)webStateInputViewProvider:(web::WebState*)webState; @@ -131,17 +118,10 @@ void ContextMenuConfiguration( WebState* source, const ContextMenuParams& params, - void (^completion_handler)(UIContextMenuConfiguration*)) - API_AVAILABLE(ios(13.0)) override; - void ContextMenuDidEnd(WebState* source, const GURL& link_url) - API_AVAILABLE(ios(13.0)) override; + void (^completion_handler)(UIContextMenuConfiguration*)) override; void ContextMenuWillCommitWithAnimator( WebState* source, - const GURL& link_url, - id<UIContextMenuInteractionCommitAnimating> animator) - API_AVAILABLE(ios(13.0)) override; - void ContextMenuWillPresent(WebState* source, const GURL& link_url) - API_AVAILABLE(ios(13.0)) override; + id<UIContextMenuInteractionCommitAnimating> animator) override; id<CRWResponderInputView> GetResponderInputView(WebState* source) override;
diff --git a/ios/web/web_state/ui/crw_context_menu_controller.mm b/ios/web/web_state/ui/crw_context_menu_controller.mm index 126353a3..4723f33e 100644 --- a/ios/web/web_state/ui/crw_context_menu_controller.mm +++ b/ios/web/web_state/ui/crw_context_menu_controller.mm
@@ -196,6 +196,15 @@ : nil; } +- (void)contextMenuInteraction:(UIContextMenuInteraction*)interaction + willPerformPreviewActionForMenuWithConfiguration: + (UIContextMenuConfiguration*)configuration + animator: + (id<UIContextMenuInteractionCommitAnimating>)animator { + self.webState->GetDelegate()->ContextMenuWillCommitWithAnimator(self.webState, + animator); +} + #pragma mark - Private // Prevents the web view gesture recognizer to get the touch events.
diff --git a/ios/web/web_state/ui/crw_wk_ui_handler.mm b/ios/web/web_state/ui/crw_wk_ui_handler.mm index 99ebbd5..07b4760 100644 --- a/ios/web/web_state/ui/crw_wk_ui_handler.mm +++ b/ios/web/web_state/ui/crw_wk_ui_handler.mm
@@ -182,7 +182,7 @@ contextMenuConfigurationForElement:(WKContextMenuElementInfo*)elementInfo completionHandler: (void (^)(UIContextMenuConfiguration* _Nullable)) - completionHandler API_AVAILABLE(ios(13.0)) { + completionHandler { web::WebStateDelegate* delegate = self.webStateImpl->GetDelegate(); if (!delegate) { completionHandler(nil); @@ -197,41 +197,15 @@ } - (void)webView:(WKWebView*)webView - contextMenuDidEndForElement:(WKContextMenuElementInfo*)elementInfo - API_AVAILABLE(ios(13.0)) { - web::WebStateDelegate* delegate = self.webStateImpl->GetDelegate(); - if (!delegate) { - return; - } - - delegate->ContextMenuDidEnd(self.webStateImpl, - net::GURLWithNSURL(elementInfo.linkURL)); -} - -- (void)webView:(WKWebView*)webView - contextMenuForElement:(nonnull WKContextMenuElementInfo*)elementInfo + contextMenuForElement:(WKContextMenuElementInfo*)elementInfo willCommitWithAnimator: - (nonnull id<UIContextMenuInteractionCommitAnimating>)animator - API_AVAILABLE(ios(13.0)) { + (id<UIContextMenuInteractionCommitAnimating>)animator { web::WebStateDelegate* delegate = self.webStateImpl->GetDelegate(); if (!delegate) { return; } - delegate->ContextMenuWillCommitWithAnimator( - self.webStateImpl, net::GURLWithNSURL(elementInfo.linkURL), animator); -} - -- (void)webView:(WKWebView*)webView - contextMenuWillPresentForElement:(WKContextMenuElementInfo*)elementInfo - API_AVAILABLE(ios(13.0)) { - web::WebStateDelegate* delegate = self.webStateImpl->GetDelegate(); - if (!delegate) { - return; - } - - delegate->ContextMenuWillPresent(self.webStateImpl, - net::GURLWithNSURL(elementInfo.linkURL)); + delegate->ContextMenuWillCommitWithAnimator(self.webStateImpl, animator); } #pragma mark - Helper
diff --git a/ios/web/web_state/web_state_context_menu_bridge_unittest.mm b/ios/web/web_state/web_state_context_menu_bridge_unittest.mm index 49bbd3c..d3ab282 100644 --- a/ios/web/web_state/web_state_context_menu_bridge_unittest.mm +++ b/ios/web/web_state/web_state_context_menu_bridge_unittest.mm
@@ -22,49 +22,27 @@ @property(nonatomic) web::WebState* webState; @property(nonatomic) NSURL* URL; @property(nonatomic) BOOL contextMenuConfigurationNeeded; -@property(nonatomic) BOOL contextMenuWillPresent; @property(nonatomic) BOOL contextMenuWillCommitWithAnimator; -@property(nonatomic) BOOL contextMenuDidEnd; @end @implementation FakeCRWWebStateDelegate - (void)webState:(web::WebState*)webState contextMenuConfigurationForParams:(const web::ContextMenuParams&)params - completionHandler: - (void (^)(UIContextMenuConfiguration*))completionHandler - API_AVAILABLE(ios(13.0)) { + completionHandler:(void (^)(UIContextMenuConfiguration*)) + completionHandler { self.webState = webState; self.URL = net::NSURLWithGURL(params.link_url); self.contextMenuConfigurationNeeded = YES; } - (void)webState:(web::WebState*)webState - contextMenuWillPresentForLinkWithURL:(const GURL&)linkURL - API_AVAILABLE(ios(13.0)) { + contextMenuWillCommitWithAnimator: + (id<UIContextMenuInteractionCommitAnimating>)animator { self.webState = webState; - self.URL = net::NSURLWithGURL(linkURL); - self.contextMenuWillPresent = YES; -} - -- (void)webState:(web::WebState*)webState - contextMenuForLinkWithURL:(const GURL&)linkURL - willCommitWithAnimator: - (id<UIContextMenuInteractionCommitAnimating>)animator - API_AVAILABLE(ios(13.0)) { - self.webState = webState; - self.URL = net::NSURLWithGURL(linkURL); self.contextMenuWillCommitWithAnimator = YES; } -- (void)webState:(web::WebState*)webState - contextMenuDidEndForLinkWithURL:(const GURL&)linkURL - API_AVAILABLE(ios(13.0)) { - self.webState = webState; - self.URL = net::NSURLWithGURL(linkURL); - self.contextMenuDidEnd = YES; -} - @end namespace web { @@ -88,59 +66,33 @@ std::unique_ptr<web::WebStateDelegateBridge> web_state_delegate_bridge_; }; -TEST_F(WebStateContextMenuBridgeTest, IOS13ContextMenuDelegateBridgeTest) { - if (@available(iOS 13, *)) { - WKWebView* web_view = [web_controller() ensureWebViewCreated]; - id<WKUIDelegate> ui_delegate = web_view.UIDelegate; +TEST_F(WebStateContextMenuBridgeTest, ContextMenuDelegateBridgeTest) { + WKWebView* web_view = [web_controller() ensureWebViewCreated]; + id<WKUIDelegate> ui_delegate = web_view.UIDelegate; - NSURL* url = [NSURL URLWithString:@"https://google.com/"]; - id element_info = OCMClassMock([WKContextMenuElementInfo class]); - [[[element_info stub] andReturn:url] linkURL]; + NSURL* url = [NSURL URLWithString:@"https://google.com/"]; + id element_info = OCMClassMock([WKContextMenuElementInfo class]); + [[[element_info stub] andReturn:url] linkURL]; - FakeCRWWebStateDelegate* web_state_delegate = MakeFakeCRWWebStateDelegate(); - [ui_delegate webView:web_view - contextMenuConfigurationForElement:element_info - completionHandler:^(id){ - }]; - EXPECT_EQ(web_state(), web_state_delegate.webState); - EXPECT_NSEQ(url, web_state_delegate.URL); - EXPECT_TRUE(web_state_delegate.contextMenuConfigurationNeeded); - EXPECT_FALSE(web_state_delegate.contextMenuDidEnd); - EXPECT_FALSE(web_state_delegate.contextMenuWillCommitWithAnimator); - EXPECT_FALSE(web_state_delegate.contextMenuWillPresent); + FakeCRWWebStateDelegate* web_state_delegate = MakeFakeCRWWebStateDelegate(); + [ui_delegate webView:web_view + contextMenuConfigurationForElement:element_info + completionHandler:^(id){ + }]; + EXPECT_EQ(web_state(), web_state_delegate.webState); + EXPECT_NSEQ(url, web_state_delegate.URL); + EXPECT_TRUE(web_state_delegate.contextMenuConfigurationNeeded); + EXPECT_FALSE(web_state_delegate.contextMenuWillCommitWithAnimator); - web_state_delegate = MakeFakeCRWWebStateDelegate(); - [ui_delegate webView:web_view contextMenuDidEndForElement:element_info]; - EXPECT_EQ(web_state(), web_state_delegate.webState); - EXPECT_NSEQ(url, web_state_delegate.URL); - EXPECT_FALSE(web_state_delegate.contextMenuConfigurationNeeded); - EXPECT_TRUE(web_state_delegate.contextMenuDidEnd); - EXPECT_FALSE(web_state_delegate.contextMenuWillCommitWithAnimator); - EXPECT_FALSE(web_state_delegate.contextMenuWillPresent); - - web_state_delegate = MakeFakeCRWWebStateDelegate(); - [ui_delegate webView:web_view - contextMenuForElement:element_info - willCommitWithAnimator: - [OCMockObject - mockForProtocol:@protocol(UIContextMenuInteractionDelegate)]]; - EXPECT_EQ(web_state(), web_state_delegate.webState); - EXPECT_NSEQ(url, web_state_delegate.URL); - EXPECT_FALSE(web_state_delegate.contextMenuConfigurationNeeded); - EXPECT_FALSE(web_state_delegate.contextMenuDidEnd); - EXPECT_TRUE(web_state_delegate.contextMenuWillCommitWithAnimator); - EXPECT_FALSE(web_state_delegate.contextMenuWillPresent); - - web_state_delegate = MakeFakeCRWWebStateDelegate(); - [ui_delegate webView:web_view - contextMenuWillPresentForElement:element_info]; - EXPECT_EQ(web_state(), web_state_delegate.webState); - EXPECT_NSEQ(url, web_state_delegate.URL); - EXPECT_FALSE(web_state_delegate.contextMenuConfigurationNeeded); - EXPECT_FALSE(web_state_delegate.contextMenuDidEnd); - EXPECT_FALSE(web_state_delegate.contextMenuWillCommitWithAnimator); - EXPECT_TRUE(web_state_delegate.contextMenuWillPresent); - } + web_state_delegate = MakeFakeCRWWebStateDelegate(); + [ui_delegate webView:web_view + contextMenuForElement:element_info + willCommitWithAnimator: + [OCMockObject + mockForProtocol:@protocol(UIContextMenuInteractionDelegate)]]; + EXPECT_EQ(web_state(), web_state_delegate.webState); + EXPECT_FALSE(web_state_delegate.contextMenuConfigurationNeeded); + EXPECT_TRUE(web_state_delegate.contextMenuWillCommitWithAnimator); } } // namespace web
diff --git a/ios/web/web_state/web_state_delegate.mm b/ios/web/web_state/web_state_delegate.mm index 9158fba..b2e45a7d 100644 --- a/ios/web/web_state/web_state_delegate.mm +++ b/ios/web/web_state/web_state_delegate.mm
@@ -72,23 +72,13 @@ void WebStateDelegate::ContextMenuConfiguration( WebState* source, const ContextMenuParams& params, - void (^completion_handler)(UIContextMenuConfiguration*)) - API_AVAILABLE(ios(13.0)) { + void (^completion_handler)(UIContextMenuConfiguration*)) { completion_handler(nil); } -void WebStateDelegate::ContextMenuDidEnd(WebState* source, const GURL& link_url) - API_AVAILABLE(ios(13.0)) {} - void WebStateDelegate::ContextMenuWillCommitWithAnimator( WebState* source, - const GURL& link_url, - id<UIContextMenuInteractionCommitAnimating> animator) - API_AVAILABLE(ios(13.0)) {} - -void WebStateDelegate::ContextMenuWillPresent(WebState* source, - const GURL& link_url) - API_AVAILABLE(ios(13.0)) {} + id<UIContextMenuInteractionCommitAnimating> animator) {} id<CRWResponderInputView> WebStateDelegate::GetResponderInputView( WebState* source) {
diff --git a/ios/web/web_state/web_state_delegate_bridge.mm b/ios/web/web_state/web_state_delegate_bridge.mm index 5f3282b..dd26b9c 100644 --- a/ios/web/web_state/web_state_delegate_bridge.mm +++ b/ios/web/web_state/web_state_delegate_bridge.mm
@@ -111,8 +111,7 @@ void WebStateDelegateBridge::ContextMenuConfiguration( WebState* source, const ContextMenuParams& params, - void (^completion_handler)(UIContextMenuConfiguration*)) - API_AVAILABLE(ios(13.0)) { + void (^completion_handler)(UIContextMenuConfiguration*)) { if ([delegate_ respondsToSelector:@selector (webState: contextMenuConfigurationForParams:completionHandler:)]) { @@ -124,35 +123,12 @@ } } -void WebStateDelegateBridge::ContextMenuDidEnd(WebState* source, - const GURL& link_url) - API_AVAILABLE(ios(13.0)) { - if ([delegate_ respondsToSelector:@selector(webState: - contextMenuDidEndForLinkWithURL:)]) { - [delegate_ webState:source contextMenuDidEndForLinkWithURL:link_url]; - } -} - void WebStateDelegateBridge::ContextMenuWillCommitWithAnimator( WebState* source, - const GURL& link_url, - id<UIContextMenuInteractionCommitAnimating> animator) - API_AVAILABLE(ios(13.0)) { - if ([delegate_ respondsToSelector:@selector - (webState: - contextMenuForLinkWithURL:willCommitWithAnimator:)]) { - [delegate_ webState:source - contextMenuForLinkWithURL:link_url - willCommitWithAnimator:animator]; - } -} - -void WebStateDelegateBridge::ContextMenuWillPresent(WebState* source, - const GURL& link_url) - API_AVAILABLE(ios(13.0)) { - if ([delegate_ respondsToSelector:@selector - (webState:contextMenuWillPresentForLinkWithURL:)]) { - [delegate_ webState:source contextMenuWillPresentForLinkWithURL:link_url]; + id<UIContextMenuInteractionCommitAnimating> animator) { + if ([delegate_ respondsToSelector:@selector(webState: + contextMenuWillCommitWithAnimator:)]) { + [delegate_ webState:source contextMenuWillCommitWithAnimator:animator]; } }
diff --git a/ios/web_view/internal/cwv_web_view.mm b/ios/web_view/internal/cwv_web_view.mm index f4f675c..629bfdf9 100644 --- a/ios/web_view/internal/cwv_web_view.mm +++ b/ios/web_view/internal/cwv_web_view.mm
@@ -509,9 +509,8 @@ - (void)webState:(web::WebState*)webState contextMenuConfigurationForParams:(const web::ContextMenuParams&)params - completionHandler: - (void (^)(UIContextMenuConfiguration*))completionHandler - API_AVAILABLE(ios(13.0)) { + completionHandler:(void (^)(UIContextMenuConfiguration*)) + completionHandler { SEL selector = @selector(webView: contextMenuConfigurationForElement:completionHandler:); if ([_UIDelegate respondsToSelector:selector]) { @@ -531,36 +530,11 @@ } - (void)webState:(web::WebState*)webState - contextMenuWillPresentForLinkWithURL:(const GURL&)linkURL - API_AVAILABLE(ios(13.0)) { - SEL selector = @selector(webView:contextMenuWillPresentForLinkWithURL:); + contextMenuWillCommitWithAnimator: + (id<UIContextMenuInteractionCommitAnimating>)animator { + SEL selector = @selector(webView:contextMenuWillCommitWithAnimator:); if ([_UIDelegate respondsToSelector:selector]) { - [_UIDelegate webView:self - contextMenuWillPresentForLinkWithURL:net::NSURLWithGURL(linkURL)]; - } -} - -- (void)webState:(web::WebState*)webState - contextMenuForLinkWithURL:(const GURL&)linkURL - willCommitWithAnimator: - (id<UIContextMenuInteractionCommitAnimating>)animator - API_AVAILABLE(ios(13.0)) { - SEL selector = @selector(webView: - contextMenuForLinkWithURL:willCommitWithAnimator:); - if ([_UIDelegate respondsToSelector:selector]) { - [_UIDelegate webView:self - contextMenuForLinkWithURL:net::NSURLWithGURL(linkURL) - willCommitWithAnimator:animator]; - } -} - -- (void)webState:(web::WebState*)webState - contextMenuDidEndForLinkWithURL:(const GURL&)linkURL - API_AVAILABLE(ios(13.0)) { - SEL selector = @selector(webView:contextMenuDidEndForLinkWithURL:); - if ([_UIDelegate respondsToSelector:selector]) { - [_UIDelegate webView:self - contextMenuDidEndForLinkWithURL:net::NSURLWithGURL(linkURL)]; + [_UIDelegate webView:self contextMenuWillCommitWithAnimator:animator]; } }
diff --git a/ios/web_view/public/cwv_ui_delegate.h b/ios/web_view/public/cwv_ui_delegate.h index 7af95a467..dc65c02 100644 --- a/ios/web_view/public/cwv_ui_delegate.h +++ b/ios/web_view/public/cwv_ui_delegate.h
@@ -70,26 +70,13 @@ contextMenuConfigurationForElement:(CWVHTMLElement*)element completionHandler: (void (^)(UIContextMenuConfiguration* _Nullable)) - completionHandler API_AVAILABLE(ios(13.0)); - -// Equivalent of -[WKUIDelegate -// webView:contextMenuWillPresentForElement:]. -- (void)webView:(CWVWebView*)webView - contextMenuWillPresentForLinkWithURL:(NSURL*)linkURL - API_AVAILABLE(ios(13.0)); + completionHandler; // Equivalent of -[WKUIDelegate // webView:contextMenuForElement:willCommitWithAnimator:]. - (void)webView:(CWVWebView*)webView - contextMenuForLinkWithURL:(NSURL*)linkURL - willCommitWithAnimator: - (id<UIContextMenuInteractionCommitAnimating>)animator - API_AVAILABLE(ios(13.0)); - -// Equivalent of -[WKUIDelegate -// webView:contextMenuDidEndForElement:]. -- (void)webView:(CWVWebView*)webView - contextMenuDidEndForLinkWithURL:(NSURL*)linkURL API_AVAILABLE(ios(13.0)); + contextMenuWillCommitWithAnimator: + (id<UIContextMenuInteractionCommitAnimating>)animator; @end
diff --git a/ios/web_view/shell/shell_view_controller.m b/ios/web_view/shell/shell_view_controller.m index 64d87cba..385632bb 100644 --- a/ios/web_view/shell/shell_view_controller.m +++ b/ios/web_view/shell/shell_view_controller.m
@@ -833,8 +833,7 @@ - (void)webView:(CWVWebView*)webView contextMenuConfigurationForElement:(CWVHTMLElement*)element completionHandler:(void (^)(UIContextMenuConfiguration*)) - completionHandler - API_AVAILABLE(ios(13.0)) { + completionHandler { void (^copyHandler)(UIAction*) = ^(UIAction* action) { NSDictionary* item = @{ (NSString*)(kUTTypeURL) : element.hyperlink.absoluteString, @@ -876,24 +875,9 @@ } - (void)webView:(CWVWebView*)webView - contextMenuWillPresentForLinkWithURL:(NSURL*)linkURL - API_AVAILABLE(ios(13.0)) { - NSLog(@"webView:contextMenuWillPresentForLinkWithURL: %@", - linkURL.absoluteString); -} - -- (void)webView:(CWVWebView*)webView - contextMenuForLinkWithURL:(NSURL*)linkURL - willCommitWithAnimator: - (id<UIContextMenuInteractionCommitAnimating>)animator - API_AVAILABLE(ios(13.0)) { - NSLog(@"webView:contextMenuForLinkWithURL:willCommitWithAnimator: %@", - linkURL.absoluteString); -} - -- (void)webView:(CWVWebView*)webView - contextMenuDidEndForLinkWithURL:(NSURL*)linkURL API_AVAILABLE(ios(13.0)) { - NSLog(@"webView:contextMenuDidEndForLinkWithURL: %@", linkURL.absoluteString); + contextMenuWillCommitWithAnimator: + (id<UIContextMenuInteractionCommitAnimating>)animator { + NSLog(@"webView:contextMenuWillCommitWithAnimator:"); } - (void)webView:(CWVWebView*)webView
diff --git a/media/capture/video/mac/sample_buffer_transformer_mac_unittest.mm b/media/capture/video/mac/sample_buffer_transformer_mac_unittest.mm index 3c83dd24..0d4540480 100644 --- a/media/capture/video/mac/sample_buffer_transformer_mac_unittest.mm +++ b/media/capture/video/mac/sample_buffer_transformer_mac_unittest.mm
@@ -187,7 +187,6 @@ int height, int padding) { size_t num_planes = CVPixelBufferGetPlaneCount(pixel_buffer); - size_t padded_size = 0; std::vector<size_t> plane_widths; std::vector<size_t> plane_heights; std::vector<size_t> plane_strides; @@ -201,7 +200,6 @@ plane_heights.push_back(h); plane_widths.push_back(w); plane_strides.push_back(padded_stride); - padded_size += h * padded_stride; } } else { // CVPixelBufferGetPlaneCount returns 0 for non-planar buffers. @@ -209,7 +207,6 @@ size_t plane_stride = CVPixelBufferGetBytesPerRow(pixel_buffer); size_t padded_stride = plane_stride + padding; size_t h = CVPixelBufferGetHeight(pixel_buffer); - padded_size += h * padded_stride; plane_heights.push_back(h); plane_strides.push_back(padded_stride); }
diff --git a/media/gpu/windows/dxva_video_decode_accelerator_win.cc b/media/gpu/windows/dxva_video_decode_accelerator_win.cc index c09bde8..d21dc50 100644 --- a/media/gpu/windows/dxva_video_decode_accelerator_win.cc +++ b/media/gpu/windows/dxva_video_decode_accelerator_win.cc
@@ -42,7 +42,9 @@ #include "build/build_config.h" #include "components/viz/common/resources/resource_format_utils.h" #include "gpu/command_buffer/common/shared_image_usage.h" +#include "gpu/command_buffer/service/shared_image_backing.h" #include "gpu/command_buffer/service/shared_image_backing_d3d.h" +#include "gpu/command_buffer/service/shared_image_backing_gl_image.h" #include "gpu/command_buffer/service/shared_image_factory.h" #include "gpu/config/gpu_driver_bug_workarounds.h" #include "gpu/config/gpu_preferences.h" @@ -1406,10 +1408,7 @@ } bool DXVAVideoDecodeAccelerator::SupportsSharedImagePictureBuffers() const { - // Shared image is needed to display overlays which can be used directly - // by the video processor. - // TODO(crbug.com/1011555): Support for non-bind cases. - return GetPictureBufferMechanism() == PictureBufferMechanism::BIND; + return true; } // static @@ -2676,9 +2675,13 @@ RETURN_AND_NOTIFY_ON_FAILURE(result, "Failed to complete copying surface", PLATFORM_FAILURE, ); + std::vector<scoped_refptr<Picture::ScopedSharedImage>> scoped_shared_images = + GetSharedImagesFromPictureBuffer(picture_buffer); + NotifyPictureReady( picture_buffer->id(), input_buffer_id, picture_buffer->visible_rect(), - picture_buffer->color_space(), picture_buffer->AllowOverlay()); + picture_buffer->color_space(), picture_buffer->AllowOverlay(), + std::move(scoped_shared_images)); { base::AutoLock lock(decoder_lock_); @@ -2733,84 +2736,8 @@ RETURN_AND_NOTIFY_ON_FAILURE(result, "Failed to bind sample to texture", PLATFORM_FAILURE, ); - // Create the DX11 texture backed shared images (texture per plane). - std::vector<scoped_refptr<Picture::ScopedSharedImage>> scoped_shared_images; - if (SupportsSharedImagePictureBuffers()) { - gl::GLImageDXGI* gl_image_dxgi = - gl::GLImageDXGI::FromGLImage(picture_buffer->gl_image().get()); - DCHECK(gl_image_dxgi); - - const size_t textures_per_picture = - picture_buffer->service_texture_ids().size(); - - // Get the viz resource format per texture. - std::array<viz::ResourceFormat, VideoFrame::kMaxPlanes> viz_formats; - { - result = VideoPixelFormatToVizFormat(picture_buffer->pixel_format(), - textures_per_picture, viz_formats); - RETURN_AND_NOTIFY_ON_FAILURE( - result, "Could not convert pixel format to viz format", - PLATFORM_FAILURE, ); - } - - CommandBufferHelper* helper = client_->GetCommandBufferHelper(); - DCHECK(helper); - - for (uint32_t texture_idx = 0; texture_idx < textures_per_picture; - texture_idx++) { - // Usage flags to allow the display compositor to draw from it, video - // to decode, and allow webgl/canvas access. - constexpr uint32_t shared_image_usage = - gpu::SHARED_IMAGE_USAGE_VIDEO_DECODE | gpu::SHARED_IMAGE_USAGE_GLES2 | - gpu::SHARED_IMAGE_USAGE_RASTER | gpu::SHARED_IMAGE_USAGE_DISPLAY | - gpu::SHARED_IMAGE_USAGE_SCANOUT; - - // Create a shared image - // TODO(crbug.com/1011555): Need key shared mutex if shared image is ever - // used by another device. - scoped_refptr<gpu::gles2::TexturePassthrough> gl_texture = - gpu::gles2::TexturePassthrough::CheckedCast(helper->GetTexture( - picture_buffer->service_texture_ids()[texture_idx])); - - // Create a new shared image mailbox. The existing mailbox belonging to - // this |picture_buffer| will be updated when the video frame is created. - const auto& mailbox = gpu::Mailbox::GenerateForSharedImage(); - - auto shared_image = gpu::SharedImageBackingD3D::CreateFromGLTexture( - mailbox, viz_formats[texture_idx], - picture_buffer->texture_size(texture_idx), - picture_buffer->color_space(), kTopLeft_GrSurfaceOrigin, - kPremul_SkAlphaType, shared_image_usage, gl_image_dxgi->texture(), - std::move(gl_texture)); - - // Caller is assumed to provide cleared d3d textures. - shared_image->SetCleared(); - - gpu::SharedImageStub* shared_image_stub = client_->GetSharedImageStub(); - DCHECK(shared_image_stub); - const bool success = shared_image_stub->factory()->RegisterBacking( - std::move(shared_image), /* legacy_mailbox */ true); - if (!success) { - RETURN_AND_NOTIFY_ON_FAILURE(false, "Failed to register shared image", - PLATFORM_FAILURE, ); - } - - auto destroy_shared_image_callback = base::BindPostTask( - main_thread_task_runner_, - base::BindOnce( - shared_image_stub->GetSharedImageDestructionCallback(mailbox), - gpu::SyncToken())); - - // Wrap the factory ref with a scoped shared image. The factory ref - // is used instead of requiring a destruction call-back. - auto scoped_shared_image = - base::MakeRefCounted<Picture::ScopedSharedImage>( - mailbox, GetTextureTarget(), - std::move(destroy_shared_image_callback)); - - scoped_shared_images.push_back(std::move(scoped_shared_image)); - } - } + std::vector<scoped_refptr<Picture::ScopedSharedImage>> scoped_shared_images = + GetSharedImagesFromPictureBuffer(picture_buffer); NotifyPictureReady( picture_buffer->id(), input_buffer_id, picture_buffer->visible_rect(), @@ -3304,6 +3231,95 @@ num_picture_buffers_requested_ = kNumPictureBuffers; } +std::vector<scoped_refptr<Picture::ScopedSharedImage>> +DXVAVideoDecodeAccelerator::GetSharedImagesFromPictureBuffer( + DXVAPictureBuffer* picture_buffer) { + const size_t textures_per_picture = + picture_buffer->service_texture_ids().size(); + + // Get the viz resource format per texture. + std::array<viz::ResourceFormat, VideoFrame::kMaxPlanes> viz_formats; + { + bool result = VideoPixelFormatToVizFormat( + picture_buffer->pixel_format(), textures_per_picture, viz_formats); + RETURN_AND_NOTIFY_ON_FAILURE(result, + "Could not convert pixel format to viz format", + PLATFORM_FAILURE, {}); + } + + std::vector<scoped_refptr<Picture::ScopedSharedImage>> scoped_shared_images; + CommandBufferHelper* helper = client_->GetCommandBufferHelper(); + DCHECK(helper); + + for (uint32_t texture_idx = 0; texture_idx < textures_per_picture; + texture_idx++) { + // Usage flags to allow the display compositor to draw from it, video + // to decode, and allow webgl/canvas access. + constexpr uint32_t shared_image_usage = + gpu::SHARED_IMAGE_USAGE_VIDEO_DECODE | gpu::SHARED_IMAGE_USAGE_GLES2 | + gpu::SHARED_IMAGE_USAGE_RASTER | gpu::SHARED_IMAGE_USAGE_DISPLAY | + gpu::SHARED_IMAGE_USAGE_SCANOUT; + + // Create a shared image + // TODO(crbug.com/1011555): Need key shared mutex if shared image is ever + // used by another device. + scoped_refptr<gpu::gles2::TexturePassthrough> gl_texture = + gpu::gles2::TexturePassthrough::CheckedCast(helper->GetTexture( + picture_buffer->service_texture_ids()[texture_idx])); + + // Create a new shared image mailbox. The existing mailbox belonging to + // this |picture_buffer| will be updated when the video frame is created. + const auto& mailbox = gpu::Mailbox::GenerateForSharedImage(); + + std::unique_ptr<gpu::SharedImageBacking> shared_image; + // Check if this picture buffer has a DX11 texture. + gl::GLImageDXGI* gl_image_dxgi = + gl::GLImageDXGI::FromGLImage(picture_buffer->gl_image().get()); + if (gl_image_dxgi) { + shared_image = gpu::SharedImageBackingD3D::CreateFromGLTexture( + mailbox, viz_formats[texture_idx], + picture_buffer->texture_size(texture_idx), + picture_buffer->color_space(), kTopLeft_GrSurfaceOrigin, + kPremul_SkAlphaType, shared_image_usage, gl_image_dxgi->texture(), + std::move(gl_texture)); + } else { + shared_image = gpu::SharedImageBackingGLImage::CreateFromGLTexture( + picture_buffer->gl_image(), mailbox, viz_formats[texture_idx], + picture_buffer->size(), picture_buffer->color_space(), + kTopLeft_GrSurfaceOrigin, kPremul_SkAlphaType, shared_image_usage, + GetTextureTarget(), std::move(gl_texture)); + } + + DCHECK(shared_image); + // Caller is assumed to provide cleared d3d textures. + shared_image->SetCleared(); + + gpu::SharedImageStub* shared_image_stub = client_->GetSharedImageStub(); + DCHECK(shared_image_stub); + const bool success = shared_image_stub->factory()->RegisterBacking( + std::move(shared_image), /* legacy_mailbox */ true); + if (!success) { + RETURN_AND_NOTIFY_ON_FAILURE(false, "Failed to register shared image", + PLATFORM_FAILURE, {}); + } + + auto destroy_shared_image_callback = base::BindPostTask( + main_thread_task_runner_, + base::BindOnce( + shared_image_stub->GetSharedImageDestructionCallback(mailbox), + gpu::SyncToken())); + + // Wrap the factory ref with a scoped shared image. The factory ref + // is used instead of requiring a destruction call-back. + auto scoped_shared_image = base::MakeRefCounted<Picture::ScopedSharedImage>( + mailbox, GetTextureTarget(), std::move(destroy_shared_image_callback)); + + scoped_shared_images.push_back(std::move(scoped_shared_image)); + } + + return scoped_shared_images; +} + DXVAVideoDecodeAccelerator::PictureBufferMechanism DXVAVideoDecodeAccelerator::GetPictureBufferMechanism() const { if (use_fp16_)
diff --git a/media/gpu/windows/dxva_video_decode_accelerator_win.h b/media/gpu/windows/dxva_video_decode_accelerator_win.h index b8632891..39a3d118 100644 --- a/media/gpu/windows/dxva_video_decode_accelerator_win.h +++ b/media/gpu/windows/dxva_video_decode_accelerator_win.h
@@ -38,6 +38,7 @@ namespace gl { class GLContext; +class GLImageDXGI; } namespace gpu { @@ -415,6 +416,13 @@ // |num_picture_buffers_requested_|. void DisableSharedTextureSupport(); + // Creates ScopedSharedImages for the provided PictureBuffer. If the buffer + // has a GLImageDXGI this function will create SharedImageBackingD3D using the + // DX11 texture. Otherwise it will create thin SharedImageBackingGLImage + // wrappers around the existing textures in |picture_buffer|. + std::vector<scoped_refptr<Picture::ScopedSharedImage>> + GetSharedImagesFromPictureBuffer(DXVAPictureBuffer* picture_buffer); + uint32_t GetTextureTarget() const; PictureBufferMechanism GetPictureBufferMechanism() const;
diff --git a/net/base/features.cc b/net/base/features.cc index 549f376..672f24b 100644 --- a/net/base/features.cc +++ b/net/base/features.cc
@@ -89,6 +89,9 @@ const base::Feature kEnableTLS13EarlyData{"EnableTLS13EarlyData", base::FEATURE_DISABLED_BY_DEFAULT}; +const base::Feature kEncryptedClientHello{"EncryptedClientHello", + base::FEATURE_DISABLED_BY_DEFAULT}; + const base::Feature kNetworkQualityEstimator{"NetworkQualityEstimator", base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/net/base/features.h b/net/base/features.h index e516e675..fcdb5c4 100644 --- a/net/base/features.h +++ b/net/base/features.h
@@ -34,9 +34,6 @@ // origin requests are restricted to contain at most the source origin. NET_EXPORT extern const base::Feature kCapReferrerToOriginOnCrossOrigin; -// Enables TLS 1.3 early data. -NET_EXPORT extern const base::Feature kEnableTLS13EarlyData; - // Support for altering the parameters used for DNS transaction timeout. See // ResolveContext::SecureTransactionTimeout(). NET_EXPORT extern const base::Feature kDnsTransactionDynamicTimeouts; @@ -148,6 +145,16 @@ NET_EXPORT extern const base::FeatureParam<int> kUseDnsHttpsSvcbExtraTimePercent; +// Enables TLS 1.3 early data. +NET_EXPORT extern const base::Feature kEnableTLS13EarlyData; + +// Enables the TLS Encrypted ClientHello feature. +// https://datatracker.ietf.org/doc/html/draft-ietf-tls-esni-13 +// +// TODO(https://crbug.com/1091403): This flag does not currently do much yet. +// ECH is still in development. +NET_EXPORT extern const base::Feature kEncryptedClientHello; + // Enables optimizing the network quality estimation algorithms in network // quality estimator (NQE). NET_EXPORT extern const base::Feature kNetworkQualityEstimator;
diff --git a/net/cert/cert_verify_proc_mac.cc b/net/cert/cert_verify_proc_mac.cc index 909c4ac..b4563ba 100644 --- a/net/cert/cert_verify_proc_mac.cc +++ b/net/cert/cert_verify_proc_mac.cc
@@ -1058,7 +1058,6 @@ // error was due to an unsupported key size. bool policy_failed = false; bool policy_fail_already_mapped = false; - bool weak_key_or_signature_algorithm = false; // As of macOS 10.13, if |trust_result| (from SecTrustGetResult) returns // kSecTrustResultInvalid, subsequent invocations of SecTrust APIs may @@ -1130,7 +1129,6 @@ CertStatus mapped_status = 0; if (policy_failed && status_code == CSSMERR_TP_INVALID_CERTIFICATE) { mapped_status = CERT_STATUS_WEAK_SIGNATURE_ALGORITHM; - weak_key_or_signature_algorithm = true; policy_fail_already_mapped = true; } else if (base::mac::IsOS10_12() && policy_failed && (flags & CertVerifyProc::VERIFY_REV_CHECKING_ENABLED) && @@ -1146,7 +1144,6 @@ } else { mapped_status = CertStatusFromOSStatus(status_code); if (mapped_status == CERT_STATUS_WEAK_KEY) { - weak_key_or_signature_algorithm = true; policy_fail_already_mapped = true; } }
diff --git a/net/socket/ssl_client_socket_impl.cc b/net/socket/ssl_client_socket_impl.cc index f6ba903..daac901 100644 --- a/net/socket/ssl_client_socket_impl.cc +++ b/net/socket/ssl_client_socket_impl.cc
@@ -912,9 +912,11 @@ host_and_port_, &client_cert_, &client_private_key_); } - // TODO(https://crbug.com/1091403): Also enable ECH GREASE, gated on SSLConfig - // or a base::Feature, for when we don't have an ECHConfig. + if (base::FeatureList::IsEnabled(features::kEncryptedClientHello)) { + SSL_set_enable_ech_grease(ssl_.get(), 1); + } if (!ssl_config_.ech_config_list.empty()) { + DCHECK(base::FeatureList::IsEnabled(features::kEncryptedClientHello)); net_log_.AddEvent(NetLogEventType::SSL_ECH_CONFIG_LIST, [&] { base::Value dict(base::Value::Type::DICTIONARY); dict.SetKey("bytes", NetLogBinaryValue(ssl_config_.ech_config_list));
diff --git a/net/socket/ssl_client_socket_unittest.cc b/net/socket/ssl_client_socket_unittest.cc index abcc990..675f010 100644 --- a/net/socket/ssl_client_socket_unittest.cc +++ b/net/socket/ssl_client_socket_unittest.cc
@@ -5544,6 +5544,9 @@ } TEST_F(SSLClientSocketTest, ECH) { + base::test::ScopedFeatureList feature_list; + feature_list.InitAndEnableFeature(features::kEncryptedClientHello); + SSLServerConfig server_config; SSLConfig client_config; server_config.ech_keys = MakeTestECHKeys( @@ -5599,6 +5602,9 @@ } TEST_F(SSLClientSocketTest, ECHWrongKeys) { + base::test::ScopedFeatureList feature_list; + feature_list.InitAndEnableFeature(features::kEncryptedClientHello); + std::vector<uint8_t> ech_config_list1, ech_config_list2; bssl::UniquePtr<SSL_ECH_KEYS> keys1 = MakeTestECHKeys("public.example", /*max_name_len=*/64, &ech_config_list1); @@ -5625,6 +5631,9 @@ } TEST_F(SSLClientSocketTest, InvalidECHConfigList) { + base::test::ScopedFeatureList feature_list; + feature_list.InitAndEnableFeature(features::kEncryptedClientHello); + ASSERT_TRUE( StartEmbeddedTestServer(EmbeddedTestServer::CERT_OK, SSLServerConfig())); @@ -5637,6 +5646,55 @@ EXPECT_THAT(rv, IsError(ERR_INVALID_ECH_CONFIG_LIST)); } +// Test that, if no ECHConfigList is available, the client sends ECH GREASE. +TEST_F(SSLClientSocketTest, ECHGreaseEnabled) { + base::test::ScopedFeatureList feature_list; + feature_list.InitAndEnableFeature(features::kEncryptedClientHello); + + // Configure the server to expect an ECH extension. + bool ran_callback = false; + SSLServerConfig server_config; + server_config.client_hello_callback_for_testing = + base::BindLambdaForTesting([&](const SSL_CLIENT_HELLO* client_hello) { + const uint8_t* data; + size_t len; + EXPECT_TRUE(SSL_early_callback_ctx_extension_get( + client_hello, TLSEXT_TYPE_encrypted_client_hello, &data, &len)); + ran_callback = true; + }); + ASSERT_TRUE( + StartEmbeddedTestServer(EmbeddedTestServer::CERT_OK, server_config)); + int rv; + ASSERT_TRUE(CreateAndConnectSSLClientSocket(SSLConfig(), &rv)); + EXPECT_THAT(rv, IsOk()); + EXPECT_TRUE(ran_callback); +} + +// Test that, if the feature flag is disabled, the client does not send ECH +// GREASE. +TEST_F(SSLClientSocketTest, ECHGreaseDisabled) { + base::test::ScopedFeatureList feature_list; + feature_list.InitAndDisableFeature(features::kEncryptedClientHello); + + // Configure the server not to expect an ECH extension. + bool ran_callback = false; + SSLServerConfig server_config; + server_config.client_hello_callback_for_testing = + base::BindLambdaForTesting([&](const SSL_CLIENT_HELLO* client_hello) { + const uint8_t* data; + size_t len; + EXPECT_FALSE(SSL_early_callback_ctx_extension_get( + client_hello, TLSEXT_TYPE_encrypted_client_hello, &data, &len)); + ran_callback = true; + }); + ASSERT_TRUE( + StartEmbeddedTestServer(EmbeddedTestServer::CERT_OK, server_config)); + int rv; + ASSERT_TRUE(CreateAndConnectSSLClientSocket(SSLConfig(), &rv)); + EXPECT_THAT(rv, IsOk()); + EXPECT_TRUE(ran_callback); +} + class TLS13DowngradeTest : public SSLClientSocketTest, public ::testing::WithParamInterface<
diff --git a/net/socket/ssl_server_socket_impl.cc b/net/socket/ssl_server_socket_impl.cc index 4bed18d..fc9b766 100644 --- a/net/socket/ssl_server_socket_impl.cc +++ b/net/socket/ssl_server_socket_impl.cc
@@ -9,7 +9,6 @@ #include "base/bind.h" #include "base/callback_helpers.h" -#include "base/lazy_instance.h" #include "base/logging.h" #include "base/memory/weak_ptr.h" #include "base/strings/string_util.h" @@ -43,27 +42,6 @@ // overlap with any value of the net::Error range, including net::OK). const int kSSLServerSocketNoPendingResult = 1; -class SocketDataIndex { - public: - static SocketDataIndex* GetInstance(); - SocketDataIndex() { - ssl_socket_data_index_ = - SSL_get_ex_new_index(0, nullptr, nullptr, nullptr, nullptr); - } - - // This is the index used with SSL_get_ex_data to retrieve the owner - // SSLServerSocketImpl object from an SSL instance. - int ssl_socket_data_index_; -}; - -base::LazyInstance<SocketDataIndex>::Leaky g_ssl_socket_data_index_ = - LAZY_INSTANCE_INITIALIZER; - -// static -SocketDataIndex* SocketDataIndex::GetInstance() { - return g_ssl_socket_data_index_.Pointer(); -} - } // namespace class SSLServerContextImpl::SocketImpl : public SSLServerSocket, @@ -121,6 +99,8 @@ int64_t GetTotalReceivedBytes() const override; void ApplySocketTag(const SocketTag& tag) override; + static SocketImpl* FromSSL(SSL* ssl); + static ssl_verify_result_t CertVerifyCallback(SSL* ssl, uint8_t* out_alert); ssl_verify_result_t CertVerifyCallbackImpl(uint8_t* out_alert); @@ -161,6 +141,9 @@ unsigned in_len, void* arg); + static ssl_select_cert_result_t SelectCertificateCallback( + const SSL_CLIENT_HELLO* client_hello); + // SocketBIOAdapter::Delegate implementation. void OnReadReady() override; void OnWriteReady() override; @@ -237,11 +220,7 @@ transport_socket_(std::move(transport_socket)), next_handshake_state_(STATE_NONE), completed_handshake_(false), - negotiated_protocol_(kProtoUnknown) { - ssl_.reset(SSL_new(context_->ssl_ctx_.get())); - SSL_set_app_data(ssl_.get(), this); - SSL_set_shed_handshake_config(ssl_.get(), 1); -} + negotiated_protocol_(kProtoUnknown) {} SSLServerContextImpl::SocketImpl::~SocketImpl() { if (ssl_) { @@ -269,13 +248,8 @@ uint16_t algorithm, const uint8_t* in, size_t in_len) { - DCHECK(ssl); - SSLServerContextImpl::SocketImpl* socket = - static_cast<SSLServerContextImpl::SocketImpl*>(SSL_get_ex_data( - ssl, SocketDataIndex::GetInstance()->ssl_socket_data_index_)); - DCHECK(socket); - return socket->PrivateKeySignCallback(out, out_len, max_out, algorithm, in, - in_len); + return FromSSL(ssl)->PrivateKeySignCallback(out, out_len, max_out, algorithm, + in, in_len); } // static @@ -296,12 +270,7 @@ uint8_t* out, size_t* out_len, size_t max_out) { - DCHECK(ssl); - SSLServerContextImpl::SocketImpl* socket = - static_cast<SSLServerContextImpl::SocketImpl*>(SSL_get_ex_data( - ssl, SocketDataIndex::GetInstance()->ssl_socket_data_index_)); - DCHECK(socket); - return socket->PrivateKeyCompleteCallback(out, out_len, max_out); + return FromSSL(ssl)->PrivateKeyCompleteCallback(out, out_len, max_out); } ssl_private_key_result_t @@ -360,9 +329,7 @@ const uint8_t* in, unsigned in_len, void* arg) { - SSLServerContextImpl::SocketImpl* socket = - static_cast<SSLServerContextImpl::SocketImpl*>(SSL_get_ex_data( - ssl, SocketDataIndex::GetInstance()->ssl_socket_data_index_)); + SSLServerContextImpl::SocketImpl* socket = FromSSL(ssl); // Iterate over the server protocols in preference order. for (NextProto server_proto : @@ -399,6 +366,17 @@ return SSL_TLSEXT_ERR_NOACK; } +ssl_select_cert_result_t +SSLServerContextImpl::SocketImpl::SelectCertificateCallback( + const SSL_CLIENT_HELLO* client_hello) { + SSLServerContextImpl::SocketImpl* socket = FromSSL(client_hello->ssl); + const SSLServerConfig& config = socket->context_->ssl_server_config_; + if (!config.client_hello_callback_for_testing.is_null()) { + config.client_hello_callback_for_testing.Run(client_hello); + } + return ssl_select_cert_success; +} + int SSLServerContextImpl::SocketImpl::Handshake( CompletionOnceCallback callback) { net_log_.BeginEvent(NetLogEventType::SSL_SERVER_HANDSHAKE); @@ -828,11 +806,12 @@ crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); - if (!ssl_ || - !SSL_set_ex_data(ssl_.get(), - SocketDataIndex::GetInstance()->ssl_socket_data_index_, - this)) + ssl_.reset(SSL_new(context_->ssl_ctx_.get())); + if (!ssl_ || !SSL_set_app_data(ssl_.get(), this)) { return ERR_UNEXPECTED; + } + + SSL_set_shed_handshake_config(ssl_.get(), 1); // Set certificate and private key. if (context_->pkey_) { @@ -878,12 +857,18 @@ return OK; } +SSLServerContextImpl::SocketImpl* SSLServerContextImpl::SocketImpl::FromSSL( + SSL* ssl) { + SocketImpl* socket = reinterpret_cast<SocketImpl*>(SSL_get_app_data(ssl)); + DCHECK(socket); + return socket; +} + // static ssl_verify_result_t SSLServerContextImpl::SocketImpl::CertVerifyCallback( SSL* ssl, uint8_t* out_alert) { - SocketImpl* socket = reinterpret_cast<SocketImpl*>(SSL_get_app_data(ssl)); - return socket->CertVerifyCallbackImpl(out_alert); + return FromSSL(ssl)->CertVerifyCallbackImpl(out_alert); } ssl_verify_result_t SSLServerContextImpl::SocketImpl::CertVerifyCallbackImpl( @@ -1068,6 +1053,9 @@ CHECK(SSL_CTX_set1_ech_keys(ssl_ctx_.get(), ssl_server_config_.ech_keys.get())); } + + SSL_CTX_set_select_certificate_cb(ssl_ctx_.get(), + &SocketImpl::SelectCertificateCallback); } SSLServerContextImpl::~SSLServerContextImpl() = default;
diff --git a/net/ssl/ssl_server_config.h b/net/ssl/ssl_server_config.h index ae5da3e..6013422 100644 --- a/net/ssl/ssl_server_config.h +++ b/net/ssl/ssl_server_config.h
@@ -10,6 +10,7 @@ #include <utility> #include <vector> +#include "base/callback.h" #include "base/containers/flat_map.h" #include "net/base/net_export.h" #include "net/socket/next_proto.h" @@ -118,6 +119,10 @@ // handshake. std::vector<uint8_t> signed_cert_timestamp_list; + // If specified, called at the start of each connection with the ClientHello. + base::RepeatingCallback<void(const SSL_CLIENT_HELLO*)> + client_hello_callback_for_testing; + // This is a workaround for BoringSSL's scopers not being copyable. See // https://crbug.com/boringssl/431. class NET_EXPORT ECHKeysContainer {
diff --git a/remoting/host/BUILD.gn b/remoting/host/BUILD.gn index dac7ada..e3fa3f3 100644 --- a/remoting/host/BUILD.gn +++ b/remoting/host/BUILD.gn
@@ -465,7 +465,6 @@ if (is_linux && !is_chromeos_lacros) { sources += [ - "desktop_resizer_linux.cc", "linux/audio_pipe_reader.cc", "linux/audio_pipe_reader.h", "linux/certificate_watcher.cc", @@ -481,7 +480,7 @@ } } - if (use_x11 && ((!is_chromeos_ash && !is_chromeos_lacros) || !use_ozone)) { + if (use_x11 && !is_chromeos_ash && !is_chromeos_lacros) { sources += [ "desktop_display_info_loader_x11.cc", "desktop_resizer_x11.cc", @@ -498,11 +497,11 @@ } } - if (use_ozone && !is_chromeos_ash && !is_chromeos_lacros) { - sources += [ - "desktop_resizer_ozone.cc", - "desktop_resizer_ozone.h", - ] + if (is_linux && (!use_x11 || is_chromeos_ash || is_chromeos_lacros)) { + # On Linux, exactly one of desktop_resizer_{linux,x11}.cc should be + # compiled in. The _linux version is a no-op and should be used on + # platforms without X11. + sources += [ "desktop_resizer_linux.cc" ] } if (is_linux && !is_chromeos_lacros) {
diff --git a/remoting/host/desktop_resizer_linux.cc b/remoting/host/desktop_resizer_linux.cc index d00697c..dd029d0 100644 --- a/remoting/host/desktop_resizer_linux.cc +++ b/remoting/host/desktop_resizer_linux.cc
@@ -8,28 +8,44 @@ #include "base/notreached.h" -#if defined(USE_X11) -#include "remoting/host/desktop_resizer_x11.h" -#endif - -#if defined(USE_OZONE) -#include "remoting/host/desktop_resizer_ozone.h" -#include "ui/base/ui_base_features.h" -#endif - namespace remoting { +namespace { + +// DesktopResizer implementation for Linux platforms where +// X11 is not enabled. +class DesktopResizerLinux : public DesktopResizer { + public: + DesktopResizerLinux() = default; + DesktopResizerLinux(const DesktopResizerLinux&) = delete; + DesktopResizerLinux& operator=(const DesktopResizerLinux&) = delete; + ~DesktopResizerLinux() override = default; + + ScreenResolution GetCurrentResolution() override { + NOTIMPLEMENTED(); + return ScreenResolution(); + } + + std::list<ScreenResolution> GetSupportedResolutions( + const ScreenResolution& preferred) override { + NOTIMPLEMENTED(); + return std::list<ScreenResolution>(); + } + + void SetResolution(const ScreenResolution& resolution) override { + NOTIMPLEMENTED(); + } + + void RestoreResolution(const ScreenResolution& original) override { + NOTIMPLEMENTED(); + } +}; + +} // namespace + +// static std::unique_ptr<DesktopResizer> DesktopResizer::Create() { -#if defined(USE_OZONE) - if (features::IsUsingOzonePlatform()) - return std::make_unique<DesktopResizerOzone>(); -#endif -#if defined(USE_X11) - return std::make_unique<DesktopResizerX11>(); -#else - NOTREACHED(); - return nullptr; -#endif + return std::make_unique<DesktopResizerLinux>(); } } // namespace remoting
diff --git a/remoting/host/desktop_resizer_ozone.cc b/remoting/host/desktop_resizer_ozone.cc deleted file mode 100644 index 35a5133..0000000 --- a/remoting/host/desktop_resizer_ozone.cc +++ /dev/null
@@ -1,41 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "remoting/host/desktop_resizer_ozone.h" - -#include "build/build_config.h" - -namespace remoting { - -DesktopResizerOzone::DesktopResizerOzone() = default; - -DesktopResizerOzone::~DesktopResizerOzone() = default; - -ScreenResolution DesktopResizerOzone::GetCurrentResolution() { - NOTIMPLEMENTED(); - return ScreenResolution(); -} - -std::list<ScreenResolution> DesktopResizerOzone::GetSupportedResolutions( - const ScreenResolution& preferred) { - NOTIMPLEMENTED(); - return std::list<ScreenResolution>(); -} - -void DesktopResizerOzone::SetResolution(const ScreenResolution& resolution) { - NOTIMPLEMENTED(); -} - -void DesktopResizerOzone::RestoreResolution(const ScreenResolution& original) {} - -// To avoid multiple definitions when use_x11 && use_ozone is true, disable this -// factory method for OS_LINUX as Linux has a factory method that decides what -// desktopresizer to use based on IsUsingOzonePlatform feature flag. -#if !defined(OS_LINUX) && !defined(OS_CHROMEOS) -std::unique_ptr<DesktopResizer> DesktopResizer::Create() { - return base::WrapUnique(new DesktopResizerOzone); -} -#endif - -} // namespace remoting
diff --git a/remoting/host/desktop_resizer_ozone.h b/remoting/host/desktop_resizer_ozone.h deleted file mode 100644 index 47e1e77..0000000 --- a/remoting/host/desktop_resizer_ozone.h +++ /dev/null
@@ -1,32 +0,0 @@ -// Copyright 2020 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef REMOTING_HOST_DESKTOP_RESIZER_OZONE_H_ -#define REMOTING_HOST_DESKTOP_RESIZER_OZONE_H_ - -#include "base/macros.h" -#include "base/memory/ptr_util.h" -#include "base/notreached.h" -#include "remoting/host/desktop_resizer.h" - -namespace remoting { - -class DesktopResizerOzone : public DesktopResizer { - public: - DesktopResizerOzone(); - DesktopResizerOzone(const DesktopResizerOzone&) = delete; - DesktopResizerOzone& operator=(const DesktopResizerOzone&) = delete; - ~DesktopResizerOzone() override; - - // DesktopResizer: - ScreenResolution GetCurrentResolution() override; - std::list<ScreenResolution> GetSupportedResolutions( - const ScreenResolution& preferred) override; - void SetResolution(const ScreenResolution& resolution) override; - void RestoreResolution(const ScreenResolution& original) override; -}; - -} // namespace remoting - -#endif // REMOTING_HOST_DESKTOP_RESIZER_OZONE_H_
diff --git a/remoting/host/desktop_resizer_x11.cc b/remoting/host/desktop_resizer_x11.cc index a1c4df5..85e9e1d 100644 --- a/remoting/host/desktop_resizer_x11.cc +++ b/remoting/host/desktop_resizer_x11.cc
@@ -4,7 +4,8 @@ #include "remoting/host/desktop_resizer_x11.h" -#include <string.h> +#include <memory> +#include <string> #include "base/command_line.h" #include "base/cxx17_backports.h" @@ -300,4 +301,9 @@ }); } +// static +std::unique_ptr<DesktopResizer> DesktopResizer::Create() { + return std::make_unique<DesktopResizerX11>(); +} + } // namespace remoting
diff --git a/storage/browser/quota/quota_callbacks.h b/storage/browser/quota/quota_callbacks.h index 36013d11..d64ab3d 100644 --- a/storage/browser/quota/quota_callbacks.h +++ b/storage/browser/quota/quota_callbacks.h
@@ -15,7 +15,7 @@ #include "base/callback.h" #include "base/containers/contains.h" -#include "components/services/storage/public/cpp/buckets/bucket_info.h" +#include "components/services/storage/public/cpp/buckets/bucket_locator.h" #include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/blink/public/mojom/quota/quota_types.mojom-forward.h" @@ -43,13 +43,13 @@ base::OnceCallback<void(blink::mojom::QuotaStatusCode, int64_t)>; using StatusCallback = base::OnceCallback<void(blink::mojom::QuotaStatusCode)>; using GetBucketsCallback = - base::OnceCallback<void(const std::set<BucketInfo>& buckets, + base::OnceCallback<void(const std::set<BucketLocator>& buckets, blink::mojom::StorageType type)>; using GetStorageKeysCallback = base::OnceCallback<void(const std::set<blink::StorageKey>& storage_keys)>; using GetUsageInfoCallback = base::OnceCallback<void(UsageInfoEntries)>; using GetBucketCallback = - base::OnceCallback<void(const absl::optional<BucketInfo>& bucket_info)>; + base::OnceCallback<void(const absl::optional<BucketLocator>& bucket_info)>; // Simple template wrapper for a callback queue. template <typename CallbackType, typename... Args>
diff --git a/storage/browser/quota/quota_database.cc b/storage/browser/quota/quota_database.cc index 328c009..0c541155 100644 --- a/storage/browser/quota/quota_database.cc +++ b/storage/browser/quota/quota_database.cc
@@ -574,7 +574,7 @@ return true; } -QuotaErrorOr<BucketInfo> QuotaDatabase::GetLRUBucket( +QuotaErrorOr<BucketLocator> QuotaDatabase::GetLRUBucket( StorageType type, const std::set<BucketId>& bucket_exceptions, SpecialStoragePolicy* special_storage_policy) { @@ -585,8 +585,7 @@ // clang-format off static constexpr char kSql[] = - "SELECT id, storage_key, name, expiration, quota " - "FROM buckets " + "SELECT id, storage_key, name FROM buckets " "WHERE type = ? " "ORDER BY last_accessed"; // clang-format on @@ -612,9 +611,8 @@ special_storage_policy->IsStorageUnlimited(read_gurl))) { continue; } - return BucketInfo(read_bucket_id, std::move(read_storage_key).value(), type, - statement.ColumnString(2), statement.ColumnTime(3), - statement.ColumnInt(4)); + return BucketLocator(read_bucket_id, std::move(read_storage_key).value(), + type, statement.ColumnString(2) == kDefaultBucketName); } return QuotaError::kNotFound; } @@ -643,7 +641,7 @@ return storage_keys; } -QuotaErrorOr<std::set<BucketInfo>> QuotaDatabase::GetBucketsModifiedBetween( +QuotaErrorOr<std::set<BucketLocator>> QuotaDatabase::GetBucketsModifiedBetween( StorageType type, base::Time begin, base::Time end) { @@ -656,7 +654,7 @@ DCHECK(end != base::Time()); // clang-format off static constexpr char kSql[] = - "SELECT id, storage_key, name, expiration, quota FROM buckets " + "SELECT id, storage_key, name FROM buckets " "WHERE type = ? AND last_modified >= ? AND last_modified < ?"; // clang-format on @@ -665,15 +663,15 @@ statement.BindTime(1, begin); statement.BindTime(2, end); - std::set<BucketInfo> buckets; + std::set<BucketLocator> buckets; while (statement.Step()) { absl::optional<StorageKey> read_storage_key = StorageKey::Deserialize(statement.ColumnString(1)); if (!read_storage_key.has_value()) continue; buckets.emplace(BucketId(statement.ColumnInt64(0)), - read_storage_key.value(), type, statement.ColumnString(2), - statement.ColumnTime(3), statement.ColumnInt(4)); + read_storage_key.value(), type, + statement.ColumnString(2) == kDefaultBucketName); } return buckets; }
diff --git a/storage/browser/quota/quota_database.h b/storage/browser/quota/quota_database.h index 5864a9a..b825975 100644 --- a/storage/browser/quota/quota_database.h +++ b/storage/browser/quota/quota_database.h
@@ -188,10 +188,10 @@ // Deletes the specified bucket. bool DeleteBucketInfo(BucketId bucket_id); - // Returns the BucketInfo for the least recently used bucket. Will exclude + // Returns the BucketLocator for the least recently used bucket. Will exclude // buckets with ids in `bucket_exceptions` and origins that have the special // unlimited storage policy. Returns a QuotaError if the operation has failed. - QuotaErrorOr<BucketInfo> GetLRUBucket( + QuotaErrorOr<BucketLocator> GetLRUBucket( blink::mojom::StorageType type, const std::set<BucketId>& bucket_exceptions, SpecialStoragePolicy* special_storage_policy); @@ -202,7 +202,7 @@ // Returns a set of buckets that have been modified since the `begin` and // until the `end`. Returns a QuotaError if the operations has failed. - QuotaErrorOr<std::set<BucketInfo>> GetBucketsModifiedBetween( + QuotaErrorOr<std::set<BucketLocator>> GetBucketsModifiedBetween( blink::mojom::StorageType type, base::Time begin, base::Time end);
diff --git a/storage/browser/quota/quota_database_unittest.cc b/storage/browser/quota/quota_database_unittest.cc index 0a82637c..54d9a64 100644 --- a/storage/browser/quota/quota_database_unittest.cc +++ b/storage/browser/quota/quota_database_unittest.cc
@@ -503,7 +503,7 @@ EXPECT_TRUE(EnsureOpened(&db, EnsureOpenedMode::kCreateIfNotFound)); std::set<BucketId> bucket_exceptions; - QuotaErrorOr<BucketInfo> result = + QuotaErrorOr<BucketLocator> result = db.GetLRUBucket(kTemp, bucket_exceptions, nullptr); EXPECT_FALSE(result.ok()); EXPECT_EQ(result.error(), QuotaError::kNotFound); @@ -654,10 +654,10 @@ QuotaDatabase db(use_in_memory_db() ? base::FilePath() : DbPath()); EXPECT_TRUE(EnsureOpened(&db, EnsureOpenedMode::kCreateIfNotFound)); - QuotaErrorOr<std::set<BucketInfo>> result = + QuotaErrorOr<std::set<BucketLocator>> result = db.GetBucketsModifiedBetween(kTemp, base::Time(), base::Time::Max()); EXPECT_TRUE(result.ok()); - std::set<BucketInfo> buckets = result.value(); + std::set<BucketLocator> buckets = result.value(); EXPECT_TRUE(buckets.empty()); QuotaErrorOr<BucketInfo> result1 = db.CreateBucketForTesting( @@ -699,30 +699,30 @@ EXPECT_TRUE(result.ok()); buckets = result.value(); EXPECT_EQ(3U, buckets.size()); - EXPECT_EQ(1U, buckets.count(bucket1)); - EXPECT_EQ(1U, buckets.count(bucket2)); - EXPECT_EQ(1U, buckets.count(bucket3)); - EXPECT_EQ(0U, buckets.count(bucket4)); + EXPECT_TRUE(ContainsBucket(buckets, bucket1)); + EXPECT_TRUE(ContainsBucket(buckets, bucket2)); + EXPECT_TRUE(ContainsBucket(buckets, bucket3)); + EXPECT_FALSE(ContainsBucket(buckets, bucket4)); result = db.GetBucketsModifiedBetween(kTemp, base::Time::FromJavaTime(5), base::Time::Max()); EXPECT_TRUE(result.ok()); buckets = result.value(); EXPECT_EQ(2U, buckets.size()); - EXPECT_EQ(0U, buckets.count(bucket1)); - EXPECT_EQ(1U, buckets.count(bucket2)); - EXPECT_EQ(1U, buckets.count(bucket3)); - EXPECT_EQ(0U, buckets.count(bucket4)); + EXPECT_FALSE(ContainsBucket(buckets, bucket1)); + EXPECT_TRUE(ContainsBucket(buckets, bucket2)); + EXPECT_TRUE(ContainsBucket(buckets, bucket3)); + EXPECT_FALSE(ContainsBucket(buckets, bucket4)); result = db.GetBucketsModifiedBetween(kTemp, base::Time::FromJavaTime(15), base::Time::Max()); EXPECT_TRUE(result.ok()); buckets = result.value(); EXPECT_EQ(1U, buckets.size()); - EXPECT_EQ(0U, buckets.count(bucket1)); - EXPECT_EQ(0U, buckets.count(bucket2)); - EXPECT_EQ(1U, buckets.count(bucket3)); - EXPECT_EQ(0U, buckets.count(bucket4)); + EXPECT_FALSE(ContainsBucket(buckets, bucket1)); + EXPECT_FALSE(ContainsBucket(buckets, bucket2)); + EXPECT_TRUE(ContainsBucket(buckets, bucket3)); + EXPECT_FALSE(ContainsBucket(buckets, bucket4)); result = db.GetBucketsModifiedBetween(kTemp, base::Time::FromJavaTime(25), base::Time::Max()); @@ -735,30 +735,30 @@ EXPECT_TRUE(result.ok()); buckets = result.value(); EXPECT_EQ(1U, buckets.size()); - EXPECT_EQ(0U, buckets.count(bucket1)); - EXPECT_EQ(1U, buckets.count(bucket2)); - EXPECT_EQ(0U, buckets.count(bucket3)); - EXPECT_EQ(0U, buckets.count(bucket4)); + EXPECT_FALSE(ContainsBucket(buckets, bucket1)); + EXPECT_TRUE(ContainsBucket(buckets, bucket2)); + EXPECT_FALSE(ContainsBucket(buckets, bucket3)); + EXPECT_FALSE(ContainsBucket(buckets, bucket4)); result = db.GetBucketsModifiedBetween(kTemp, base::Time::FromJavaTime(0), base::Time::FromJavaTime(20)); EXPECT_TRUE(result.ok()); buckets = result.value(); EXPECT_EQ(2U, buckets.size()); - EXPECT_EQ(1U, buckets.count(bucket1)); - EXPECT_EQ(1U, buckets.count(bucket2)); - EXPECT_EQ(0U, buckets.count(bucket3)); - EXPECT_EQ(0U, buckets.count(bucket4)); + EXPECT_TRUE(ContainsBucket(buckets, bucket1)); + EXPECT_TRUE(ContainsBucket(buckets, bucket2)); + EXPECT_FALSE(ContainsBucket(buckets, bucket3)); + EXPECT_FALSE(ContainsBucket(buckets, bucket4)); result = db.GetBucketsModifiedBetween(kPerm, base::Time::FromJavaTime(0), base::Time::FromJavaTime(35)); EXPECT_TRUE(result.ok()); buckets = result.value(); EXPECT_EQ(1U, buckets.size()); - EXPECT_EQ(0U, buckets.count(bucket1)); - EXPECT_EQ(0U, buckets.count(bucket2)); - EXPECT_EQ(0U, buckets.count(bucket3)); - EXPECT_EQ(1U, buckets.count(bucket4)); + EXPECT_FALSE(ContainsBucket(buckets, bucket1)); + EXPECT_FALSE(ContainsBucket(buckets, bucket2)); + EXPECT_FALSE(ContainsBucket(buckets, bucket3)); + EXPECT_TRUE(ContainsBucket(buckets, bucket4)); } TEST_P(QuotaDatabaseTest, RegisterInitialStorageKeyInfo) {
diff --git a/storage/browser/quota/quota_manager_impl.cc b/storage/browser/quota/quota_manager_impl.cc index 878b150..1bd78d05 100644 --- a/storage/browser/quota/quota_manager_impl.cc +++ b/storage/browser/quota/quota_manager_impl.cc
@@ -151,7 +151,7 @@ return database->GetBucketsForStorageKey(storage_key, type); } -QuotaErrorOr<std::set<BucketInfo>> GetModifiedBetweenOnDBThread( +QuotaErrorOr<std::set<BucketLocator>> GetModifiedBetweenOnDBThread( StorageType type, base::Time begin, base::Time end, @@ -178,7 +178,7 @@ return false; } -QuotaErrorOr<BucketInfo> GetLRUBucketOnDBThread( +QuotaErrorOr<BucketLocator> GetLRUBucketOnDBThread( StorageType type, const std::set<BucketId>& bucket_exceptions, SpecialStoragePolicy* policy, @@ -740,7 +740,7 @@ class QuotaManagerImpl::BucketDataDeleter : public QuotaTask { public: BucketDataDeleter(QuotaManagerImpl* manager, - const BucketInfo& bucket, + const BucketLocator& bucket, QuotaClientTypes quota_client_types, bool is_eviction, StatusCallback callback) @@ -758,7 +758,7 @@ // they are not being tracked yet. // TODO(crbug.com/1199417): Update to call for all buckets once QuotaClient // is migrated to operate on buckets. - if (!bucket_.is_default()) { + if (!bucket_.is_default) { CallCompleted(); return; } @@ -772,7 +772,8 @@ static int tracing_id = 0; std::ostringstream bucket_params; bucket_params << "storage_key: " << bucket_.storage_key.Serialize() - << ", name: " << bucket_.name << ", id: " << bucket_.id; + << ", is_default: " << bucket_.is_default + << ", id: " << bucket_.id; TRACE_EVENT_NESTABLE_ASYNC_BEGIN2( "browsing_data", "QuotaManagerImpl::BucketDataDeleter", ++tracing_id, "client_type", client_type, "bucket", @@ -827,7 +828,7 @@ return static_cast<QuotaManagerImpl*>(observer()); } - const BucketInfo bucket_; + const BucketLocator bucket_; const QuotaClientTypes quota_client_types_; int error_count_ = 0; size_t remaining_clients_ = 0; @@ -1317,7 +1318,7 @@ GetUsageTracker(type)->SetUsageCacheEnabled(client_id, storage_key, enabled); } -void QuotaManagerImpl::DeleteBucketData(const BucketInfo& bucket, +void QuotaManagerImpl::DeleteBucketData(const BucketLocator& bucket, QuotaClientTypes quota_client_types, StatusCallback callback) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); @@ -1796,7 +1797,7 @@ } void QuotaManagerImpl::DeleteBucketDataInternal( - const BucketInfo& bucket, + const BucketLocator& bucket, QuotaClientTypes quota_client_types, bool is_eviction, StatusCallback callback) { @@ -2011,7 +2012,7 @@ void QuotaManagerImpl::DidGetEvictionBucket( GetBucketCallback callback, - const absl::optional<BucketInfo>& bucket) { + const absl::optional<BucketLocator>& bucket) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); // Make sure the returned bucket has not been accessed since we posted the // eviction task. @@ -2020,7 +2021,7 @@ // TODO(crbug.com/1208141): Remove this evaluation for storage key once // QuotaClient is migrated to operate on buckets and NotifyStorageAccessed // no longer used. - if (bucket.has_value() && bucket->is_default() && + if (bucket.has_value() && bucket->is_default && base::Contains(access_notified_storage_keys_, bucket->storage_key)) { std::move(callback).Run(absl::nullopt); } else if (bucket.has_value() && @@ -2061,7 +2062,7 @@ GetLRUBucket(type, std::move(did_get_bucket_callback)); } -void QuotaManagerImpl::EvictBucketData(const BucketInfo& bucket, +void QuotaManagerImpl::EvictBucketData(const BucketLocator& bucket, StatusCallback callback) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(io_thread_->BelongsToCurrentThread()); @@ -2137,7 +2138,7 @@ *new_quota); } -void QuotaManagerImpl::DidGetLRUBucket(QuotaErrorOr<BucketInfo> result) { +void QuotaManagerImpl::DidGetLRUBucket(QuotaErrorOr<BucketLocator> result) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DidDatabaseWork(result.ok() || result.error() != QuotaError::kDatabaseError); @@ -2261,7 +2262,9 @@ return; } - DeleteBucketDataInternal(result.value(), AllQuotaClientTypes(), + BucketLocator bucket(result->id, result->storage_key, result->type, + result->name == kDefaultBucketName); + DeleteBucketDataInternal(bucket, AllQuotaClientTypes(), /*is_eviction=*/false, std::move(callback)); return; } @@ -2289,11 +2292,11 @@ void QuotaManagerImpl::DidGetModifiedBetween( GetBucketsCallback callback, StorageType type, - QuotaErrorOr<std::set<BucketInfo>> result) { + QuotaErrorOr<std::set<BucketLocator>> result) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DidDatabaseWork(result.ok() || result.error() != QuotaError::kDatabaseError); if (!result.ok()) { - std::move(callback).Run(std::set<BucketInfo>(), type); + std::move(callback).Run(std::set<BucketLocator>(), type); return; } std::move(callback).Run(result.value(), type);
diff --git a/storage/browser/quota/quota_manager_impl.h b/storage/browser/quota/quota_manager_impl.h index eab17be..6a3988d 100644 --- a/storage/browser/quota/quota_manager_impl.h +++ b/storage/browser/quota/quota_manager_impl.h
@@ -85,7 +85,7 @@ GetBucketCallback callback) = 0; // Called to evict a bucket. - virtual void EvictBucketData(const BucketInfo& bucket, + virtual void EvictBucketData(const BucketLocator& bucket, StatusCallback callback) = 0; protected: @@ -318,7 +318,7 @@ // the types of QuotaClients to delete from the storage key. // Pass in QuotaClientType::AllClients() to remove all clients from the // storage key, regardless of type. - virtual void DeleteBucketData(const BucketInfo& bucket, + virtual void DeleteBucketData(const BucketLocator& bucket, QuotaClientTypes quota_client_types, StatusCallback callback); void DeleteHostData(const std::string& host, @@ -468,7 +468,7 @@ struct EvictionContext { EvictionContext(); ~EvictionContext(); - BucketInfo evicted_bucket; + BucketLocator evicted_bucket; StatusCallback evict_bucket_data_callback; }; @@ -505,7 +505,7 @@ // Runs BucketDataDeleter which calls QuotaClients to clear data for the // bucket. Once the task is complete, calls the QuotaDatabase to delete the // bucket from the bucket table. - void DeleteBucketDataInternal(const BucketInfo& bucket, + void DeleteBucketDataInternal(const BucketLocator& bucket, QuotaClientTypes quota_client_types, bool is_eviction, StatusCallback callback); @@ -532,13 +532,13 @@ // consistent errors after multiple attempts. std::set<BucketId> GetEvictionBucketExceptions(); void DidGetEvictionBucket(GetBucketCallback callback, - const absl::optional<BucketInfo>& bucket); + const absl::optional<BucketLocator>& bucket); // QuotaEvictionHandler. void GetEvictionBucket(blink::mojom::StorageType type, int64_t global_quota, GetBucketCallback callback) override; - void EvictBucketData(const BucketInfo& bucket, + void EvictBucketData(const BucketLocator& bucket, StatusCallback callback) override; void GetEvictionRoundInfo(EvictionRoundInfoCallback callback) override; @@ -553,7 +553,7 @@ QuotaCallback callback, const int64_t* new_quota, bool success); - void DidGetLRUBucket(QuotaErrorOr<BucketInfo> result); + void DidGetLRUBucket(QuotaErrorOr<BucketLocator> result); void GetQuotaSettings(QuotaSettingsCallback callback); void DidGetSettings(absl::optional<QuotaSettings> settings); void GetStorageCapacity(StorageCapacityCallback callback); @@ -574,7 +574,7 @@ QuotaErrorOr<std::set<BucketLocator>> result); void DidGetModifiedBetween(GetBucketsCallback callback, blink::mojom::StorageType type, - QuotaErrorOr<std::set<BucketInfo>> result); + QuotaErrorOr<std::set<BucketLocator>> result); void DeleteOnCorrectThread() const;
diff --git a/storage/browser/quota/quota_manager_unittest.cc b/storage/browser/quota/quota_manager_unittest.cc index e9be6133..c135853 100644 --- a/storage/browser/quota/quota_manager_unittest.cc +++ b/storage/browser/quota/quota_manager_unittest.cc
@@ -86,6 +86,11 @@ return StorageKey::CreateFromStringForTesting(url); } +BucketLocator ToBucketLocator(const BucketInfo& bucket) { + return BucketLocator(bucket.id, bucket.storage_key, bucket.type, + bucket.name == kDefaultBucketName); +} + MATCHER_P3(MatchesBucketTableEntry, storage_key, type, use_count, "") { return testing::ExplainMatchResult(storage_key, arg.storage_key, result_listener) && @@ -374,14 +379,14 @@ weak_factory_.GetWeakPtr())); } - void EvictBucketData(const BucketInfo& bucket) { + void EvictBucketData(const BucketLocator& bucket) { quota_status_ = QuotaStatusCode::kUnknown; quota_manager_impl_->EvictBucketData( bucket, base::BindOnce(&QuotaManagerImplTest::StatusCallback, weak_factory_.GetWeakPtr())); } - void DeleteBucketData(const BucketInfo& bucket, + void DeleteBucketData(const BucketLocator& bucket, QuotaClientTypes quota_client_types) { quota_status_ = QuotaStatusCode::kUnknown; quota_manager_impl_->DeleteBucketData( @@ -582,14 +587,14 @@ usage_ = global_usage; } - void DidGetEvictionBucket(const absl::optional<BucketInfo>& bucket) { + void DidGetEvictionBucket(const absl::optional<BucketLocator>& bucket) { eviction_bucket_ = bucket; DCHECK(!bucket.has_value() || !bucket->storage_key.origin().GetURL().is_empty()); } void DidGetModifiedBuckets(base::OnceClosure quit_closure, - const std::set<BucketInfo>& buckets, + const std::set<BucketLocator>& buckets, StorageType type) { modified_buckets_ = buckets; modified_buckets_type_ = type; @@ -663,10 +668,10 @@ int64_t quota() const { return quota_; } int64_t total_space() const { return total_space_; } int64_t available_space() const { return available_space_; } - const absl::optional<BucketInfo>& eviction_bucket() const { + const absl::optional<BucketLocator>& eviction_bucket() const { return eviction_bucket_; } - const std::set<BucketInfo>& modified_buckets() const { + const std::set<BucketLocator>& modified_buckets() const { return modified_buckets_; } StorageType modified_buckets_type() const { return modified_buckets_type_; } @@ -701,8 +706,8 @@ int64_t quota_; int64_t total_space_; int64_t available_space_; - absl::optional<BucketInfo> eviction_bucket_; - std::set<BucketInfo> modified_buckets_; + absl::optional<BucketLocator> eviction_bucket_; + std::set<BucketLocator> modified_buckets_; StorageType modified_buckets_type_; QuotaTableEntries quota_entries_; BucketTableEntries bucket_entries_; @@ -1802,7 +1807,7 @@ GetBucket(ToStorageKey("http://foo.com/"), kDefaultBucketName, kTemp); ASSERT_TRUE(bucket_.ok()); - EvictBucketData(bucket_.value()); + EvictBucketData(ToBucketLocator(bucket_.value())); task_environment_.RunUntilIdle(); DumpBucketTable(); @@ -1844,7 +1849,7 @@ ASSERT_TRUE(bucket_.ok()); BucketInfo created_bucket = bucket_.value(); - EvictBucketData(created_bucket); + EvictBucketData(ToBucketLocator(created_bucket)); task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); @@ -1868,7 +1873,7 @@ ASSERT_TRUE(bucket_.ok()); BucketInfo default_bucket = bucket_.value(); - EvictBucketData(default_bucket); + EvictBucketData(ToBucketLocator(default_bucket)); task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); @@ -1897,7 +1902,7 @@ CreateBucketForTesting(kStorageKey, kDefaultBucketName, kTemp); ASSERT_TRUE(bucket_.ok()); - EvictBucketData(bucket_.value()); + EvictBucketData(ToBucketLocator(bucket_.value())); task_environment_.RunUntilIdle(); // Ensure use count and time since access are recorded. @@ -1917,7 +1922,7 @@ GetGlobalUsage(kTemp); - EvictBucketData(bucket_.value()); + EvictBucketData(ToBucketLocator(bucket_.value())); task_environment_.RunUntilIdle(); // The new use count should be logged. @@ -1962,7 +1967,7 @@ for (int i = 0; i < QuotaManagerImpl::kThresholdOfErrorsToBeDenylisted + 1; ++i) { - EvictBucketData(bucket_.value()); + EvictBucketData(ToBucketLocator(bucket_.value())); task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kErrorInvalidModification, status()); } @@ -2245,7 +2250,7 @@ kTemp); ASSERT_TRUE(bucket_.ok()); - DeleteBucketData(bucket_.value(), AllQuotaClientTypes()); + DeleteBucketData(ToBucketLocator(bucket_.value()), AllQuotaClientTypes()); task_environment_.RunUntilIdle(); EXPECT_EQ(QuotaStatusCode::kOk, status()); } @@ -2305,9 +2310,9 @@ task_environment_.RunUntilIdle(); reset_status_callback_count(); - DeleteBucketData(foo_temp_bucket, AllQuotaClientTypes()); - DeleteBucketData(bar_temp_bucket, AllQuotaClientTypes()); - DeleteBucketData(foo_temp_bucket, AllQuotaClientTypes()); + DeleteBucketData(ToBucketLocator(foo_temp_bucket), AllQuotaClientTypes()); + DeleteBucketData(ToBucketLocator(bar_temp_bucket), AllQuotaClientTypes()); + DeleteBucketData(ToBucketLocator(foo_temp_bucket), AllQuotaClientTypes()); task_environment_.RunUntilIdle(); EXPECT_EQ(3, status_callback_count()); @@ -2399,8 +2404,8 @@ task_environment_.RunUntilIdle(); reset_status_callback_count(); - DeleteBucketData(foo_perm_bucket, AllQuotaClientTypes()); - DeleteBucketData(bar_perm_bucket, AllQuotaClientTypes()); + DeleteBucketData(ToBucketLocator(foo_perm_bucket), AllQuotaClientTypes()); + DeleteBucketData(ToBucketLocator(bar_perm_bucket), AllQuotaClientTypes()); task_environment_.RunUntilIdle(); EXPECT_EQ(2, status_callback_count()); @@ -2609,13 +2614,13 @@ GetEvictionBucket(kTemp); task_environment_.RunUntilIdle(); - EXPECT_EQ(bucket_a, eviction_bucket()); + EXPECT_EQ(ToBucketLocator(bucket_a), eviction_bucket()); // Notify that the `bucket_a` is accessed. NotifyBucketAccessed(bucket_a.id); GetEvictionBucket(kTemp); task_environment_.RunUntilIdle(); - EXPECT_EQ(bucket_b, eviction_bucket()); + EXPECT_EQ(ToBucketLocator(bucket_b), eviction_bucket()); // Notify that the `bucket_b` is accessed while GetEvictionBucket is running. GetEvictionBucket(kTemp); @@ -2638,7 +2643,6 @@ blink::mojom::StorageType::kPersistent}); GetBucketsModifiedBetween(kTemp, base::Time(), base::Time::Max()); - task_environment_.RunUntilIdle(); EXPECT_TRUE(modified_buckets().empty()); EXPECT_EQ(modified_buckets_type(), kTemp); @@ -2652,35 +2656,31 @@ base::Time time3 = client->IncrementMockTime(); GetBucketsModifiedBetween(kTemp, time1, base::Time::Max()); - task_environment_.RunUntilIdle(); EXPECT_EQ(modified_buckets_type(), kTemp); EXPECT_THAT(modified_buckets(), testing::UnorderedElementsAre( - testing::Field(&BucketInfo::storage_key, + testing::Field(&BucketLocator::storage_key, ToStorageKey("http://a.com")), - testing::Field(&BucketInfo::storage_key, + testing::Field(&BucketLocator::storage_key, ToStorageKey("http://a.com:1")), - testing::Field(&BucketInfo::storage_key, + testing::Field(&BucketLocator::storage_key, ToStorageKey("https://a.com")), - testing::Field(&BucketInfo::storage_key, + testing::Field(&BucketLocator::storage_key, ToStorageKey("http://c.com")))); GetBucketsModifiedBetween(kTemp, time2, base::Time::Max()); - task_environment_.RunUntilIdle(); EXPECT_EQ(2U, modified_buckets().size()); GetBucketsModifiedBetween(kTemp, time3, base::Time::Max()); - task_environment_.RunUntilIdle(); EXPECT_TRUE(modified_buckets().empty()); EXPECT_EQ(modified_buckets_type(), kTemp); client->ModifyStorageKeyAndNotify(ToStorageKey("http://a.com/"), kTemp, 10); GetBucketsModifiedBetween(kTemp, time3, base::Time::Max()); - task_environment_.RunUntilIdle(); EXPECT_THAT(modified_buckets(), testing::UnorderedElementsAre(testing::Field( - &BucketInfo::storage_key, ToStorageKey("http://a.com/")))); + &BucketLocator::storage_key, ToStorageKey("http://a.com/")))); EXPECT_EQ(modified_buckets_type(), kTemp); } @@ -2691,7 +2691,6 @@ disable_quota_database(true); GetBucketsModifiedBetween(kTemp, base::Time(), base::Time::Max()); - task_environment_.RunUntilIdle(); // Return empty set when error is encountered. EXPECT_TRUE(modified_buckets().empty()); @@ -2777,22 +2776,24 @@ GetHostUsageWithBreakdown("foo.com", kTemp); const int64_t predelete_foo_tmp = usage(); - DeleteBucketData(foo_bucket, {QuotaClientType::kFileSystem}); + DeleteBucketData(ToBucketLocator(foo_bucket), {QuotaClientType::kFileSystem}); task_environment_.RunUntilIdle(); GetHostUsageWithBreakdown("foo.com", kTemp); EXPECT_EQ(predelete_foo_tmp - 1, usage()); - DeleteBucketData(foo_bucket, {QuotaClientType::kServiceWorkerCache}); + DeleteBucketData(ToBucketLocator(foo_bucket), + {QuotaClientType::kServiceWorkerCache}); task_environment_.RunUntilIdle(); GetHostUsageWithBreakdown("foo.com", kTemp); EXPECT_EQ(predelete_foo_tmp - 2 - 1, usage()); - DeleteBucketData(foo_bucket, {QuotaClientType::kDatabase}); + DeleteBucketData(ToBucketLocator(foo_bucket), {QuotaClientType::kDatabase}); task_environment_.RunUntilIdle(); GetHostUsageWithBreakdown("foo.com", kTemp); EXPECT_EQ(predelete_foo_tmp - 4 - 2 - 1, usage()); - DeleteBucketData(foo_bucket, {QuotaClientType::kIndexedDatabase}); + DeleteBucketData(ToBucketLocator(foo_bucket), + {QuotaClientType::kIndexedDatabase}); task_environment_.RunUntilIdle(); GetHostUsageWithBreakdown("foo.com", kTemp); EXPECT_EQ(predelete_foo_tmp - 8 - 4 - 2 - 1, usage()); @@ -2874,14 +2875,15 @@ GetHostUsageWithBreakdown("foo.com", kTemp); const int64_t predelete_foo_tmp = usage(); - DeleteBucketData(foo_bucket, + DeleteBucketData(ToBucketLocator(foo_bucket), {QuotaClientType::kFileSystem, QuotaClientType::kDatabase}); task_environment_.RunUntilIdle(); GetHostUsageWithBreakdown("foo.com", kTemp); EXPECT_EQ(predelete_foo_tmp - 4 - 1, usage()); - DeleteBucketData(foo_bucket, {QuotaClientType::kServiceWorkerCache, - QuotaClientType::kIndexedDatabase}); + DeleteBucketData(ToBucketLocator(foo_bucket), + {QuotaClientType::kServiceWorkerCache, + QuotaClientType::kIndexedDatabase}); task_environment_.RunUntilIdle(); GetHostUsageWithBreakdown("foo.com", kTemp); EXPECT_EQ(predelete_foo_tmp - 8 - 4 - 2 - 1, usage());
diff --git a/storage/browser/quota/quota_temporary_storage_evictor.cc b/storage/browser/quota/quota_temporary_storage_evictor.cc index d6e4b90f..38faa8a 100644 --- a/storage/browser/quota/quota_temporary_storage_evictor.cc +++ b/storage/browser/quota/quota_temporary_storage_evictor.cc
@@ -216,7 +216,7 @@ } void QuotaTemporaryStorageEvictor::OnGotEvictionBucket( - const absl::optional<BucketInfo>& bucket) { + const absl::optional<BucketLocator>& bucket) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (!bucket.has_value()) {
diff --git a/storage/browser/quota/quota_temporary_storage_evictor.h b/storage/browser/quota/quota_temporary_storage_evictor.h index fb536df..fd86774 100644 --- a/storage/browser/quota/quota_temporary_storage_evictor.h +++ b/storage/browser/quota/quota_temporary_storage_evictor.h
@@ -16,7 +16,7 @@ #include "base/memory/weak_ptr.h" #include "base/sequence_checker.h" #include "base/timer/timer.h" -#include "components/services/storage/public/cpp/buckets/bucket_info.h" +#include "components/services/storage/public/cpp/buckets/bucket_locator.h" #include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/blink/public/mojom/quota/quota_types.mojom.h" @@ -79,7 +79,7 @@ int64_t total_space, int64_t current_usage, bool current_usage_is_complete); - void OnGotEvictionBucket(const absl::optional<BucketInfo>& bucket); + void OnGotEvictionBucket(const absl::optional<BucketLocator>& bucket); void OnEvictionComplete(blink::mojom::QuotaStatusCode status); void OnEvictionRoundStarted();
diff --git a/storage/browser/quota/quota_temporary_storage_evictor_unittest.cc b/storage/browser/quota/quota_temporary_storage_evictor_unittest.cc index 89ffbc6..aa3306e 100644 --- a/storage/browser/quota/quota_temporary_storage_evictor_unittest.cc +++ b/storage/browser/quota/quota_temporary_storage_evictor_unittest.cc
@@ -17,7 +17,7 @@ #include "base/run_loop.h" #include "base/test/task_environment.h" #include "components/services/storage/public/cpp/buckets/bucket_id.h" -#include "components/services/storage/public/cpp/buckets/bucket_info.h" +#include "components/services/storage/public/cpp/buckets/bucket_locator.h" #include "storage/browser/quota/quota_manager_impl.h" #include "storage/browser/quota/quota_temporary_storage_evictor.h" #include "testing/gtest/include/gtest/gtest.h" @@ -37,7 +37,7 @@ error_on_evict_buckets_data_(false), error_on_get_usage_and_quota_(false) {} - void EvictBucketData(const BucketInfo& bucket, + void EvictBucketData(const BucketLocator& bucket, StatusCallback callback) override { if (error_on_evict_buckets_data_) { std::move(callback).Run( @@ -103,7 +103,7 @@ // Simulates an access to `bucket`. It reorders the internal LRU list. // It internally uses AddBucket(). - void AccessBucket(const BucketInfo& bucket) { + void AccessBucket(const BucketLocator& bucket) { const auto& it = buckets_.find(bucket.id); EXPECT_TRUE(buckets_.end() != it); AddBucket(bucket, it->second); @@ -112,14 +112,14 @@ // Simulates adding or overwriting the `bucket` to the internal bucket set // with the `usage`. It also adds or moves the `bucket` to the // end of the LRU list. - void AddBucket(const BucketInfo& bucket, int64_t usage) { + void AddBucket(const BucketLocator& bucket, int64_t usage) { EnsureBucketRemoved(bucket); bucket_order_.push_back(bucket); buckets_[bucket.id] = usage; } private: - int64_t EnsureBucketRemoved(const BucketInfo& bucket) { + int64_t EnsureBucketRemoved(const BucketLocator& bucket) { int64_t bucket_usage; if (!base::Contains(buckets_, bucket.id)) return -1; @@ -133,7 +133,7 @@ QuotaSettings settings_; int64_t available_space_; - std::list<BucketInfo> bucket_order_; + std::list<BucketLocator> bucket_order_; std::map<BucketId, int64_t> buckets_; bool error_on_evict_buckets_data_; bool error_on_get_usage_and_quota_; @@ -163,8 +163,9 @@ } void TaskForRepeatedEvictionTest( - const std::pair<absl::optional<BucketInfo>, int64_t>& bucket_to_be_added, - const absl::optional<BucketInfo> bucket_to_be_accessed, + const std::pair<absl::optional<BucketLocator>, int64_t>& + bucket_to_be_added, + const absl::optional<BucketLocator> bucket_to_be_accessed, int expected_usage_after_first, int expected_usage_after_second) { EXPECT_GE(4, num_get_usage_and_quota_for_eviction_); @@ -187,11 +188,10 @@ ++num_get_usage_and_quota_for_eviction_; } - BucketInfo CreateBucket(const std::string& url, const std::string& name) { - return BucketInfo(bucket_id_generator_.GenerateNextId(), - blink::StorageKey::CreateFromStringForTesting(url), - blink::mojom::StorageType::kTemporary, name, - /*expiration=*/base::Time::Max(), /*quota=*/0); + BucketLocator CreateBucket(const std::string& url, bool is_default) { + return BucketLocator(bucket_id_generator_.GenerateNextId(), + blink::StorageKey::CreateFromStringForTesting(url), + blink::mojom::StorageType::kTemporary, is_default); } protected: @@ -226,12 +226,12 @@ }; TEST_F(QuotaTemporaryStorageEvictorTest, SimpleEvictionTest) { - quota_eviction_handler()->AddBucket(CreateBucket("http://www.z.com", "test"), - 3000); - quota_eviction_handler()->AddBucket(CreateBucket("http://www.y.com", "test"), - 200); - quota_eviction_handler()->AddBucket(CreateBucket("http://www.x.com", "test"), - 500); + quota_eviction_handler()->AddBucket( + CreateBucket("http://www.z.com", /*is_default=*/false), 3000); + quota_eviction_handler()->AddBucket( + CreateBucket("http://www.y.com", /*is_default=*/false), 200); + quota_eviction_handler()->AddBucket( + CreateBucket("http://www.x.com", /*is_default=*/false), 500); quota_eviction_handler()->SetPoolSize(4000); quota_eviction_handler()->set_available_space(1000000000); EXPECT_EQ(3000 + 200 + 500, quota_eviction_handler()->GetUsage()); @@ -248,13 +248,13 @@ TEST_F(QuotaTemporaryStorageEvictorTest, MultipleEvictionTest) { quota_eviction_handler()->AddBucket( - CreateBucket("http://www.z.com", kDefaultBucketName), 20); + CreateBucket("http://www.z.com", /*is_default=*/true), 20); quota_eviction_handler()->AddBucket( - CreateBucket("http://www.y.com", kDefaultBucketName), 2900); + CreateBucket("http://www.y.com", /*is_default=*/true), 2900); quota_eviction_handler()->AddBucket( - CreateBucket("http://www.x.com", kDefaultBucketName), 450); + CreateBucket("http://www.x.com", /*is_default=*/true), 450); quota_eviction_handler()->AddBucket( - CreateBucket("http://www.w.com", kDefaultBucketName), 400); + CreateBucket("http://www.w.com", /*is_default=*/true), 400); quota_eviction_handler()->SetPoolSize(4000); quota_eviction_handler()->set_available_space(1000000000); EXPECT_EQ(20 + 2900 + 450 + 400, quota_eviction_handler()->GetUsage()); @@ -277,21 +277,22 @@ const int64_t initial_total_size = a_size + b_size + c_size + d_size; const int64_t e_size = 275; - quota_eviction_handler()->AddBucket(CreateBucket("http://www.d.com", "test"), - d_size); - quota_eviction_handler()->AddBucket(CreateBucket("http://www.c.com", "test"), - c_size); - quota_eviction_handler()->AddBucket(CreateBucket("http://www.b.com", "test"), - b_size); - quota_eviction_handler()->AddBucket(CreateBucket("http://www.a.com", "test"), - a_size); + quota_eviction_handler()->AddBucket( + CreateBucket("http://www.d.com", /*is_default=*/false), d_size); + quota_eviction_handler()->AddBucket( + CreateBucket("http://www.c.com", /*is_default=*/false), c_size); + quota_eviction_handler()->AddBucket( + CreateBucket("http://www.b.com", /*is_default=*/false), b_size); + quota_eviction_handler()->AddBucket( + CreateBucket("http://www.a.com", /*is_default=*/false), a_size); quota_eviction_handler()->SetPoolSize(1000); quota_eviction_handler()->set_available_space(1000000000); quota_eviction_handler()->set_task_for_get_usage_and_quota( base::BindRepeating( &QuotaTemporaryStorageEvictorTest::TaskForRepeatedEvictionTest, weak_factory_.GetWeakPtr(), - std::make_pair(CreateBucket("http://www.e.com", "test"), e_size), + std::make_pair(CreateBucket("http://www.e.com", /*is_default=*/false), + e_size), absl::nullopt, initial_total_size - d_size, initial_total_size - d_size + e_size - c_size)); EXPECT_EQ(initial_total_size, quota_eviction_handler()->GetUsage()); @@ -315,13 +316,13 @@ const int64_t initial_total_size = a_size + b_size + c_size + d_size; quota_eviction_handler()->AddBucket( - CreateBucket("http://www.d.com", kDefaultBucketName), d_size); + CreateBucket("http://www.d.com", /*is_default=*/true), d_size); quota_eviction_handler()->AddBucket( - CreateBucket("http://www.c.com", kDefaultBucketName), c_size); + CreateBucket("http://www.c.com", /*is_default=*/true), c_size); quota_eviction_handler()->AddBucket( - CreateBucket("http://www.b.com", kDefaultBucketName), b_size); + CreateBucket("http://www.b.com", /*is_default=*/true), b_size); quota_eviction_handler()->AddBucket( - CreateBucket("http://www.a.com", kDefaultBucketName), a_size); + CreateBucket("http://www.a.com", /*is_default=*/true), a_size); quota_eviction_handler()->SetPoolSize(1000); quota_eviction_handler()->set_available_space(1000000000); quota_eviction_handler()->set_task_for_get_usage_and_quota( @@ -351,11 +352,16 @@ const int64_t initial_total_size = a_size + b_size + c_size + d_size; const int64_t e_size = 275; - BucketInfo a_bucket = CreateBucket("http://www.a.com", kDefaultBucketName); - BucketInfo b_bucket = CreateBucket("http://www.b.com", kDefaultBucketName); - BucketInfo c_bucket = CreateBucket("http://www.c.com", kDefaultBucketName); - BucketInfo d_bucket = CreateBucket("http://www.d.com", kDefaultBucketName); - BucketInfo e_bucket = CreateBucket("http://www.e.com", kDefaultBucketName); + BucketLocator a_bucket = + CreateBucket("http://www.a.com", /*is_default=*/true); + BucketLocator b_bucket = + CreateBucket("http://www.b.com", /*is_default=*/true); + BucketLocator c_bucket = + CreateBucket("http://www.c.com", /*is_default=*/true); + BucketLocator d_bucket = + CreateBucket("http://www.d.com", /*is_default=*/true); + BucketLocator e_bucket = + CreateBucket("http://www.e.com", /*is_default=*/true); quota_eviction_handler()->AddBucket(d_bucket, d_size); quota_eviction_handler()->AddBucket(c_bucket, c_size); @@ -386,9 +392,9 @@ // If we're using so little that evicting all of it wouldn't // do enough to alleviate a diskspace shortage, we don't evict. quota_eviction_handler()->AddBucket( - CreateBucket("http://www.z.com", kDefaultBucketName), 10); + CreateBucket("http://www.z.com", /*is_default=*/true), 10); quota_eviction_handler()->AddBucket( - CreateBucket("http://www.x.com", kDefaultBucketName), 20); + CreateBucket("http://www.x.com", /*is_default=*/true), 20); quota_eviction_handler()->SetPoolSize(10000); quota_eviction_handler()->set_available_space( quota_eviction_handler()->settings().should_remain_available - 350); @@ -406,13 +412,13 @@ TEST_F(QuotaTemporaryStorageEvictorTest, DiskSpaceEvictionTest) { quota_eviction_handler()->AddBucket( - CreateBucket("http://www.z.com", kDefaultBucketName), 294); + CreateBucket("http://www.z.com", /*is_default=*/true), 294); quota_eviction_handler()->AddBucket( - CreateBucket("http://www.y.com", kDefaultBucketName), 120); + CreateBucket("http://www.y.com", /*is_default=*/true), 120); quota_eviction_handler()->AddBucket( - CreateBucket("http://www.x.com", kDefaultBucketName), 150); + CreateBucket("http://www.x.com", /*is_default=*/true), 150); quota_eviction_handler()->AddBucket( - CreateBucket("http://www.w.com", kDefaultBucketName), 300); + CreateBucket("http://www.w.com", /*is_default=*/true), 300); quota_eviction_handler()->SetPoolSize(10000); quota_eviction_handler()->set_available_space( quota_eviction_handler()->settings().should_remain_available - 350);
diff --git a/storage/browser/test/mock_quota_manager.cc b/storage/browser/test/mock_quota_manager.cc index 96748fa..8b33393b 100644 --- a/storage/browser/test/mock_quota_manager.cc +++ b/storage/browser/test/mock_quota_manager.cc
@@ -138,11 +138,13 @@ base::Time begin, base::Time end, GetBucketsCallback callback) { - auto buckets_to_return = std::make_unique<std::set<BucketInfo>>(); + auto buckets_to_return = std::make_unique<std::set<BucketLocator>>(); for (const auto& info : buckets_) { if (info.bucket.type == type && info.modified >= begin && info.modified < end) - buckets_to_return->insert(info.bucket); + buckets_to_return->insert(BucketLocator( + info.bucket.id, info.bucket.storage_key, info.bucket.type, + info.bucket.name == kDefaultBucketName)); } base::ThreadTaskRunnerHandle::Get()->PostTask( @@ -151,11 +153,11 @@ std::move(buckets_to_return), type)); } -void MockQuotaManager::DeleteBucketData(const BucketInfo& bucket, +void MockQuotaManager::DeleteBucketData(const BucketLocator& bucket, QuotaClientTypes quota_client_types, StatusCallback callback) { for (auto current = buckets_.begin(); current != buckets_.end(); ++current) { - if (current->bucket == bucket) { + if (current->bucket.id == bucket.id) { // Modify the mask: if it's 0 after "deletion", remove the storage key. for (QuotaClientType type : quota_client_types) current->quota_client_types.erase(type); @@ -211,7 +213,7 @@ void MockQuotaManager::DidGetModifiedInTimeRange( GetBucketsCallback callback, - std::unique_ptr<std::set<BucketInfo>> buckets, + std::unique_ptr<std::set<BucketLocator>> buckets, StorageType storage_type) { std::move(callback).Run(*buckets, storage_type); }
diff --git a/storage/browser/test/mock_quota_manager.h b/storage/browser/test/mock_quota_manager.h index ea46034..dd3c276 100644 --- a/storage/browser/test/mock_quota_manager.h +++ b/storage/browser/test/mock_quota_manager.h
@@ -77,7 +77,7 @@ // specifies the types of QuotaClients which should be removed from this // bucket. Setting the mask to AllQuotaClientTypes() will remove all // clients from the bucket, regardless of type. - void DeleteBucketData(const BucketInfo& bucket, + void DeleteBucketData(const BucketLocator& bucket, QuotaClientTypes quota_client_types, StatusCallback callback) override; @@ -171,9 +171,10 @@ void DidGetBucket(base::OnceCallback<void(QuotaErrorOr<BucketInfo>)> callback, QuotaErrorOr<BucketInfo> result); - void DidGetModifiedInTimeRange(GetBucketsCallback callback, - std::unique_ptr<std::set<BucketInfo>> buckets, - blink::mojom::StorageType storage_type); + void DidGetModifiedInTimeRange( + GetBucketsCallback callback, + std::unique_ptr<std::set<BucketLocator>> buckets, + blink::mojom::StorageType storage_type); void DidDeleteStorageKeyData(StatusCallback callback, blink::mojom::QuotaStatusCode status);
diff --git a/storage/browser/test/mock_quota_manager_unittest.cc b/storage/browser/test/mock_quota_manager_unittest.cc index e0ea19d56..7d53c753 100644 --- a/storage/browser/test/mock_quota_manager_unittest.cc +++ b/storage/browser/test/mock_quota_manager_unittest.cc
@@ -17,6 +17,7 @@ #include "base/test/bind.h" #include "base/test/task_environment.h" #include "base/threading/thread_task_runner_handle.h" +#include "components/services/storage/public/cpp/buckets/bucket_locator.h" #include "storage/browser/quota/quota_client_type.h" #include "storage/browser/test/mock_special_storage_policy.h" #include "testing/gtest/include/gtest/gtest.h" @@ -34,6 +35,20 @@ constexpr QuotaClientType kClientFile = QuotaClientType::kFileSystem; constexpr QuotaClientType kClientDB = QuotaClientType::kIndexedDatabase; +bool ContainsBucket(const std::set<BucketLocator>& buckets, + const BucketInfo& target_bucket) { + BucketLocator target_bucket_locator( + target_bucket.id, target_bucket.storage_key, target_bucket.type, + target_bucket.name == kDefaultBucketName); + auto it = buckets.find(target_bucket_locator); + return it != buckets.end(); +} + +BucketLocator ToBucketLocator(const BucketInfo& bucket) { + return BucketLocator(bucket.id, bucket.storage_key, bucket.type, + bucket.name == kDefaultBucketName); +} + } // namespace class MockQuotaManagerTest : public testing::Test { @@ -94,14 +109,14 @@ } void GotModifiedBuckets(base::OnceClosure quit_closure, - const std::set<BucketInfo>& buckets, + const std::set<BucketLocator>& buckets, StorageType type) { buckets_ = buckets; type_ = type; std::move(quit_closure).Run(); } - void DeleteBucketData(const BucketInfo& bucket, + void DeleteBucketData(const BucketLocator& bucket, QuotaClientTypes quota_client_types) { base::RunLoop run_loop; manager_->DeleteBucketData( @@ -126,7 +141,7 @@ return manager_.get(); } - const std::set<BucketInfo>& buckets() const { return buckets_; } + const std::set<BucketLocator>& buckets() const { return buckets_; } const StorageType& type() const { return type_; @@ -140,7 +155,7 @@ int deletion_callback_count_; - std::set<BucketInfo> buckets_; + std::set<BucketLocator> buckets_; StorageType type_; base::WeakPtrFactory<MockQuotaManagerTest> weak_factory_{this}; @@ -292,7 +307,7 @@ manager()->AddBucket(bucket2, {kClientFile, kClientDB}, base::Time::Now()); manager()->AddBucket(bucket3, {kClientFile, kClientDB}, base::Time::Now()); - DeleteBucketData(bucket2, {kClientFile}); + DeleteBucketData(ToBucketLocator(bucket2), {kClientFile}); EXPECT_EQ(1, deletion_callback_count()); EXPECT_EQ(manager()->BucketDataCount(kClientFile), 2); @@ -302,7 +317,7 @@ EXPECT_TRUE(manager()->BucketHasData(bucket3, kClientFile)); EXPECT_TRUE(manager()->BucketHasData(bucket3, kClientDB)); - DeleteBucketData(bucket3, {kClientFile, kClientDB}); + DeleteBucketData(ToBucketLocator(bucket3), {kClientFile, kClientDB}); EXPECT_EQ(2, deletion_callback_count()); EXPECT_EQ(manager()->BucketDataCount(kClientFile), 1); @@ -333,8 +348,8 @@ EXPECT_EQ(kTemporary, type()); EXPECT_EQ(1UL, buckets().size()); - EXPECT_EQ(1UL, buckets().count(bucket1)); - EXPECT_EQ(0UL, buckets().count(bucket2)); + EXPECT_TRUE(ContainsBucket(buckets(), bucket1)); + EXPECT_FALSE(ContainsBucket(buckets(), bucket2)); manager()->AddBucket(bucket2, {kClientFile}, now); @@ -342,21 +357,21 @@ EXPECT_EQ(kTemporary, type()); EXPECT_EQ(2UL, buckets().size()); - EXPECT_EQ(1UL, buckets().count(bucket1)); - EXPECT_EQ(1UL, buckets().count(bucket2)); + EXPECT_TRUE(ContainsBucket(buckets(), bucket1)); + EXPECT_TRUE(ContainsBucket(buckets(), bucket2)); GetModifiedBuckets(kTemporary, then, now); EXPECT_EQ(kTemporary, type()); EXPECT_EQ(1UL, buckets().size()); - EXPECT_EQ(1UL, buckets().count(bucket1)); - EXPECT_EQ(0UL, buckets().count(bucket2)); + EXPECT_TRUE(ContainsBucket(buckets(), bucket1)); + EXPECT_FALSE(ContainsBucket(buckets(), bucket2)); GetModifiedBuckets(kTemporary, now - a_minute, now + a_minute); EXPECT_EQ(kTemporary, type()); EXPECT_EQ(1UL, buckets().size()); - EXPECT_EQ(0UL, buckets().count(bucket1)); - EXPECT_EQ(1UL, buckets().count(bucket2)); + EXPECT_FALSE(ContainsBucket(buckets(), bucket1)); + EXPECT_TRUE(ContainsBucket(buckets(), bucket2)); } } // namespace storage
diff --git a/testing/buildbot/chromium.gpu.fyi.json b/testing/buildbot/chromium.gpu.fyi.json index 4f3922c..04bfa4bd 100644 --- a/testing/buildbot/chromium.gpu.fyi.json +++ b/testing/buildbot/chromium.gpu.fyi.json
@@ -2051,46 +2051,6 @@ "gtest_tests": [ { "args": [ - "angle_end2end_tests", - "--gtest_filter=-*Vulkan_SwiftShader*", - "--shard-timeout=180", - "-v" - ], - "merge": { - "args": [], - "script": "//testing/merge_scripts/standard_isolated_script_merge.py" - }, - "resultdb": { - "enable": true, - "has_native_resultdb_integration": true - }, - "swarming": { - "can_use_on_swarming_builders": true, - "cipd_packages": [ - { - "cipd_package": "infra/tools/luci/logdog/butler/${platform}", - "location": "bin", - "revision": "git_revision:ff387eadf445b24c935f1cf7d6ddd279f8a6b04c" - } - ], - "containment_type": "AUTO", - "dimension_sets": [ - { - "device_os": "MMB29Q", - "device_os_type": "userdebug", - "device_type": "bullhead", - "os": "Android" - } - ], - "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", - "shards": 4 - }, - "test": "angle_end2end_tests", - "test_id_prefix": "ninja://third_party/angle/src/tests:angle_end2end_tests/", - "use_isolated_scripts_api": true - }, - { - "args": [ "--gs-results-bucket=chromium-result-details", "--recover-devices" ],
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl index 467b2d4..8362879 100644 --- a/testing/buildbot/test_suites.pyl +++ b/testing/buildbot/test_suites.pyl
@@ -6397,7 +6397,6 @@ ], 'gpu_fyi_android_gtests': [ - 'gpu_angle_end2end_gtests', 'gpu_angle_unit_gtests', 'gpu_common_gtests_validating', 'gpu_fyi_and_optional_non_linux_gtests',
diff --git a/testing/scripts/PRESUBMIT.py b/testing/scripts/PRESUBMIT.py index 1298c22..768fef289 100644 --- a/testing/scripts/PRESUBMIT.py +++ b/testing/scripts/PRESUBMIT.py
@@ -12,7 +12,8 @@ def CommonChecks(input_api, output_api): return input_api.canned_checks.RunUnitTestsInDirectory( - input_api, output_api, '.', files_to_check=[r'^.+_unittest\.py$']) + input_api, output_api, '.', files_to_check=[r'^.+_unittest\.py$'], + skip_shebang_check=True) def CheckChangeOnUpload(input_api, output_api): return CommonChecks(input_api, output_api)
diff --git a/testing/scripts/wpt_common_unittest.py b/testing/scripts/wpt_common_unittest.py index 11d6c76e..85ea0b3 100755 --- a/testing/scripts/wpt_common_unittest.py +++ b/testing/scripts/wpt_common_unittest.py
@@ -251,7 +251,8 @@ LAYOUT_TEST_RESULTS_SUBDIR, 'full_results_jsonp.js')] match = re.match(r'ADD_FULL_RESULTS\((.*)\);$', full_results_jsonp) self.assertIsNotNone(match) - self.assertEqual(match.group(1), written_files[OUTPUT_JSON_FILENAME]) + self.assertEqual(match.group(1), + written_files[OUTPUT_JSON_FILENAME].decode(encoding='utf-8')) failing_results_jsonp = written_files[os.path.join( LAYOUT_TEST_RESULTS_SUBDIR, 'failing_results.json')] match = re.match(r'ADD_RESULTS\((.*)\);$', failing_results_jsonp) @@ -303,7 +304,8 @@ self.wpt_adapter.do_post_test_run_tasks() written_files = self.wpt_adapter.fs.written_files actual_path = os.path.join(artifact_subdir, "test-actual.txt") - self.assertEqual("test.html actual text", written_files[actual_path]) + self.assertEqual("test.html actual text", + written_files[actual_path].decode(encoding='utf-8')) # Ensure the artifact in the json was replaced with the location of # the newly-created file. updated_json = self._load_json_output() @@ -341,7 +343,8 @@ "external", "wpt") stderr_path = os.path.join(artifact_subdir, "test-stderr.txt") - self.assertEqual("test.html exceptions", written_files[stderr_path]) + self.assertEqual("test.html exceptions", + written_files[stderr_path].decode(encoding='utf-8')) # Ensure the artifact in the json was replaced with the location of # the newly-created file. updated_json = self._load_json_output() @@ -376,7 +379,8 @@ "external", "wpt") crash_log_path = os.path.join(artifact_subdir, "test-crash-log.txt") - self.assertEqual("test.html crashed!", written_files[crash_log_path]) + self.assertEqual("test.html crashed!", + written_files[crash_log_path].decode(encoding='utf-8')) # Ensure the artifact in the json was replaced with the location of # the newly-created file. updated_json = self._load_json_output() @@ -470,12 +474,13 @@ "external", "wpt") actual_path = os.path.join(artifact_subdir, "test-actual.txt") - self.assertEqual("test.html actual text", written_files[actual_path]) + self.assertEqual("test.html actual text", + written_files[actual_path].decode(encoding='utf-8')) # The checked-in metadata file gets renamed from .ini to -expected.txt expected_path = os.path.join(artifact_subdir, "test-expected.txt") self.assertEqual("test.html checked-in metadata", - written_files[expected_path]) + written_files[expected_path].decode(encoding='utf-8')) # Ensure the artifacts in the json were replaced with the locations of # the newly-created files. updated_json = self._load_json_output() @@ -496,8 +501,9 @@ # validate the entire diff files to avoid checking line numbers/markup. diff_path = os.path.join(artifact_subdir, "test-diff.txt") self.assertIn("-test.html checked-in metadata", - written_files[diff_path]) - self.assertIn("+test.html actual text", written_files[diff_path]) + written_files[diff_path].decode(encoding='utf-8')) + self.assertIn("+test.html actual text", + written_files[diff_path].decode(encoding='utf-8')) self.assertEqual( [diff_path], updated_json["tests"]["external"]["wpt"]["test.html"]["artifacts"] @@ -505,8 +511,9 @@ pretty_diff_path = os.path.join(artifact_subdir, "test-pretty-diff.html") self.assertIn("test.html checked-in metadata", - written_files[pretty_diff_path]) - self.assertIn("test.html actual text", written_files[pretty_diff_path]) + written_files[pretty_diff_path].decode(encoding='utf-8')) + self.assertIn("test.html actual text", + written_files[pretty_diff_path].decode(encoding='utf-8')) self.assertEqual( [pretty_diff_path], updated_json["tests"]["external"]["wpt"]["test.html"]["artifacts"] @@ -546,12 +553,12 @@ actual_path = os.path.join(artifact_subdir, "variant_foo=bar_abc-actual.txt") self.assertEqual("variant bar/abc actual text", - written_files[actual_path]) + written_files[actual_path].decode(encoding='utf-8')) # The checked-in metadata file gets renamed from .ini to -expected.txt expected_path = os.path.join(artifact_subdir, "variant_foo=bar_abc-expected.txt") self.assertEqual("variant.html checked-in metadata", - written_files[expected_path]) + written_files[expected_path].decode(encoding='utf-8')) # Ensure the artifacts in the json were replaced with the locations of # the newly-created files. updated_json = self._load_json_output() @@ -605,13 +612,13 @@ actual_path = os.path.join(artifact_subdir, "dir/multiglob.https.any.worker-actual.txt") self.assertEqual("dir/multiglob worker actual text", - written_files[actual_path]) + written_files[actual_path].decode(encoding='utf-8')) # The checked-in metadata file gets renamed from .ini to -expected.txt expected_path = os.path.join( artifact_subdir, "dir/multiglob.https.any.worker-expected.txt") self.assertEqual("dir/multiglob checked-in metadata", - written_files[expected_path]) + written_files[expected_path].decode(encoding='utf-8')) # Ensure the artifacts in the json were replaced with the locations of # the newly-created files. updated_json = self._load_json_output()
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index 413e4f2..ecd534e 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -4318,6 +4318,30 @@ ] } ], + "IgnoreSyncEncryptionKeysLongMissing": [ + { + "platforms": [ + "android", + "chromeos", + "chromeos_lacros", + "ios", + "linux", + "mac", + "windows" + ], + "experiments": [ + { + "name": "Enabled", + "params": { + "MinGuResponsesToIgnoreKey": "2" + }, + "enable_features": [ + "IgnoreSyncEncryptionKeysLongMissing" + ] + } + ] + } + ], "IncludeInitiallyInvisibleImagesInLCP": [ { "platforms": [ @@ -5328,6 +5352,24 @@ ] } ], + "OmniboxPedalsBatch3": [ + { + "platforms": [ + "chromeos", + "linux", + "mac", + "windows" + ], + "experiments": [ + { + "name": "Batch3_Enabled", + "enable_features": [ + "OmniboxPedalsBatch3" + ] + } + ] + } + ], "OmniboxUpdatedConnectionSecurityIndicatorsIPH": [ { "platforms": [ @@ -7520,6 +7562,40 @@ ] } ], + "TabSearchEntrypointChevronIcon": [ + { + "platforms": [ + "chromeos", + "chromeos_lacros", + "linux", + "mac" + ], + "experiments": [ + { + "name": "Enabled", + "enable_features": [ + "TabSearchChevronIcon" + ] + } + ] + } + ], + "TabSearchEntrypointWindowsEntrypoint": [ + { + "platforms": [ + "windows" + ], + "experiments": [ + { + "name": "Enabled", + "enable_features": [ + "TabSearchChevronIcon", + "Win10TabSearchCaptionButton" + ] + } + ] + } + ], "TabSearchIPH": [ { "platforms": [ @@ -8105,7 +8181,6 @@ { "platforms": [ "android", - "chromeos_lacros", "ios", "linux", "mac", @@ -8135,7 +8210,8 @@ }, { "platforms": [ - "chromeos" + "chromeos", + "chromeos_lacros" ], "experiments": [ { @@ -8679,24 +8755,6 @@ ] } ], - "WebRTC-DataChannel-Dcsctp": [ - { - "platforms": [ - "android", - "chromeos", - "chromeos_lacros", - "ios", - "linux", - "mac", - "windows" - ], - "experiments": [ - { - "name": "Enabled" - } - ] - } - ], "WebRTC-TaskQueuePacer": [ { "platforms": [
diff --git a/third_party/blink/common/loader/url_loader_factory_bundle.cc b/third_party/blink/common/loader/url_loader_factory_bundle.cc index c8dcae3..39e16d96 100644 --- a/third_party/blink/common/loader/url_loader_factory_bundle.cc +++ b/third_party/blink/common/loader/url_loader_factory_bundle.cc
@@ -59,7 +59,6 @@ PendingURLLoaderFactoryBundle::CreateFactory() { auto other = std::make_unique<PendingURLLoaderFactoryBundle>(); other->pending_default_factory_ = std::move(pending_default_factory_); - other->pending_appcache_factory_ = std::move(pending_appcache_factory_); other->pending_scheme_specific_factories_ = std::move(pending_scheme_specific_factories_); other->pending_isolated_world_factories_ = @@ -93,10 +92,6 @@ return it2->second.get(); } - // AppCache factory must be used if it's given. - if (appcache_factory_) - return appcache_factory_.get(); - // Hitting the DCHECK below means that a subresource load has unexpectedly // happened in a speculative frame (or in a test frame created via // RenderViewTest). This most likely indicates a bug somewhere else. @@ -137,11 +132,6 @@ CloneRemoteMapToPendingRemoteMap(isolated_world_factories_), bypass_redirect_checks_); - if (appcache_factory_) { - appcache_factory_->Clone(pending_factories->pending_appcache_factory() - .InitWithNewPipeAndPassReceiver()); - } - return pending_factories; } @@ -156,11 +146,6 @@ default_factory_.Bind( std::move(pending_factories->pending_default_factory())); } - if (pending_factories->pending_appcache_factory()) { - appcache_factory_.reset(); - appcache_factory_.Bind( - std::move(pending_factories->pending_appcache_factory())); - } BindPendingRemoteMapToRemoteMap( &scheme_specific_factories_, std::move(pending_factories->pending_scheme_specific_factories()));
diff --git a/third_party/blink/common/loader/url_loader_factory_bundle_mojom_traits.cc b/third_party/blink/common/loader/url_loader_factory_bundle_mojom_traits.cc index 843e839..9ed45a86 100644 --- a/third_party/blink/common/loader/url_loader_factory_bundle_mojom_traits.cc +++ b/third_party/blink/common/loader/url_loader_factory_bundle_mojom_traits.cc
@@ -22,12 +22,6 @@ } // static -mojo::PendingRemote<network::mojom::URLLoaderFactory> Traits::appcache_factory( - BundleInfoType& bundle) { - return std::move(bundle->pending_appcache_factory()); -} - -// static blink::PendingURLLoaderFactoryBundle::SchemeMap Traits::scheme_specific_factories(BundleInfoType& bundle) { return std::move(bundle->pending_scheme_specific_factories()); @@ -51,8 +45,6 @@ (*out_bundle)->pending_default_factory() = data.TakeDefaultFactory< mojo::PendingRemote<network::mojom::URLLoaderFactory>>(); - (*out_bundle)->pending_appcache_factory() = data.TakeAppcacheFactory< - mojo::PendingRemote<network::mojom::URLLoaderFactory>>(); if (!data.ReadSchemeSpecificFactories( &(*out_bundle)->pending_scheme_specific_factories())) { return false;
diff --git a/third_party/blink/public/common/loader/url_loader_factory_bundle.h b/third_party/blink/public/common/loader/url_loader_factory_bundle.h index eab9f521..e47e393 100644 --- a/third_party/blink/public/common/loader/url_loader_factory_bundle.h +++ b/third_party/blink/public/common/loader/url_loader_factory_bundle.h
@@ -60,11 +60,6 @@ return pending_default_factory_; } - mojo::PendingRemote<network::mojom::URLLoaderFactory>& - pending_appcache_factory() { - return pending_appcache_factory_; - } - SchemeMap& pending_scheme_specific_factories() { return pending_scheme_specific_factories_; } @@ -85,8 +80,6 @@ mojo::PendingRemote<network::mojom::URLLoaderFactory> pending_default_factory_; - mojo::PendingRemote<network::mojom::URLLoaderFactory> - pending_appcache_factory_; SchemeMap pending_scheme_specific_factories_; // TODO(https://crbug.com/1098410): Remove the @@ -156,11 +149,6 @@ // context should not be given access to the network. mojo::Remote<network::mojom::URLLoaderFactory> default_factory_; - // |appcache_factory_| is a special loader factory that intercepts - // requests when the context has AppCache. See also - // AppCacheSubresourceURLFactory. - mojo::Remote<network::mojom::URLLoaderFactory> appcache_factory_; - // Map from URL scheme to Remote<URLLoaderFactory> for handling URL requests // for schemes not handled by the |default_factory_|. See also // PendingURLLoaderFactoryBundle::SchemeMap and
diff --git a/third_party/blink/public/mojom/loader/url_loader_factory_bundle.mojom b/third_party/blink/public/mojom/loader/url_loader_factory_bundle.mojom index 82abe20d..aa3e86f 100644 --- a/third_party/blink/public/mojom/loader/url_loader_factory_bundle.mojom +++ b/third_party/blink/public/mojom/loader/url_loader_factory_bundle.mojom
@@ -30,10 +30,6 @@ map<url.mojom.Origin, pending_remote<network.mojom.URLLoaderFactory>> isolated_world_factories; - // A special factory that is used for AppCache. - // TODO(https://crbug.com/582750): Drop this when AppCache is deprecated. - pending_remote<network.mojom.URLLoaderFactory>? appcache_factory; - // Whether redirect checks should be bypassed, since they are happening in the // browser. bool bypass_redirect_checks = false;
diff --git a/third_party/blink/public/platform/child_url_loader_factory_bundle.h b/third_party/blink/public/platform/child_url_loader_factory_bundle.h index 70656202..f4cdf67 100644 --- a/third_party/blink/public/platform/child_url_loader_factory_bundle.h +++ b/third_party/blink/public/platform/child_url_loader_factory_bundle.h
@@ -38,8 +38,6 @@ ChildPendingURLLoaderFactoryBundle( mojo::PendingRemote<network::mojom::URLLoaderFactory> pending_default_factory, - mojo::PendingRemote<network::mojom::URLLoaderFactory> - pending_default_network_factory, SchemeMap pending_scheme_specific_factories, OriginMap pending_isolated_world_factories, mojo::PendingRemote<network::mojom::URLLoaderFactory> @@ -58,7 +56,6 @@ std::unique_ptr<ChildPendingURLLoaderFactoryBundle> pending_bundle( new ChildPendingURLLoaderFactoryBundle( std::move(pending_default_factory), - {}, // pending_default_network_factory {}, // pending_scheme_specific_factories {}, // pending_isolated_world_factories {}, // pending_prefetch_loader_factory @@ -100,13 +97,6 @@ override; std::unique_ptr<network::PendingSharedURLLoaderFactory> Clone() override; - // Does the same as Clone(), but without cloning the appcache_factory_. - // This is used for creating a bundle for network fallback loading with - // Service Workers (where AppCache must be skipped), and only when - // claim() is called. - virtual std::unique_ptr<network::PendingSharedURLLoaderFactory> - CloneWithoutAppCacheFactory(); - std::unique_ptr<ChildPendingURLLoaderFactoryBundle> PassInterface(); void Update( @@ -124,9 +114,6 @@ ~ChildURLLoaderFactoryBundle() override; private: - std::unique_ptr<network::PendingSharedURLLoaderFactory> CloneInternal( - bool include_appcache); - mojo::Remote<network::mojom::URLLoaderFactory> prefetch_loader_factory_; std::map<GURL, mojom::TransferrableURLLoaderPtr> subresource_overrides_;
diff --git a/third_party/blink/public/platform/tracked_child_url_loader_factory_bundle.h b/third_party/blink/public/platform/tracked_child_url_loader_factory_bundle.h index 1810078a..05df1e5 100644 --- a/third_party/blink/public/platform/tracked_child_url_loader_factory_bundle.h +++ b/third_party/blink/public/platform/tracked_child_url_loader_factory_bundle.h
@@ -31,8 +31,6 @@ TrackedChildPendingURLLoaderFactoryBundle( mojo::PendingRemote<network::mojom::URLLoaderFactory> pending_default_factory, - mojo::PendingRemote<network::mojom::URLLoaderFactory> - pending_appcache_factory, SchemeMap pending_scheme_specific_factories, OriginMap pending_isolated_world_factories, mojo::PendingRemote<network::mojom::URLLoaderFactory> @@ -135,8 +133,6 @@ // ChildURLLoaderFactoryBundle overrides. // Returns |std::unique_ptr<TrackedChildPendingURLLoaderFactoryBundle>|. std::unique_ptr<network::PendingSharedURLLoaderFactory> Clone() override; - std::unique_ptr<network::PendingSharedURLLoaderFactory> - CloneWithoutAppCacheFactory() override; bool IsHostChildURLLoaderFactoryBundle() const override; // Update this bundle with |info|, and post cloned |info| to tracked bundles.
diff --git a/third_party/blink/renderer/bindings/idl_in_core.gni b/third_party/blink/renderer/bindings/idl_in_core.gni index f721185..350c7a8 100644 --- a/third_party/blink/renderer/bindings/idl_in_core.gni +++ b/third_party/blink/renderer/bindings/idl_in_core.gni
@@ -645,6 +645,7 @@ "//third_party/blink/renderer/core/svg/svg_view_element.idl", "//third_party/blink/renderer/core/svg/svg_zoom_and_pan.idl", "//third_party/blink/renderer/core/timing/dom_high_res_time_stamp.idl", + "//third_party/blink/renderer/core/timing/epoch_time_stamp.idl", "//third_party/blink/renderer/core/timing/event_counts.idl", "//third_party/blink/renderer/core/timing/internals_profiler.idl", "//third_party/blink/renderer/core/timing/largest_contentful_paint.idl",
diff --git a/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_serializer_for_modules_test.cc b/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_serializer_for_modules_test.cc index 761019b..eb212b5 100644 --- a/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_serializer_for_modules_test.cc +++ b/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_serializer_for_modules_test.cc
@@ -14,7 +14,7 @@ #include "third_party/blink/renderer/bindings/core/v8/dictionary.h" #include "third_party/blink/renderer/bindings/core/v8/script_function.h" #include "third_party/blink/renderer/bindings/core/v8/script_value.h" -#include "third_party/blink/renderer/bindings/core/v8/to_v8_for_core.h" +#include "third_party/blink/renderer/bindings/core/v8/to_v8_traits.h" #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h" #include "third_party/blink/renderer/bindings/core/v8/v8_dom_exception.h" #include "third_party/blink/renderer/bindings/core/v8/v8_dom_rect_read_only.h"
diff --git a/third_party/blink/renderer/bindings/modules/v8/v8_binding_for_modules_test.cc b/third_party/blink/renderer/bindings/modules/v8/v8_binding_for_modules_test.cc index b76a6c62..030fe87 100644 --- a/third_party/blink/renderer/bindings/modules/v8/v8_binding_for_modules_test.cc +++ b/third_party/blink/renderer/bindings/modules/v8/v8_binding_for_modules_test.cc
@@ -32,7 +32,7 @@ #include "third_party/blink/public/platform/web_string.h" #include "third_party/blink/renderer/bindings/core/v8/serialization/serialization_tag.h" #include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h" -#include "third_party/blink/renderer/bindings/core/v8/to_v8_for_core.h" +#include "third_party/blink/renderer/bindings/core/v8/to_v8_traits.h" #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h" #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h" #include "third_party/blink/renderer/bindings/core/v8/v8_object_builder.h"
diff --git a/third_party/blink/renderer/core/css/cascade_layer_map.cc b/third_party/blink/renderer/core/css/cascade_layer_map.cc index 47052b2..62e0cc1 100644 --- a/third_party/blink/renderer/core/css/cascade_layer_map.cc +++ b/third_party/blink/renderer/core/css/cascade_layer_map.cc
@@ -8,7 +8,8 @@ namespace blink { -const unsigned CascadeLayerMap::kImplicitOuterLayerOrder = 0; +const unsigned CascadeLayerMap::kImplicitOuterLayerOrder = + std::numeric_limits<unsigned>::max(); namespace { @@ -34,9 +35,9 @@ void ComputeLayerOrder(const CascadeLayer& layer, unsigned& next, LayerOrderMap& layer_order_map) { - layer_order_map.insert(&layer, next++); for (const auto& sub_layer : layer.GetDirectSubLayers()) ComputeLayerOrder(*sub_layer, next, layer_order_map); + layer_order_map.insert(&layer, next++); } } // namespace @@ -53,15 +54,23 @@ } } - unsigned next = kImplicitOuterLayerOrder; + unsigned next = 0; LayerOrderMap canonical_layer_order_map; ComputeLayerOrder(*canonical_root_layer, next, canonical_layer_order_map); + canonical_layer_order_map.Set(canonical_root_layer, kImplicitOuterLayerOrder); + for (const auto& iter : canonical_layer_map) { const CascadeLayer* layer_from_sheet = iter.key; const CascadeLayer* canonical_layer = iter.value; unsigned layer_order = canonical_layer_order_map.at(canonical_layer); layer_order_map_.insert(layer_from_sheet, layer_order); + +#if DCHECK_IS_ON() + // The implicit outer layer is placed above all explicit layers. + if (canonical_layer != canonical_root_layer) + DCHECK_LT(layer_order, kImplicitOuterLayerOrder); +#endif } }
diff --git a/third_party/blink/renderer/core/css/cssom/css_style_value.cc b/third_party/blink/renderer/core/css/cssom/css_style_value.cc index c8b1f00b..1b06f74 100644 --- a/third_party/blink/renderer/core/css/cssom/css_style_value.cc +++ b/third_party/blink/renderer/core/css/cssom/css_style_value.cc
@@ -5,7 +5,7 @@ #include "third_party/blink/renderer/core/css/cssom/css_style_value.h" #include "third_party/blink/renderer/bindings/core/v8/script_value.h" -#include "third_party/blink/renderer/bindings/core/v8/to_v8_for_core.h" +#include "third_party/blink/renderer/bindings/core/v8/to_v8_traits.h" #include "third_party/blink/renderer/core/css/cssom/style_value_factory.h" #include "third_party/blink/renderer/core/css/parser/css_parser_context.h" #include "third_party/blink/renderer/core/css/properties/css_property.h"
diff --git a/third_party/blink/renderer/core/css/resolver/match_result.h b/third_party/blink/renderer/core/css/resolver/match_result.h index 9748793d..a65ba21 100644 --- a/third_party/blink/renderer/core/css/resolver/match_result.h +++ b/third_party/blink/renderer/core/css/resolver/match_result.h
@@ -144,7 +144,7 @@ private: unsigned link_match_type_ = CSSSelector::kMatchAll; ValidPropertyFilter valid_property_filter_ = ValidPropertyFilter::kNoFilter; - unsigned layer_order_ = CascadeLayerMap::kImplicitOuterLayerOrder; + unsigned layer_order_ = 0; bool is_inline_style_ = false; friend class Builder;
diff --git a/third_party/blink/renderer/core/css/resolver/style_resolver_test.cc b/third_party/blink/renderer/core/css/resolver/style_resolver_test.cc index 57510c1..23e6d05 100644 --- a/third_party/blink/renderer/core/css/resolver/style_resolver_test.cc +++ b/third_party/blink/renderer/core/css/resolver/style_resolver_test.cc
@@ -1385,19 +1385,22 @@ const auto& properties = match_result.GetMatchedProperties(); ASSERT_EQ(properties.size(), 3u); + const uint16_t kImplicitOuterLayerOrder = + CascadeLayerMap::kImplicitOuterLayerOrder; + // div { display: block; } EXPECT_TRUE(properties[0].properties->HasProperty(CSSPropertyID::kDisplay)); - EXPECT_EQ(0u, properties[0].types_.layer_order); + EXPECT_EQ(kImplicitOuterLayerOrder, properties[0].types_.layer_order); EXPECT_EQ(properties[0].types_.origin, CascadeOrigin::kUserAgent); // .b { font-size: 16px; } EXPECT_TRUE(properties[1].properties->HasProperty(CSSPropertyID::kFontSize)); - EXPECT_EQ(0u, properties[1].types_.layer_order); + EXPECT_EQ(kImplicitOuterLayerOrder, properties[1].types_.layer_order); EXPECT_EQ(properties[1].types_.origin, CascadeOrigin::kAuthor); // #a { color: green; } EXPECT_TRUE(properties[2].properties->HasProperty(CSSPropertyID::kColor)); - EXPECT_EQ(0u, properties[2].types_.layer_order); + EXPECT_EQ(kImplicitOuterLayerOrder, properties[2].types_.layer_order); EXPECT_EQ(properties[2].types_.origin, CascadeOrigin::kAuthor); } @@ -1431,26 +1434,30 @@ const auto& properties = match_result.GetMatchedProperties(); ASSERT_EQ(properties.size(), 4u); + const uint16_t kImplicitOuterLayerOrder = + CascadeLayerMap::kImplicitOuterLayerOrder; + // div { display: block; } EXPECT_TRUE(properties[0].properties->HasProperty(CSSPropertyID::kDisplay)); - EXPECT_EQ(0u, properties[0].types_.layer_order); + EXPECT_EQ(kImplicitOuterLayerOrder, properties[0].types_.layer_order); EXPECT_EQ(properties[0].types_.origin, CascadeOrigin::kUserAgent); // @layer foo { #a { font-size: 16px } }" EXPECT_TRUE(properties[1].properties->HasProperty(CSSPropertyID::kFontSize)); - EXPECT_EQ(1u, properties[1].types_.layer_order); + EXPECT_EQ(0u, properties[1].types_.layer_order); EXPECT_EQ(properties[1].types_.origin, CascadeOrigin::kAuthor); // @layer bar { .b { color: green } }" EXPECT_TRUE(properties[2].properties->HasProperty(CSSPropertyID::kColor)); - EXPECT_EQ(2u, properties[2].types_.layer_order); + EXPECT_EQ(1u, properties[2].types_.layer_order); EXPECT_EQ(properties[2].types_.origin, CascadeOrigin::kAuthor); // style="font-family: custom" EXPECT_TRUE( properties[3].properties->HasProperty(CSSPropertyID::kFontFamily)); - EXPECT_EQ(0u, properties[3].types_.layer_order); + EXPECT_TRUE(properties[3].types_.is_inline_style); EXPECT_EQ(properties[3].types_.origin, CascadeOrigin::kAuthor); + // There's no layer order for inline style; it's always above all layers. } TEST_F(StyleResolverTest, CascadeLayersInDifferentTreeScopes) { @@ -1488,21 +1495,24 @@ const auto& properties = match_result.GetMatchedProperties(); ASSERT_EQ(properties.size(), 3u); + const uint16_t kImplicitOuterLayerOrder = + CascadeLayerMap::kImplicitOuterLayerOrder; + // div { display: block } EXPECT_TRUE(properties[0].properties->HasProperty(CSSPropertyID::kDisplay)); - EXPECT_EQ(0u, properties[0].types_.layer_order); + EXPECT_EQ(kImplicitOuterLayerOrder, properties[0].types_.layer_order); EXPECT_EQ(properties[0].types_.origin, CascadeOrigin::kUserAgent); // @layer bar { :host { font-size: 16px } } EXPECT_TRUE(properties[1].properties->HasProperty(CSSPropertyID::kFontSize)); - EXPECT_EQ(1u, properties[1].types_.layer_order); + EXPECT_EQ(0u, properties[1].types_.layer_order); EXPECT_EQ(properties[1].types_.origin, CascadeOrigin::kAuthor); EXPECT_EQ(match_result.ScopeFromTreeOrder(properties[1].types_.tree_order), GetDocument().getElementById("host")->GetShadowRoot()); // @layer foo { #host { color: green } } EXPECT_TRUE(properties[2].properties->HasProperty(CSSPropertyID::kColor)); - EXPECT_EQ(1u, properties[2].types_.layer_order); + EXPECT_EQ(0u, properties[2].types_.layer_order); EXPECT_EQ(match_result.ScopeFromTreeOrder(properties[2].types_.tree_order), &GetDocument()); } @@ -1514,10 +1524,10 @@ GetDocument().documentElement()->setInnerHTML(R"HTML( <style> + @page { margin-top: 100px; } @layer { - @page { margin-top: 100px; } + @page { margin-top: 50px; } } - @page { margin-top: 50px; } </style> )HTML");
diff --git a/third_party/blink/renderer/core/css/style_engine_test.cc b/third_party/blink/renderer/core/css/style_engine_test.cc index a44c8d9..0c8160c 100644 --- a/third_party/blink/renderer/core/css/style_engine_test.cc +++ b/third_party/blink/renderer/core/css/style_engine_test.cc
@@ -4071,24 +4071,25 @@ UpdateAllLifecyclePhases(); - // User layer order: (implicit outer layer), foo, bar + // User layer order: foo, bar, (implicit outer layer) auto* user_layer_map = GetStyleEngine().GetUserCascadeLayerMap(); ASSERT_TRUE(user_layer_map); const CascadeLayer& user_outer_layer = user_sheet->GetRuleSet().CascadeLayers(); EXPECT_EQ("", user_outer_layer.GetName()); - EXPECT_EQ(0u, user_layer_map->GetLayerOrder(user_outer_layer)); + EXPECT_EQ(CascadeLayerMap::kImplicitOuterLayerOrder, + user_layer_map->GetLayerOrder(user_outer_layer)); const CascadeLayer& user_foo = *user_outer_layer.GetDirectSubLayers()[0]; EXPECT_EQ("foo", user_foo.GetName()); - EXPECT_EQ(1u, user_layer_map->GetLayerOrder(user_foo)); + EXPECT_EQ(0u, user_layer_map->GetLayerOrder(user_foo)); const CascadeLayer& user_bar = *user_outer_layer.GetDirectSubLayers()[1]; EXPECT_EQ("bar", user_bar.GetName()); - EXPECT_EQ(2u, user_layer_map->GetLayerOrder(user_bar)); + EXPECT_EQ(1u, user_layer_map->GetLayerOrder(user_bar)); - // Document scope author layer order: (implicit outer layer), bar, foo + // Document scope author layer order: bar, foo, (implicit outer layer) auto* document_layer_map = GetDocument().GetScopedStyleResolver()->GetCascadeLayerMap(); ASSERT_TRUE(document_layer_map); @@ -4100,19 +4101,20 @@ ->GetRuleSet() .CascadeLayers(); EXPECT_EQ("", document_outer_layer.GetName()); - EXPECT_EQ(0u, document_layer_map->GetLayerOrder(document_outer_layer)); + EXPECT_EQ(CascadeLayerMap::kImplicitOuterLayerOrder, + document_layer_map->GetLayerOrder(document_outer_layer)); const CascadeLayer& document_bar = *document_outer_layer.GetDirectSubLayers()[0]; EXPECT_EQ("bar", document_bar.GetName()); - EXPECT_EQ(1u, document_layer_map->GetLayerOrder(document_bar)); + EXPECT_EQ(0u, document_layer_map->GetLayerOrder(document_bar)); const CascadeLayer& document_foo = *document_outer_layer.GetDirectSubLayers()[1]; EXPECT_EQ("foo", document_foo.GetName()); - EXPECT_EQ(2u, document_layer_map->GetLayerOrder(document_foo)); + EXPECT_EQ(1u, document_layer_map->GetLayerOrder(document_foo)); - // Shadow scope author layer order: (implicit outer layer), foo, foo.baz, bar + // Shadow scope author layer order: foo.baz, foo, bar, (implicit outer layer) ShadowRoot* shadow = GetDocument().getElementById("host")->GetShadowRoot(); auto* shadow_layer_map = shadow->GetScopedStyleResolver()->GetCascadeLayerMap(); @@ -4125,7 +4127,8 @@ ->GetRuleSet() .CascadeLayers(); EXPECT_EQ("", shadow_outer_layer.GetName()); - EXPECT_EQ(0u, shadow_layer_map->GetLayerOrder(shadow_outer_layer)); + EXPECT_EQ(CascadeLayerMap::kImplicitOuterLayerOrder, + shadow_layer_map->GetLayerOrder(shadow_outer_layer)); const CascadeLayer& shadow_foo = *shadow_outer_layer.GetDirectSubLayers()[0]; EXPECT_EQ("foo", shadow_foo.GetName()); @@ -4133,11 +4136,11 @@ const CascadeLayer& shadow_foo_baz = *shadow_foo.GetDirectSubLayers()[0]; EXPECT_EQ("baz", shadow_foo_baz.GetName()); - EXPECT_EQ(2u, shadow_layer_map->GetLayerOrder(shadow_foo_baz)); + EXPECT_EQ(0u, shadow_layer_map->GetLayerOrder(shadow_foo_baz)); const CascadeLayer& shadow_bar = *shadow_outer_layer.GetDirectSubLayers()[1]; EXPECT_EQ("bar", shadow_bar.GetName()); - EXPECT_EQ(3u, shadow_layer_map->GetLayerOrder(shadow_bar)); + EXPECT_EQ(2u, shadow_layer_map->GetLayerOrder(shadow_bar)); } TEST_F(StyleEngineTest, CascadeLayersFromMultipleSheets) { @@ -4156,7 +4159,7 @@ UpdateAllLifecyclePhases(); // Final layer ordering: - // (implicit outer layer), foo, foo.quux, bar, bar.qux, baz + // foo.quux, foo, bar.qux, bar, baz, (implicit outer layer) auto* layer_map = GetDocument().GetScopedStyleResolver()->GetCascadeLayerMap(); ASSERT_TRUE(layer_map); @@ -4168,7 +4171,8 @@ ->GetRuleSet() .CascadeLayers(); EXPECT_EQ("", sheet1_outer_layer.GetName()); - EXPECT_EQ(0u, layer_map->GetLayerOrder(sheet1_outer_layer)); + EXPECT_EQ(CascadeLayerMap::kImplicitOuterLayerOrder, + layer_map->GetLayerOrder(sheet1_outer_layer)); const CascadeLayer& sheet1_foo = *sheet1_outer_layer.GetDirectSubLayers()[0]; EXPECT_EQ("foo", sheet1_foo.GetName()); @@ -4185,11 +4189,12 @@ ->GetRuleSet() .CascadeLayers(); EXPECT_EQ("", sheet2_outer_layer.GetName()); - EXPECT_EQ(0u, layer_map->GetLayerOrder(sheet2_outer_layer)); + EXPECT_EQ(CascadeLayerMap::kImplicitOuterLayerOrder, + layer_map->GetLayerOrder(sheet2_outer_layer)); const CascadeLayer& sheet2_baz = *sheet2_outer_layer.GetDirectSubLayers()[0]; EXPECT_EQ("baz", sheet2_baz.GetName()); - EXPECT_EQ(5u, layer_map->GetLayerOrder(sheet2_baz)); + EXPECT_EQ(4u, layer_map->GetLayerOrder(sheet2_baz)); const CascadeLayer& sheet2_bar = *sheet2_outer_layer.GetDirectSubLayers()[1]; EXPECT_EQ("bar", sheet2_bar.GetName()); @@ -4197,7 +4202,7 @@ const CascadeLayer& sheet2_bar_qux = *sheet2_bar.GetDirectSubLayers()[0]; EXPECT_EQ("qux", sheet2_bar_qux.GetName()); - EXPECT_EQ(4u, layer_map->GetLayerOrder(sheet2_bar_qux)); + EXPECT_EQ(2u, layer_map->GetLayerOrder(sheet2_bar_qux)); const CascadeLayer& sheet2_foo = *sheet2_outer_layer.GetDirectSubLayers()[2]; EXPECT_EQ("foo", sheet2_foo.GetName()); @@ -4205,7 +4210,7 @@ const CascadeLayer& sheet2_foo_quux = *sheet2_foo.GetDirectSubLayers()[0]; EXPECT_EQ("quux", sheet2_foo_quux.GetName()); - EXPECT_EQ(2u, layer_map->GetLayerOrder(sheet2_foo_quux)); + EXPECT_EQ(0u, layer_map->GetLayerOrder(sheet2_foo_quux)); } TEST_F(StyleEngineTest, CascadeLayersNotExplicitlyDeclared) {
diff --git a/third_party/blink/renderer/core/exported/web_array_buffer_converter.cc b/third_party/blink/renderer/core/exported/web_array_buffer_converter.cc index 0008abc..f9f8032e 100644 --- a/third_party/blink/renderer/core/exported/web_array_buffer_converter.cc +++ b/third_party/blink/renderer/core/exported/web_array_buffer_converter.cc
@@ -31,7 +31,7 @@ #include "third_party/blink/public/web/web_array_buffer_converter.h" #include "third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.h" -#include "third_party/blink/renderer/bindings/core/v8/to_v8_for_core.h" +#include "third_party/blink/renderer/bindings/core/v8/to_v8_traits.h" #include "third_party/blink/renderer/platform/bindings/exception_state.h" namespace blink {
diff --git a/third_party/blink/renderer/core/layout/build.gni b/third_party/blink/renderer/core/layout/build.gni index 6d20156..6727a66 100644 --- a/third_party/blink/renderer/core/layout/build.gni +++ b/third_party/blink/renderer/core/layout/build.gni
@@ -322,6 +322,7 @@ "ng/grid/layout_ng_grid.h", "ng/grid/layout_ng_grid_interface.h", "ng/grid/ng_grid_data.h", + "ng/grid/ng_grid_geometry.h", "ng/grid/ng_grid_layout_algorithm.cc", "ng/grid/ng_grid_layout_algorithm.h", "ng/grid/ng_grid_node.cc",
diff --git a/third_party/blink/renderer/core/layout/ng/flex/ng_flex_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/flex/ng_flex_layout_algorithm.cc index ed21aee..3f21c78 100644 --- a/third_party/blink/renderer/core/layout/ng/flex/ng_flex_layout_algorithm.cc +++ b/third_party/blink/renderer/core/layout/ng/flex/ng_flex_layout_algorithm.cc
@@ -322,6 +322,72 @@ return space_builder.ToConstraintSpace(); } +NGConstraintSpace NGFlexLayoutAlgorithm::BuildSpaceForLayout( + const FlexItem& flex_item) const { + const ComputedStyle& child_style = flex_item.ng_input_node_.Style(); + NGConstraintSpaceBuilder space_builder(ConstraintSpace(), + child_style.GetWritingDirection(), + /* is_new_fc */ true); + SetOrthogonalFallbackInlineSizeIfNeeded(Style(), flex_item.ng_input_node_, + &space_builder); + space_builder.SetIsPaintedAtomically(true); + + LogicalSize available_size; + if (is_column_) { + available_size.inline_size = ChildAvailableSize().inline_size; + available_size.block_size = + flex_item.flexed_content_size_ + flex_item.main_axis_border_padding_; + space_builder.SetIsFixedBlockSize(true); + if (WillChildCrossSizeBeContainerCrossSize(flex_item.ng_input_node_)) + space_builder.SetInlineAutoBehavior(NGAutoBehavior::kStretchExplicit); + // https://drafts.csswg.org/css-flexbox/#definite-sizes + // If the flex container has a definite main size, a flex item's + // post-flexing main size is treated as definite, even though it can + // rely on the indefinite sizes of any flex items in the same line. + // TODO(crbug.com/1255340): This logic, and the similar below call to + // IsColumnContainerMainSizeDefinite need some refinement. + if (!IsColumnContainerMainSizeDefinite() && + !IsItemFlexBasisDefinite(flex_item.ng_input_node_) && + !IsItemMainSizeDefinite(flex_item.ng_input_node_)) { + space_builder.SetIsInitialBlockSizeIndefinite(true); + } + } else { + available_size.inline_size = + flex_item.flexed_content_size_ + flex_item.main_axis_border_padding_; + available_size.block_size = ChildAvailableSize().block_size; + space_builder.SetIsFixedInlineSize(true); + if (WillChildCrossSizeBeContainerCrossSize(flex_item.ng_input_node_)) + space_builder.SetBlockAutoBehavior(NGAutoBehavior::kStretchExplicit); + } + if (DoesItemStretch(flex_item.ng_input_node_)) { + // For stretched items, the goal of this layout is determine the + // post-flexed, pre-stretched cross-axis size. Stretched items will + // later get a final layout with a potentially different cross size so + // use the "measure" slot for this layout. We will use the "layout" + // cache slot for the item's final layout. + // + // Setting the "measure" cache slot on the space writes the result + // into both the "measure" and "layout" cache slots. So the stretch + // layout will reuse this "measure" result if it can. + space_builder.SetCacheSlot(NGCacheSlot::kMeasure); + } + + space_builder.SetAvailableSize(available_size); + space_builder.SetPercentageResolutionSize(child_percentage_size_); + space_builder.SetReplacedPercentageResolutionSize(child_percentage_size_); + + // For a button child, we need the baseline type same as the container's + // baseline type for UseCounter. For example, if the container's display + // property is 'inline-block', we need the last-line baseline of the + // child. See the bottom of GiveLinesAndItemsFinalPositionAndSize(). + if (Node().IsButton()) { + space_builder.SetBaselineAlgorithmType( + ConstraintSpace().BaselineAlgorithmType()); + } + + return space_builder.ToConstraintSpace(); +} + void NGFlexLayoutAlgorithm::ConstructAndAppendFlexItems() { NGFlexChildIterator iterator(Node()); @@ -741,69 +807,8 @@ } for (wtf_size_t i = 0; i < line->line_items_.size(); ++i) { FlexItem& flex_item = line->line_items_[i]; + NGConstraintSpace child_space = BuildSpaceForLayout(flex_item); - const ComputedStyle& child_style = flex_item.ng_input_node_.Style(); - NGConstraintSpaceBuilder space_builder(ConstraintSpace(), - child_style.GetWritingDirection(), - /* is_new_fc */ true); - SetOrthogonalFallbackInlineSizeIfNeeded(Style(), flex_item.ng_input_node_, - &space_builder); - space_builder.SetIsPaintedAtomically(true); - - LogicalSize available_size; - if (is_column_) { - available_size.inline_size = ChildAvailableSize().inline_size; - available_size.block_size = flex_item.flexed_content_size_ + - flex_item.main_axis_border_padding_; - space_builder.SetIsFixedBlockSize(true); - if (WillChildCrossSizeBeContainerCrossSize(flex_item.ng_input_node_)) - space_builder.SetInlineAutoBehavior(NGAutoBehavior::kStretchExplicit); - // https://drafts.csswg.org/css-flexbox/#definite-sizes - // If the flex container has a definite main size, a flex item's - // post-flexing main size is treated as definite, even though it can - // rely on the indefinite sizes of any flex items in the same line. - // TODO(crbug.com/1255340): This logic, and the similar below call to - // IsColumnContainerMainSizeDefinite need some refinement. - if (!IsColumnContainerMainSizeDefinite() && - !IsItemFlexBasisDefinite(flex_item.ng_input_node_) && - !IsItemMainSizeDefinite(flex_item.ng_input_node_)) { - space_builder.SetIsInitialBlockSizeIndefinite(true); - } - } else { - available_size.inline_size = flex_item.flexed_content_size_ + - flex_item.main_axis_border_padding_; - available_size.block_size = ChildAvailableSize().block_size; - space_builder.SetIsFixedInlineSize(true); - if (WillChildCrossSizeBeContainerCrossSize(flex_item.ng_input_node_)) - space_builder.SetBlockAutoBehavior(NGAutoBehavior::kStretchExplicit); - } - if (DoesItemStretch(flex_item.ng_input_node_)) { - // For stretched items, the goal of this layout is determine the - // post-flexed, pre-stretched cross-axis size. Stretched items will - // later get a final layout with a potentially different cross size so - // use the "measure" slot for this layout. We will use the "layout" - // cache slot for the item's final layout. - // - // Setting the "measure" cache slot on the space writes the result - // into both the "measure" and "layout" cache slots. So the stretch - // layout will reuse this "measure" result if it can. - space_builder.SetCacheSlot(NGCacheSlot::kMeasure); - } - - space_builder.SetAvailableSize(available_size); - space_builder.SetPercentageResolutionSize(child_percentage_size_); - space_builder.SetReplacedPercentageResolutionSize(child_percentage_size_); - - // For a button child, we need the baseline type same as the container's - // baseline type for UseCounter. For example, if the container's display - // property is 'inline-block', we need the last-line baseline of the - // child. See the bottom of GiveLinesAndItemsFinalPositionAndSize(). - if (Node().IsButton()) { - space_builder.SetBaselineAlgorithmType( - ConstraintSpace().BaselineAlgorithmType()); - } - - NGConstraintSpace child_space = space_builder.ToConstraintSpace(); // We need to get the item's cross axis size given its new main size. If // the new main size is the item's inline size, then we have to do a // layout to get its new block size. But if the new main size is the @@ -819,7 +824,8 @@ DCHECK(!MainAxisIsInlineAxis(flex_item.ng_input_node_)); NGBoxStrut border = ComputeBorders(child_space, flex_item.ng_input_node_); - NGBoxStrut padding = ComputePadding(child_space, child_style); + NGBoxStrut padding = + ComputePadding(child_space, flex_item.ng_input_node_.Style()); if (flex_item.ng_input_node_.IsReplaced()) { LogicalSize logical_border_box_size = ComputeReplacedSize( flex_item.ng_input_node_, child_space, border + padding);
diff --git a/third_party/blink/renderer/core/layout/ng/flex/ng_flex_layout_algorithm.h b/third_party/blink/renderer/core/layout/ng/flex/ng_flex_layout_algorithm.h index 2f0704f..d9fc6c19 100644 --- a/third_party/blink/renderer/core/layout/ng/flex/ng_flex_layout_algorithm.h +++ b/third_party/blink/renderer/core/layout/ng/flex/ng_flex_layout_algorithm.h
@@ -57,6 +57,7 @@ NGConstraintSpace BuildSpaceForFlexBasis(const NGBlockNode& flex_item) const; NGConstraintSpace BuildSpaceForIntrinsicBlockSize( const NGBlockNode& flex_item) const; + NGConstraintSpace BuildSpaceForLayout(const FlexItem& flex_item) const; void ConstructAndAppendFlexItems(); void ApplyStretchAlignmentToChild(FlexItem& flex_item); bool GiveLinesAndItemsFinalPositionAndSize();
diff --git a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_geometry.h b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_geometry.h new file mode 100644 index 0000000..c26d754 --- /dev/null +++ b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_geometry.h
@@ -0,0 +1,100 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_GRID_NG_GRID_GEOMETRY_H_ +#define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_GRID_NG_GRID_GEOMETRY_H_ + +#include "third_party/blink/renderer/core/layout/ng/grid/ng_grid_data.h" +#include "third_party/blink/renderer/platform/geometry/layout_unit.h" +#include "third_party/blink/renderer/platform/wtf/vector.h" + +namespace blink { + +using SetOffsetData = NGGridData::SetData; + +// Contains the information about the start offset of the tracks, as well as +// the gutter size between them, for a given direction. +struct TrackGeometry { + LayoutUnit start_offset; + LayoutUnit gutter_size; +}; + +// Represents the offsets for the sets, and the gutter-size. +// +// Initially we only know some of the set sizes - others will be indefinite. To +// represent this we store both the offset for the set, and a vector of all +// last indefinite indices (or kNotFound if everything so far has been +// definite). This allows us to get the appropriate size if a grid item spans +// only fixed tracks, but will allow us to return an indefinite size if it +// spans any indefinite set. +// +// As an example: +// grid-template-rows: auto auto 100px 100px auto 100px; +// +// Results in: +// | auto | auto | 100 | 100 | auto | 100 | +// [{0, kNotFound}, {0, 0}, {0, 1}, {100, 1}, {200, 1}, {200, 4}, {300, 4}] +// +// Various queries (start/end refer to the grid lines): +// start: 0, end: 1 -> indefinite as: +// "start <= sets[end].last_indefinite_index" +// start: 1, end: 3 -> indefinite as: +// "start <= sets[end].last_indefinite_index" +// start: 2, end: 4 -> 200px +// start: 5, end: 6 -> 100px +// start: 3, end: 5 -> indefinite as: +// "start <= sets[end].last_indefinite_index" +struct SetGeometry { + SetGeometry() = default; + + SetGeometry(const TrackGeometry track_alignment_geometry, + const wtf_size_t set_count) + : gutter_size(track_alignment_geometry.gutter_size) { + sets.ReserveInitialCapacity(set_count); + sets.emplace_back(track_alignment_geometry.start_offset, + /* track_count */ kNotFound); + } + + SetGeometry(const Vector<SetOffsetData>& sets, const LayoutUnit gutter_size) + : sets(sets), gutter_size(gutter_size) {} + + LayoutUnit FinalGutterSize() const { + DCHECK_GT(sets.size(), 0u); + return (sets.size() == 1) ? LayoutUnit() : gutter_size; + } + + Vector<wtf_size_t> last_indefinite_indices; + Vector<SetOffsetData> sets; + LayoutUnit gutter_size; +}; + +// Contains all the geometry information relevant to the final grid. This +// should have all the grid information needed to size and position items. +struct NGGridGeometry { + NGGridGeometry(SetGeometry&& column_geometry, SetGeometry&& row_geometry) + : column_geometry(column_geometry), + row_geometry(row_geometry), + major_inline_baselines(column_geometry.sets.size(), LayoutUnit::Min()), + minor_inline_baselines(column_geometry.sets.size(), LayoutUnit::Min()), + major_block_baselines(row_geometry.sets.size(), LayoutUnit::Min()), + minor_block_baselines(row_geometry.sets.size(), LayoutUnit::Min()) {} + + NGGridGeometry() = default; + + const SetGeometry& Geometry(GridTrackSizingDirection track_direction) const { + return (track_direction == kForColumns) ? column_geometry : row_geometry; + } + + SetGeometry column_geometry; + SetGeometry row_geometry; + + Vector<LayoutUnit> major_inline_baselines; + Vector<LayoutUnit> minor_inline_baselines; + Vector<LayoutUnit> major_block_baselines; + Vector<LayoutUnit> minor_block_baselines; +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_GRID_NG_GRID_GEOMETRY_H_
diff --git a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.cc index b907ffc..a9fa795 100644 --- a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.cc +++ b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.cc
@@ -92,8 +92,6 @@ namespace { -using SetGeometry = NGGridLayoutAlgorithm::SetGeometry; - LayoutUnit ComputeSetSpanSize(const SetGeometry& set_geometry, const GridItemIndices& set_indices) { DCHECK_LT(set_indices.end, set_geometry.sets.size()); @@ -151,8 +149,7 @@ ConstructAndAppendGridItems(&grid_items, &grid_properties, &out_of_flow_items); - const auto& container_style = Style(); - NGGridPlacement grid_placement(container_style, + NGGridPlacement grid_placement(Style(), ComputeAutomaticRepetitions(kForColumns), ComputeAutomaticRepetitions(kForRows)); @@ -162,186 +159,21 @@ BuildBlockTrackCollections(&grid_items, &column_block_track_collection, &row_block_track_collection, &grid_placement); - GridGeometry grid_geometry; NGGridLayoutAlgorithmTrackCollection column_track_collection; NGGridLayoutAlgorithmTrackCollection row_track_collection; - - auto ComputeGrid = [&]() { - // Build algorithm track collections from the block track collections. - column_track_collection = NGGridLayoutAlgorithmTrackCollection( - column_block_track_collection, - grid_available_size_.inline_size == kIndefiniteSize, &grid_properties); - row_track_collection = NGGridLayoutAlgorithmTrackCollection( - row_block_track_collection, - grid_available_size_.block_size == kIndefiniteSize, &grid_properties); - - // Cache set indices for grid items. - for (auto& grid_item : grid_items.item_data) { - grid_item.ComputeSetIndices(column_track_collection); - grid_item.ComputeSetIndices(row_track_collection); - } - - // Cache track span properties for grid items. - CacheGridItemsTrackSpanProperties(column_track_collection, &grid_items); - CacheGridItemsTrackSpanProperties(row_track_collection, &grid_items); - - // We perform the track sizing algorithm using two methods. First - // |InitializeTrackSizes|, which we need to get an initial column and row - // set geometry. Then |ComputeUsedTrackSizes|, to finalize the sizing - // algorithm for both dimensions. - grid_geometry = GridGeometry(InitializeTrackSizes(&column_track_collection), - InitializeTrackSizes(&row_track_collection)); - - // Store column baselines, as these contributions can influence column - // sizing. - bool needs_additional_pass = false; - if (grid_properties.HasBaseline(kForColumns)) { - CalculateAlignmentBaselines(kForColumns, &grid_geometry, &grid_items, - &needs_additional_pass); - } - - // Resolve inline size. - bool has_block_size_dependent_item = false; - grid_geometry.column_geometry = ComputeUsedTrackSizes( - SizingConstraint::kLayout, grid_geometry, grid_properties, - /* is_min_max_pass */ false, &column_track_collection, &grid_items, - &needs_additional_pass, &has_block_size_dependent_item); - - if (grid_properties.HasBaseline(kForRows)) { - CalculateAlignmentBaselines(kForRows, &grid_geometry, &grid_items, - &needs_additional_pass); - } - - absl::optional<SetGeometry> initial_row_geometry; - if (!needs_additional_pass && has_block_size_dependent_item) - initial_row_geometry = grid_geometry.row_geometry; - - // Resolve block size. - bool unused_needs_additional_pass = false; - grid_geometry.row_geometry = ComputeUsedTrackSizes( - SizingConstraint::kLayout, grid_geometry, grid_properties, - /* is_min_max_pass */ false, &row_track_collection, &grid_items, - &unused_needs_additional_pass); - - if (initial_row_geometry) { - DCHECK(!needs_additional_pass && has_block_size_dependent_item); - needs_additional_pass = MayChangeOrthogonalItemContributions( - *initial_row_geometry, grid_geometry.row_geometry, grid_items, - container_style.GetWritingMode()); - } - - // If we had an orthogonal item which may have depended on the resolved row - // tracks, re-run the track sizing algorithm for both dimensions. - if (needs_additional_pass) { - if (grid_properties.HasBaseline(kForColumns)) { - CalculateAlignmentBaselines(kForColumns, &grid_geometry, &grid_items, - &unused_needs_additional_pass); - } - - grid_geometry.column_geometry = - InitializeTrackSizes(&column_track_collection); - grid_geometry.column_geometry = ComputeUsedTrackSizes( - SizingConstraint::kLayout, grid_geometry, grid_properties, - /* is_min_max_pass */ false, &column_track_collection, &grid_items, - &unused_needs_additional_pass); - - if (grid_properties.HasBaseline(kForRows)) { - CalculateAlignmentBaselines(kForRows, &grid_geometry, &grid_items, - &unused_needs_additional_pass); - } - - grid_geometry.row_geometry = InitializeTrackSizes(&row_track_collection); - grid_geometry.row_geometry = ComputeUsedTrackSizes( - SizingConstraint::kLayout, grid_geometry, grid_properties, - /* is_min_max_pass */ false, &row_track_collection, &grid_items, - &unused_needs_additional_pass); - } - - if (grid_properties.HasBaseline(kForColumns)) { - CalculateAlignmentBaselines(kForColumns, &grid_geometry, &grid_items, - &unused_needs_additional_pass); - } - if (grid_properties.HasBaseline(kForRows)) { - CalculateAlignmentBaselines(kForRows, &grid_geometry, &grid_items, - &unused_needs_additional_pass); - } - DCHECK(!unused_needs_additional_pass); - }; - - ComputeGrid(); - LayoutUnit intrinsic_block_size; - if (contain_intrinsic_block_size_) { - intrinsic_block_size = *contain_intrinsic_block_size_; - } else { - // Intrinsic block size is based on the final row offset. Because gutters - // are included in row offsets, subtract out the final gutter (if present). - intrinsic_block_size = grid_geometry.row_geometry.sets.back().offset - - grid_geometry.row_geometry.FinalGutterSize() + - BorderScrollbarPadding().block_end; - // TODO(layout-dev): This isn't great but matches legacy. Ideally this - // would only apply when we have only flexible track(s). - if (grid_items.IsEmpty() && Node().HasLineIfEmpty()) { - intrinsic_block_size = - std::max(intrinsic_block_size, BorderScrollbarPadding().BlockSum() + - Node().EmptyLineBlockSize()); - } - - intrinsic_block_size = - ClampIntrinsicBlockSize(ConstraintSpace(), Node(), - BorderScrollbarPadding(), intrinsic_block_size); - } - - const LayoutUnit block_size = ComputeBlockSizeForFragment( - ConstraintSpace(), container_style, BorderPadding(), intrinsic_block_size, - border_box_size_.inline_size); - - if (grid_available_size_.block_size == kIndefiniteSize) { - const LayoutUnit resolved_available_block_size = - (block_size - BorderScrollbarPadding().BlockSum()) - .ClampNegativeToZero(); - - grid_available_size_.block_size = grid_min_available_size_.block_size = - grid_max_available_size_.block_size = resolved_available_block_size; - - // Re-compute the row geometry now that we have the resolved available - // block-size. "align-content: space-evenly" etc, require the resolved size. - if (container_style.AlignContent() != - ComputedStyleInitialValues::InitialAlignContent()) { - grid_geometry.row_geometry = ComputeSetGeometry(row_track_collection); - } - - // If we have any rows, gaps which will resolve differently if we have a - // definite |grid_available_size_| re-compute the grid using the - // |block_size| calculated above. - bool should_recompute_grid = - (container_style.RowGap() && - container_style.RowGap()->IsPercentOrCalc()) || - row_track_collection.DependsOnAvailableSize(); - - // If we are a flex-item, we may have our initial block-size forced to be - // indefinite, however grid layout always re-computes the grid using the - // final "used" block-size. - // We can detect this case by checking if computing our block-size (with an - // indefinite intrinsic size) is definite. - // - // TODO(layout-dev): A small optimization here would be to do this only if - // we have 'auto' tracks which fill the remaining available space. - if (ConstraintSpace().IsInitialBlockSizeIndefinite()) { - should_recompute_grid |= - ComputeBlockSizeForFragment( - ConstraintSpace(), container_style, BorderPadding(), - /* intrinsic_block_size */ kIndefiniteSize, - border_box_size_.inline_size) != kIndefiniteSize; - } - - if (should_recompute_grid) - ComputeGrid(); - } + const NGGridGeometry grid_geometry = ComputeGridGeometry( + column_block_track_collection, row_block_track_collection, &grid_items, + &column_track_collection, &row_track_collection, &grid_properties, + &intrinsic_block_size); PlaceGridItems(grid_items, grid_geometry); + const LayoutUnit block_size = ComputeBlockSizeForFragment( + ConstraintSpace(), Style(), BorderPadding(), intrinsic_block_size, + border_box_size_.inline_size); + // Cache range placement data for out of flow items. for (auto& out_of_flow_item : out_of_flow_items) { out_of_flow_item.ComputeOutOfFlowItemPlacement(column_track_collection, @@ -474,8 +306,8 @@ auto ComputeTotalColumnSize = [&](SizingConstraint sizing_constraint) -> LayoutUnit { - GridGeometry grid_geometry(InitializeTrackSizes(&column_track_collection), - InitializeTrackSizes(&row_track_collection)); + NGGridGeometry grid_geometry(InitializeTrackSizes(&column_track_collection), + InitializeTrackSizes(&row_track_collection)); bool needs_additional_pass = false; if (grid_properties.HasBaseline(kForColumns)) { @@ -785,12 +617,6 @@ item_data.ReserveCapacity(capacity); } -const NGGridLayoutAlgorithm::SetGeometry& -NGGridLayoutAlgorithm::GridGeometry::Geometry( - GridTrackSizingDirection track_direction) const { - return (track_direction == kForColumns) ? column_geometry : row_geometry; -} - namespace { using SetIterator = NGGridLayoutAlgorithmTrackCollection::SetIterator; @@ -925,52 +751,219 @@ } // namespace -void NGGridLayoutAlgorithm::GridGeometry::UpdateBaseline( - const GridItemData& grid_item, - LayoutUnit candidate_baseline, - GridTrackSizingDirection track_direction) { - LayoutUnit* track_baseline; - if (track_direction == kForColumns) { - // "If a box spans multiple shared alignment contexts, then it participates - // in first/last baseline alignment within its start-most/end-most shared - // alignment context along that axis", so we only need to look at the first - // index for baseline/first-baseline support. - // https://www.w3.org/TR/css-align-3/#baseline-sharing-group - const wtf_size_t set_index = grid_item.column_set_indices.begin; - track_baseline = (grid_item.column_baseline_type == BaselineType::kMajor) - ? &major_inline_baselines[set_index] - : &minor_inline_baselines[set_index]; - } else { - const wtf_size_t set_index = grid_item.row_set_indices.begin; - track_baseline = (grid_item.row_baseline_type == BaselineType::kMajor) - ? &major_block_baselines[set_index] - : &minor_block_baselines[set_index]; - } - - *track_baseline = std::max(*track_baseline, candidate_baseline); -} - -LayoutUnit NGGridLayoutAlgorithm::GridGeometry::Baseline( +LayoutUnit NGGridLayoutAlgorithm::Baseline( + const NGGridGeometry& grid_geometry, const GridItemData& grid_item, GridTrackSizingDirection track_direction) const { + // "If a box spans multiple shared alignment contexts, then it participates + // in first/last baseline alignment within its start-most/end-most shared + // alignment context along that axis", so we only need to look at the first + // index for baseline/first-baseline support. + // https://www.w3.org/TR/css-align-3/#baseline-sharing-group if (track_direction == kForColumns) { - // "If a box spans multiple shared alignment contexts, then it participates - // in first/last baseline alignment within its start-most/end-most shared - // alignment context along that axis", so we only need to look at the first - // index for baseline/first-baseline support. - // https://www.w3.org/TR/css-align-3/#baseline-sharing-group const wtf_size_t set_index = grid_item.column_set_indices.begin; return (grid_item.column_baseline_type == BaselineType::kMajor) - ? major_inline_baselines[set_index] - : minor_inline_baselines[set_index]; + ? grid_geometry.major_inline_baselines[set_index] + : grid_geometry.minor_inline_baselines[set_index]; } else { const wtf_size_t set_index = grid_item.row_set_indices.begin; return (grid_item.row_baseline_type == BaselineType::kMajor) - ? major_block_baselines[set_index] - : minor_block_baselines[set_index]; + ? grid_geometry.major_block_baselines[set_index] + : grid_geometry.minor_block_baselines[set_index]; } } +NGGridGeometry NGGridLayoutAlgorithm::ComputeGridGeometry( + const NGGridBlockTrackCollection& column_block_track_collection, + const NGGridBlockTrackCollection& row_block_track_collection, + GridItems* grid_items, + NGGridLayoutAlgorithmTrackCollection* column_track_collection, + NGGridLayoutAlgorithmTrackCollection* row_track_collection, + NGGridProperties* grid_properties, + LayoutUnit* intrinsic_block_size) { + DCHECK(grid_items && column_track_collection && row_track_collection && + grid_properties && intrinsic_block_size); + + const auto& container_style = Style(); + NGGridGeometry grid_geometry; + + auto ComputeGrid = [&]() { + // Build algorithm track collections from the block track collections. + *column_track_collection = NGGridLayoutAlgorithmTrackCollection( + column_block_track_collection, + grid_available_size_.inline_size == kIndefiniteSize, grid_properties); + *row_track_collection = NGGridLayoutAlgorithmTrackCollection( + row_block_track_collection, + grid_available_size_.block_size == kIndefiniteSize, grid_properties); + + // Cache set indices for grid items. + for (auto& grid_item : grid_items->item_data) { + grid_item.ComputeSetIndices(*column_track_collection); + grid_item.ComputeSetIndices(*row_track_collection); + } + + // Cache track span properties for grid items. + CacheGridItemsTrackSpanProperties(*column_track_collection, grid_items); + CacheGridItemsTrackSpanProperties(*row_track_collection, grid_items); + + // We perform the track sizing algorithm using two methods. First + // |InitializeTrackSizes|, which we need to get an initial column and row + // set geometry. Then |ComputeUsedTrackSizes|, to finalize the sizing + // algorithm for both dimensions. + grid_geometry = + NGGridGeometry(InitializeTrackSizes(column_track_collection), + InitializeTrackSizes(row_track_collection)); + + // Store column baselines, as these contributions can influence column + // sizing. + bool needs_additional_pass = false; + if (grid_properties->HasBaseline(kForColumns)) { + CalculateAlignmentBaselines(kForColumns, &grid_geometry, grid_items, + &needs_additional_pass); + } + + // Resolve inline size. + bool has_block_size_dependent_item = false; + grid_geometry.column_geometry = ComputeUsedTrackSizes( + SizingConstraint::kLayout, grid_geometry, *grid_properties, + /* is_min_max_pass */ false, column_track_collection, grid_items, + &needs_additional_pass, &has_block_size_dependent_item); + + if (grid_properties->HasBaseline(kForRows)) { + CalculateAlignmentBaselines(kForRows, &grid_geometry, grid_items, + &needs_additional_pass); + } + + absl::optional<SetGeometry> initial_row_geometry; + if (!needs_additional_pass && has_block_size_dependent_item) + initial_row_geometry = grid_geometry.row_geometry; + + // Resolve block size. + bool unused_needs_additional_pass = false; + grid_geometry.row_geometry = ComputeUsedTrackSizes( + SizingConstraint::kLayout, grid_geometry, *grid_properties, + /* is_min_max_pass */ false, row_track_collection, grid_items, + &unused_needs_additional_pass); + + if (initial_row_geometry) { + DCHECK(!needs_additional_pass && has_block_size_dependent_item); + needs_additional_pass = MayChangeOrthogonalItemContributions( + *initial_row_geometry, grid_geometry.row_geometry, *grid_items, + container_style.GetWritingMode()); + } + + // If we had an orthogonal item which may have depended on the resolved row + // tracks, re-run the track sizing algorithm for both dimensions. + if (needs_additional_pass) { + if (grid_properties->HasBaseline(kForColumns)) { + CalculateAlignmentBaselines(kForColumns, &grid_geometry, grid_items, + &unused_needs_additional_pass); + } + + grid_geometry.column_geometry = + InitializeTrackSizes(column_track_collection); + grid_geometry.column_geometry = ComputeUsedTrackSizes( + SizingConstraint::kLayout, grid_geometry, *grid_properties, + /* is_min_max_pass */ false, column_track_collection, grid_items, + &unused_needs_additional_pass); + + if (grid_properties->HasBaseline(kForRows)) { + CalculateAlignmentBaselines(kForRows, &grid_geometry, grid_items, + &unused_needs_additional_pass); + } + + grid_geometry.row_geometry = InitializeTrackSizes(row_track_collection); + grid_geometry.row_geometry = ComputeUsedTrackSizes( + SizingConstraint::kLayout, grid_geometry, *grid_properties, + /* is_min_max_pass */ false, row_track_collection, grid_items, + &unused_needs_additional_pass); + } + + if (grid_properties->HasBaseline(kForColumns)) { + CalculateAlignmentBaselines(kForColumns, &grid_geometry, grid_items, + &unused_needs_additional_pass); + } + if (grid_properties->HasBaseline(kForRows)) { + CalculateAlignmentBaselines(kForRows, &grid_geometry, grid_items, + &unused_needs_additional_pass); + } + DCHECK(!unused_needs_additional_pass); + }; + + ComputeGrid(); + + if (contain_intrinsic_block_size_) { + *intrinsic_block_size = *contain_intrinsic_block_size_; + } else { + // Intrinsic block size is based on the final row offset. Because gutters + // are included in row offsets, subtract out the final gutter (if present). + *intrinsic_block_size = grid_geometry.row_geometry.sets.back().offset - + grid_geometry.row_geometry.FinalGutterSize() + + BorderScrollbarPadding().block_end; + + // TODO(layout-dev): This isn't great but matches legacy. Ideally this + // would only apply when we have only flexible track(s). + if (grid_items->IsEmpty() && Node().HasLineIfEmpty()) { + *intrinsic_block_size = + std::max(*intrinsic_block_size, BorderScrollbarPadding().BlockSum() + + Node().EmptyLineBlockSize()); + } + + *intrinsic_block_size = ClampIntrinsicBlockSize(ConstraintSpace(), Node(), + BorderScrollbarPadding(), + *intrinsic_block_size); + } + + const LayoutUnit block_size = ComputeBlockSizeForFragment( + ConstraintSpace(), container_style, BorderPadding(), + *intrinsic_block_size, border_box_size_.inline_size); + + if (grid_available_size_.block_size == kIndefiniteSize) { + const LayoutUnit resolved_available_block_size = + (block_size - BorderScrollbarPadding().BlockSum()) + .ClampNegativeToZero(); + + grid_available_size_.block_size = grid_min_available_size_.block_size = + grid_max_available_size_.block_size = resolved_available_block_size; + + // Re-compute the row geometry now that we have the resolved available + // block-size. "align-content: space-evenly" etc, require the resolved size. + if (container_style.AlignContent() != + ComputedStyleInitialValues::InitialAlignContent()) { + grid_geometry.row_geometry = ComputeSetGeometry(*row_track_collection); + } + + // If we have any rows, gaps which will resolve differently if we have a + // definite |grid_available_size_| re-compute the grid using the + // |block_size| calculated above. + bool should_recompute_grid = + (container_style.RowGap() && + container_style.RowGap()->IsPercentOrCalc()) || + row_track_collection->DependsOnAvailableSize(); + + // If we are a flex-item, we may have our initial block-size forced to be + // indefinite, however grid layout always re-computes the grid using the + // final "used" block-size. + // We can detect this case by checking if computing our block-size (with an + // indefinite intrinsic size) is definite. + // + // TODO(layout-dev): A small optimization here would be to do this only if + // we have 'auto' tracks which fill the remaining available space. + if (ConstraintSpace().IsInitialBlockSizeIndefinite()) { + should_recompute_grid |= + ComputeBlockSizeForFragment( + ConstraintSpace(), container_style, BorderPadding(), + /* intrinsic_block_size */ kIndefiniteSize, + border_box_size_.inline_size) != kIndefiniteSize; + } + + if (should_recompute_grid) + ComputeGrid(); + } + + return grid_geometry; +} + LayoutUnit NGGridLayoutAlgorithm::ComputeIntrinsicBlockSizeIgnoringChildren() const { DCHECK(Node().ShouldApplyBlockSizeContainment()); @@ -999,8 +992,8 @@ row_block_track_collection, grid_available_size_.block_size == kIndefiniteSize, &grid_properties); - GridGeometry grid_geometry(SetGeometry(), - InitializeTrackSizes(&row_track_collection)); + NGGridGeometry grid_geometry(SetGeometry(), + InitializeTrackSizes(&row_track_collection)); // Resolve the rows. bool unused_needs_additional_pass = false; @@ -1015,7 +1008,7 @@ } LayoutUnit NGGridLayoutAlgorithm::ContributionSizeForGridItem( - const GridGeometry& grid_geometry, + const NGGridGeometry& grid_geometry, const GridItemData& grid_item, GridTrackSizingDirection track_direction, GridItemContributionType contribution_type, @@ -1106,13 +1099,13 @@ if (grid_item.IsBaselineAlignedForDirection(track_direction)) { LayoutUnit track_baseline = - grid_geometry.Baseline(grid_item, track_direction); + Baseline(grid_geometry, grid_item, track_direction); // The item's baseline alignment impacts the item's contribution as the // difference between the track's baseline and the item's baseline. if (track_baseline != LayoutUnit::Min()) { baseline_shim = - grid_geometry.Baseline(grid_item, track_direction) - + track_baseline - GetLogicalBaseline( fragment, track_direction, ConstraintSpace().GetWritingDirection().GetWritingMode()); @@ -1846,11 +1839,34 @@ void NGGridLayoutAlgorithm::CalculateAlignmentBaselines( const GridTrackSizingDirection track_direction, - GridGeometry* grid_geometry, + NGGridGeometry* grid_geometry, GridItems* grid_items, bool* needs_additional_pass) const { DCHECK(grid_geometry && grid_items && needs_additional_pass); + auto UpdateBaseline = [&](const GridItemData& grid_item, + LayoutUnit candidate_baseline) { + // "If a box spans multiple shared alignment contexts, then it participates + // in first/last baseline alignment within its start-most/end-most shared + // alignment context along that axis", so we only need to look at the first + // index for baseline/first-baseline support. + // https://www.w3.org/TR/css-align-3/#baseline-sharing-group + LayoutUnit* track_baseline; + if (track_direction == kForColumns) { + const wtf_size_t set_index = grid_item.column_set_indices.begin; + track_baseline = (grid_item.column_baseline_type == BaselineType::kMajor) + ? &grid_geometry->major_inline_baselines[set_index] + : &grid_geometry->minor_inline_baselines[set_index]; + } else { + const wtf_size_t set_index = grid_item.row_set_indices.begin; + track_baseline = (grid_item.row_baseline_type == BaselineType::kMajor) + ? &grid_geometry->major_block_baselines[set_index] + : &grid_geometry->minor_block_baselines[set_index]; + } + + *track_baseline = std::max(*track_baseline, candidate_baseline); + }; + // Reset existing baselines from geometry so they are clean with each call to // this method. Use 'WTF::Vector::Fill()' over 'WTF::Vector::clear()', as // 'clear' will reset the capacity to zero and require re-allocations. @@ -1906,13 +1922,13 @@ // a better solution. if (grid_item.IsBaselineAlignedForDirection(track_direction) || grid_item.node.IsReplaced()) { - grid_geometry->UpdateBaseline(grid_item, baseline, track_direction); + UpdateBaseline(grid_item, baseline); } } } // https://drafts.csswg.org/css-grid-2/#algo-init -NGGridLayoutAlgorithm::SetGeometry NGGridLayoutAlgorithm::InitializeTrackSizes( +SetGeometry NGGridLayoutAlgorithm::InitializeTrackSizes( NGGridLayoutAlgorithmTrackCollection* track_collection) const { DCHECK(track_collection); const auto track_direction = track_collection->Direction(); @@ -2003,9 +2019,9 @@ } // https://drafts.csswg.org/css-grid-2/#algo-track-sizing -NGGridLayoutAlgorithm::SetGeometry NGGridLayoutAlgorithm::ComputeUsedTrackSizes( +SetGeometry NGGridLayoutAlgorithm::ComputeUsedTrackSizes( SizingConstraint sizing_constraint, - const GridGeometry& grid_geometry, + const NGGridGeometry& grid_geometry, const NGGridProperties& grid_properties, const bool is_min_max_pass, NGGridLayoutAlgorithmTrackCollection* track_collection, @@ -2491,7 +2507,7 @@ } // namespace void NGGridLayoutAlgorithm::IncreaseTrackSizesToAccommodateGridItems( - const GridGeometry& grid_geometry, + const NGGridGeometry& grid_geometry, GridItems::Iterator group_begin, GridItems::Iterator group_end, const bool is_group_spanning_flex_track, @@ -2606,7 +2622,7 @@ // https://drafts.csswg.org/css-grid-2/#algo-content void NGGridLayoutAlgorithm::ResolveIntrinsicTrackSizes( - const GridGeometry& grid_geometry, + const NGGridGeometry& grid_geometry, bool is_min_max_pass, NGGridLayoutAlgorithmTrackCollection* track_collection, GridItems* grid_items, @@ -2825,7 +2841,7 @@ // https://drafts.csswg.org/css-grid-2/#algo-flex-tracks void NGGridLayoutAlgorithm::ExpandFlexibleTracks( SizingConstraint sizing_constraint, - const GridGeometry& grid_geometry, + const NGGridGeometry& grid_geometry, bool is_min_max_pass, NGGridLayoutAlgorithmTrackCollection* track_collection, GridItems* grid_items, @@ -3017,8 +3033,6 @@ namespace { -using TrackGeometry = NGGridLayoutAlgorithm::TrackGeometry; - TrackGeometry ComputeFirstTrackInCollectionGeometry( const ComputedStyle& style, const StyleContentAlignmentData& content_alignment, @@ -3132,7 +3146,7 @@ } // namespace // Calculates the offsets for all sets. -NGGridLayoutAlgorithm::SetGeometry NGGridLayoutAlgorithm::ComputeSetGeometry( +SetGeometry NGGridLayoutAlgorithm::ComputeSetGeometry( const NGGridLayoutAlgorithmTrackCollection& track_collection) const { const LayoutUnit available_size = track_collection.IsForColumns() ? grid_available_size_.inline_size @@ -3303,7 +3317,7 @@ } const NGConstraintSpace NGGridLayoutAlgorithm::CreateConstraintSpaceForLayout( - const GridGeometry& grid_geometry, + const NGGridGeometry& grid_geometry, const GridItemData& grid_item, LogicalRect* containing_grid_area) const { ComputeGridItemOffsetAndSize(grid_item, grid_geometry.column_geometry, @@ -3319,7 +3333,7 @@ } const NGConstraintSpace NGGridLayoutAlgorithm::CreateConstraintSpaceForMeasure( - const GridGeometry& grid_geometry, + const NGGridGeometry& grid_geometry, const GridItemData& grid_item, GridTrackSizingDirection track_direction, absl::optional<LayoutUnit> opt_fixed_block_size) const { @@ -3339,8 +3353,9 @@ opt_fixed_block_size, NGCacheSlot::kMeasure); } -void NGGridLayoutAlgorithm::PlaceGridItems(const GridItems& grid_items, - const GridGeometry& grid_geometry) { +void NGGridLayoutAlgorithm::PlaceGridItems( + const GridItems& grid_items, + const NGGridGeometry& grid_geometry) { const auto& container_space = ConstraintSpace(); const auto container_writing_direction = container_space.GetWritingDirection(); @@ -3382,7 +3397,7 @@ logical_fragment, track_direction, ConstraintSpace().GetWritingDirection().GetWritingMode()); LayoutUnit track_baseline = - grid_geometry.Baseline(grid_item, track_direction); + Baseline(grid_geometry, grid_item, track_direction); return (track_baseline != LayoutUnit::Min()) ? (track_baseline - item_baseline) : item_baseline; @@ -3466,7 +3481,7 @@ const NGGridLayoutAlgorithmTrackCollection& column_track_collection, const NGGridLayoutAlgorithmTrackCollection& row_track_collection, const GridItemStorageVector& out_of_flow_items, - const GridGeometry& grid_geometry, + const NGGridGeometry& grid_geometry, LayoutUnit block_size) { const LogicalSize fragment_size(container_builder_.InlineSize(), block_size); const LogicalSize default_containing_block_size = @@ -3547,7 +3562,7 @@ out_of_flow_item.ComputeOutOfFlowItemPlacement(row_placement_track_collection, grid_placement); - GridGeometry grid_geometry( + NGGridGeometry grid_geometry( SetGeometry(column_geometry.sets, column_geometry.gutter_size), SetGeometry(row_geometry.sets, row_geometry.gutter_size)); @@ -3560,7 +3575,7 @@ LogicalRect NGGridLayoutAlgorithm::ComputeContainingGridAreaRect( const NGGridLayoutAlgorithmTrackCollection& column_track_collection, const NGGridLayoutAlgorithmTrackCollection& row_track_collection, - const GridGeometry& grid_geometry, + const NGGridGeometry& grid_geometry, const GridItemData& out_of_flow_item, const NGBoxStrut& borders, const LogicalSize& border_box_size, @@ -3582,7 +3597,7 @@ namespace { Vector<std::div_t> ComputeTrackSizesInRange( - const NGGridLayoutAlgorithm::SetGeometry& set_geometry, + const SetGeometry& set_geometry, const wtf_size_t range_starting_set_index, const wtf_size_t range_set_count) { Vector<std::div_t> track_sizes; @@ -3612,11 +3627,10 @@ // For out of flow items that are located in the middle of a range, computes // the extra offset relative to the start of its containing range. -LayoutUnit ComputeTrackOffsetInRange( - const NGGridLayoutAlgorithm::SetGeometry& set_geometry, - const wtf_size_t range_starting_set_index, - const wtf_size_t range_set_count, - const wtf_size_t offset_in_range) { +LayoutUnit ComputeTrackOffsetInRange(const SetGeometry& set_geometry, + const wtf_size_t range_starting_set_index, + const wtf_size_t range_set_count, + const wtf_size_t offset_in_range) { if (!range_set_count || !offset_in_range) return LayoutUnit(); @@ -3650,7 +3664,7 @@ template <bool snap_to_end_of_track> LayoutUnit TrackOffset( const NGGridLayoutAlgorithmTrackCollection& track_collection, - const NGGridLayoutAlgorithm::SetGeometry& set_geometry, + const SetGeometry& set_geometry, const wtf_size_t range_index, const wtf_size_t offset_in_range) { const wtf_size_t range_starting_set_index = @@ -3687,7 +3701,7 @@ LayoutUnit TrackStartOffset( const NGGridLayoutAlgorithmTrackCollection& track_collection, - const NGGridLayoutAlgorithm::SetGeometry& set_geometry, + const SetGeometry& set_geometry, const wtf_size_t range_index, const wtf_size_t offset_in_range) { if (!track_collection.RangeCount()) { @@ -3717,7 +3731,7 @@ LayoutUnit TrackEndOffset( const NGGridLayoutAlgorithmTrackCollection& track_collection, - const NGGridLayoutAlgorithm::SetGeometry& set_geometry, + const SetGeometry& set_geometry, const wtf_size_t range_index, const wtf_size_t offset_in_range) { if (!track_collection.RangeCount()) {
diff --git a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.h b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.h index a04eb47..687ac8c 100644 --- a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.h +++ b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm.h
@@ -5,6 +5,7 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_GRID_NG_GRID_LAYOUT_ALGORITHM_H_ #define THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_NG_GRID_NG_GRID_LAYOUT_ALGORITHM_H_ +#include "third_party/blink/renderer/core/layout/ng/grid/ng_grid_geometry.h" #include "third_party/blink/renderer/core/layout/ng/grid/ng_grid_node.h" #include "third_party/blink/renderer/core/layout/ng/grid/ng_grid_track_collection.h" #include "third_party/blink/renderer/core/layout/ng/ng_block_break_token.h" @@ -213,100 +214,6 @@ NGBoxFragmentBuilder, NGBlockBreakToken> { public: - // Contains the information about the start offset of the tracks, as well as - // the gutter size between them, for a given direction. - struct TrackGeometry { - LayoutUnit start_offset; - LayoutUnit gutter_size; - }; - - // Represents the offsets for the sets, and the gutter-size. - // - // Initially we only know some of the set sizes - others will be indefinite. - // To represent this we store both the offset for the set, and a vector of - // all last indefinite indices (or kNotFound if everything so far has been - // definite). This allows us to get the appropriate size if a grid item - // spans only fixed tracks, but will allow us to return an indefinite size - // if it spans any indefinite set. - // - // As an example: - // grid-template-rows: auto auto 100px 100px auto 100px; - // - // Results in: - // | auto | auto | 100 | 100 | auto | 100 | - // [{0, kNotFound}, {0, 0}, {0, 1}, {100, 1}, {200, 1}, {200, 4}, {300, - // 4}] - // - // Various queries (start/end refer to the grid lines): - // start: 0, end: 1 -> indefinite as: - // "start <= sets[end].last_indefinite_index" - // start: 1, end: 3 -> indefinite as: - // "start <= sets[end].last_indefinite_index" - // start: 2, end: 4 -> 200px - // start: 5, end: 6 -> 100px - // start: 3, end: 5 -> indefinite as: - // "start <= sets[end].last_indefinite_index" - struct SetGeometry { - SetGeometry() = default; - - SetGeometry(const TrackGeometry track_alignment_geometry, - const wtf_size_t set_count) - : gutter_size(track_alignment_geometry.gutter_size) { - sets.ReserveInitialCapacity(set_count); - sets.emplace_back(track_alignment_geometry.start_offset, - /* track_count */ kNotFound); - } - - SetGeometry(const Vector<SetOffsetData>& sets, - const LayoutUnit gutter_size) - : sets(sets), gutter_size(gutter_size) {} - - LayoutUnit FinalGutterSize() const { - DCHECK_GT(sets.size(), 0u); - return (sets.size() == 1) ? LayoutUnit() : gutter_size; - } - - Vector<wtf_size_t> last_indefinite_indices; - Vector<SetOffsetData> sets; - LayoutUnit gutter_size; - }; - - // Typically we pass around both the column, and row geometry together. - struct GridGeometry { - GridGeometry(SetGeometry&& column_geometry, SetGeometry&& row_geometry) - : column_geometry(column_geometry), - row_geometry(row_geometry), - major_inline_baselines(column_geometry.sets.size(), - LayoutUnit::Min()), - minor_inline_baselines(column_geometry.sets.size(), - LayoutUnit::Min()), - major_block_baselines(row_geometry.sets.size(), LayoutUnit::Min()), - minor_block_baselines(row_geometry.sets.size(), LayoutUnit::Min()) { - } - - GridGeometry() = default; - - const SetGeometry& Geometry( - GridTrackSizingDirection track_direction) const; - - // Updates stored major/minor baseline value. - void UpdateBaseline(const GridItemData& grid_item, - LayoutUnit candidate_baseline, - GridTrackSizingDirection track_direction); - - // Retrieves major/minor baseline. - LayoutUnit Baseline(const GridItemData& grid_item, - GridTrackSizingDirection track_direction) const; - - SetGeometry column_geometry; - SetGeometry row_geometry; - - Vector<LayoutUnit> major_inline_baselines; - Vector<LayoutUnit> minor_inline_baselines; - Vector<LayoutUnit> major_block_baselines; - Vector<LayoutUnit> minor_block_baselines; - }; - explicit NGGridLayoutAlgorithm(const NGLayoutAlgorithmParams& params); scoped_refptr<const NGLayoutResult> Layout() override; @@ -335,12 +242,25 @@ enum class SizingConstraint { kLayout, kMinContent, kMaxContent }; + LayoutUnit Baseline(const NGGridGeometry& grid_geometry, + const GridItemData& grid_item, + GridTrackSizingDirection track_direction) const; + + NGGridGeometry ComputeGridGeometry( + const NGGridBlockTrackCollection& column_block_track_collection, + const NGGridBlockTrackCollection& row_block_track_collection, + GridItems* grid_items, + NGGridLayoutAlgorithmTrackCollection* column_track_collection, + NGGridLayoutAlgorithmTrackCollection* row_track_collection, + NGGridProperties* grid_properties, + LayoutUnit* intrinsic_block_size); + LayoutUnit ComputeIntrinsicBlockSizeIgnoringChildren() const; // Returns the size that a grid item will distribute across the tracks with // an intrinsic sizing function it spans in the relevant track direction. LayoutUnit ContributionSizeForGridItem( - const GridGeometry& grid_geometry, + const NGGridGeometry& grid_geometry, const GridItemData& grid_item, GridTrackSizingDirection track_direction, GridItemContributionType contribution_type, @@ -388,7 +308,7 @@ // on each item in |grid_items|, and stores the results in |grid_geometry|. void CalculateAlignmentBaselines( const GridTrackSizingDirection track_direction, - GridGeometry* grid_geometry, + NGGridGeometry* grid_geometry, GridItems* grid_items, bool* needs_additional_pass) const; @@ -401,7 +321,7 @@ // size. SetGeometry ComputeUsedTrackSizes( SizingConstraint sizing_constraint, - const GridGeometry& grid_geometry, + const NGGridGeometry& grid_geometry, const NGGridProperties& grid_properties, const bool is_min_max_pass, NGGridLayoutAlgorithmTrackCollection* track_collection, @@ -413,7 +333,7 @@ // size resolution defined in // https://drafts.csswg.org/css-grid-2/#algo-content. void ResolveIntrinsicTrackSizes( - const GridGeometry& grid_geometry, + const NGGridGeometry& grid_geometry, bool is_min_max_pass, NGGridLayoutAlgorithmTrackCollection* track_collection, GridItems* grid_items, @@ -421,7 +341,7 @@ bool* has_block_size_dependent_item) const; void IncreaseTrackSizesToAccommodateGridItems( - const GridGeometry& grid_geometry, + const NGGridGeometry& grid_geometry, GridItems::Iterator group_begin, GridItems::Iterator group_end, const bool is_group_spanning_flex_track, @@ -441,7 +361,7 @@ void ExpandFlexibleTracks( SizingConstraint sizing_constraint, - const GridGeometry& grid_geometry, + const NGGridGeometry& grid_geometry, bool is_min_max_pass, NGGridLayoutAlgorithmTrackCollection* track_collection, GridItems* grid_items, @@ -465,19 +385,19 @@ NGCacheSlot cache_slot) const; const NGConstraintSpace CreateConstraintSpaceForLayout( - const GridGeometry& grid_geometry, + const NGGridGeometry& grid_geometry, const GridItemData& grid_item, LogicalRect* containing_grid_area) const; const NGConstraintSpace CreateConstraintSpaceForMeasure( - const GridGeometry& grid_geometry, + const NGGridGeometry& grid_geometry, const GridItemData& grid_item, GridTrackSizingDirection track_direction, absl::optional<LayoutUnit> opt_fixed_block_size = absl::nullopt) const; // Layout the |grid_items| based on the offsets provided. void PlaceGridItems(const GridItems& grid_items, - const GridGeometry& grid_geometry); + const NGGridGeometry& grid_geometry); // Computes the static position, grid area and its offset of out of flow // elements in the grid. @@ -485,7 +405,7 @@ const NGGridLayoutAlgorithmTrackCollection& column_track_collection, const NGGridLayoutAlgorithmTrackCollection& row_track_collection, const GridItemStorageVector& out_of_flow_items, - const GridGeometry& grid_geometry, + const NGGridGeometry& grid_geometry, LayoutUnit block_size); // Helper method to compute the containing block rect for out of flow @@ -493,7 +413,7 @@ static LogicalRect ComputeContainingGridAreaRect( const NGGridLayoutAlgorithmTrackCollection& column_track_collection, const NGGridLayoutAlgorithmTrackCollection& row_track_collection, - const GridGeometry& grid_geometry, + const NGGridGeometry& grid_geometry, const GridItemData& item, const NGBoxStrut& borders, const LogicalSize& border_box_size,
diff --git a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm_test.cc b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm_test.cc index 3a308bac..400bd27 100644 --- a/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm_test.cc +++ b/third_party/blink/renderer/core/layout/ng/grid/ng_grid_layout_algorithm_test.cc
@@ -203,7 +203,7 @@ NGGridLayoutAlgorithmTrackCollection column_track_collection_; NGGridLayoutAlgorithmTrackCollection row_track_collection_; - NGGridLayoutAlgorithm::GridGeometry grid_geometry_; + NGGridGeometry grid_geometry_; }; TEST_F(NGGridLayoutAlgorithmTest, NGGridLayoutAlgorithmBaseSetSizes) {
diff --git a/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc b/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc index d852d2de..c88a09c 100644 --- a/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc +++ b/third_party/blink/renderer/core/paint/paint_property_tree_builder.cc
@@ -289,20 +289,13 @@ // Inside NG block fragmentation we have to perform an offset adjustment. // An OOF fragment that is contained by something inside a fragmentainer // will be a direct child of the fragmentainer, rather than a child of its - // actual containing block. We therefore need to adjust the offset to make - // us relative to the fragmentainer before applying the offset of the OOF. - PhysicalOffset delta = - oof_context.paint_offset - context_.fragmentainer_paint_offset; - // So, we did store |fragmentainer_paint_offset| when entering the - // fragmentainer, but the offset may have been reset by - // UpdateForPaintOffsetTranslation() since we entered it, which we'll need - // to compensate for now. - delta += context_.adjustment_for_oof_in_fragmentainer; - context_.current.paint_offset -= delta; + // actual containing block. Set the paint offset to the correct one. + context_.current.paint_offset = + context_.current.paint_offset_for_oof_in_fragmentainer; } void ResetPaintOffset(PhysicalOffset new_offset = PhysicalOffset()) { - context_.adjustment_for_oof_in_fragmentainer += + context_.current.paint_offset_for_oof_in_fragmentainer -= context_.current.paint_offset - new_offset; context_.current.paint_offset = new_offset; }
diff --git a/third_party/blink/renderer/core/paint/paint_property_tree_builder.h b/third_party/blink/renderer/core/paint/paint_property_tree_builder.h index 0202154..eeca586 100644 --- a/third_party/blink/renderer/core/paint/paint_property_tree_builder.h +++ b/third_party/blink/renderer/core/paint/paint_property_tree_builder.h
@@ -120,6 +120,11 @@ const ScrollPaintPropertyNode* scroll = nullptr; FloatSize pending_scroll_anchor_adjustment; + + // Paint offset of the innermost fragmentainer minus accumulated offsets + // that are baked in PaintOffsetTranslations since we entered the + // fragmentainer. + PhysicalOffset paint_offset_for_oof_in_fragmentainer; }; ContainingBlockContext current; @@ -162,13 +167,6 @@ PhysicalOffset old_paint_offset; - // Paint offset at the current innermost fragmentainer. - PhysicalOffset fragmentainer_paint_offset; - - // Amount of adjustment done by UpdateForPaintOffsetTranslation() since we - // entered the innermost fragmentainer. - PhysicalOffset adjustment_for_oof_in_fragmentainer; - // An additional offset that applies to the current fragment, but is detected // *before* the ContainingBlockContext is updated for it. Once the // ContainingBlockContext is set, this value should be added to
diff --git a/third_party/blink/renderer/core/paint/pre_paint_tree_walk.cc b/third_party/blink/renderer/core/paint/pre_paint_tree_walk.cc index 69f67f9..a125019 100644 --- a/third_party/blink/renderer/core/paint/pre_paint_tree_walk.cc +++ b/third_party/blink/renderer/core/paint/pre_paint_tree_walk.cc
@@ -810,22 +810,17 @@ continue; } - PaintPropertyTreeBuilderContext& tree_builder_context = - *context.tree_builder_context; - PaintPropertyTreeBuilderFragmentContext& fragment_context = - tree_builder_context.fragments[0]; - PaintPropertyTreeBuilderFragmentContext::ContainingBlockContext* - containing_block_context = &fragment_context.current; + auto* containing_block_context = + &context.tree_builder_context->fragments[0].current; containing_block_context->paint_offset += child.offset; const PhysicalOffset paint_offset = containing_block_context->paint_offset; - // Keep track of the paint offset at the fragmentainer, and also reset the - // offset adjustment tracker. This is needed when entering OOF - // descendants. OOFs have the nearest fragmentainer as their containing - // block, so when entering them during LayoutObject tree traversal, we have - // to compensate for this. - fragment_context.fragmentainer_paint_offset = paint_offset; - fragment_context.adjustment_for_oof_in_fragmentainer = PhysicalOffset(); + // Keep track of the paint offset at the fragmentainer. This is needed + // when entering OOF descendants. OOFs have the nearest fragmentainer as + // their containing block, so when entering them during LayoutObject tree + // traversal, we have to compensate for this. + containing_block_context->paint_offset_for_oof_in_fragmentainer = + paint_offset; // Create corresponding |FragmentData|. Hit-testing needs // |FragmentData.PaintOffset|.
diff --git a/third_party/blink/renderer/core/scroll/scroll_animator.cc b/third_party/blink/renderer/core/scroll/scroll_animator.cc index 78907f6..9c30061 100644 --- a/third_party/blink/renderer/core/scroll/scroll_animator.cc +++ b/third_party/blink/renderer/core/scroll/scroll_animator.cc
@@ -42,6 +42,12 @@ #include "third_party/blink/renderer/platform/graphics/graphics_layer.h" #include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h" +// This should be after all other #includes. +#if defined(_WINDOWS_) // Detect whether windows.h was included. +// See base/win/windows_h_disallowed.h for details. +#error Windows.h was included unexpectedly. +#endif // defined(_WINDOWS_) + namespace blink { ScrollAnimatorBase* ScrollAnimatorBase::Create(
diff --git a/third_party/blink/renderer/core/streams/readable_byte_stream_controller.cc b/third_party/blink/renderer/core/streams/readable_byte_stream_controller.cc index a2ede38..ed1d216f 100644 --- a/third_party/blink/renderer/core/streams/readable_byte_stream_controller.cc +++ b/third_party/blink/renderer/core/streams/readable_byte_stream_controller.cc
@@ -6,7 +6,7 @@ #include "base/numerics/checked_math.h" #include "base/numerics/clamped_math.h" -#include "third_party/blink/renderer/bindings/core/v8/to_v8_for_core.h" +#include "third_party/blink/renderer/bindings/core/v8/to_v8_traits.h" #include "third_party/blink/renderer/bindings/core/v8/v8_underlying_source.h" #include "third_party/blink/renderer/bindings/core/v8/v8_underlying_source_cancel_callback.h" #include "third_party/blink/renderer/bindings/core/v8/v8_underlying_source_pull_callback.h"
diff --git a/third_party/blink/renderer/core/streams/readable_stream_default_controller_with_script_scope.h b/third_party/blink/renderer/core/streams/readable_stream_default_controller_with_script_scope.h index 9843b82e..0a43b0c 100644 --- a/third_party/blink/renderer/core/streams/readable_stream_default_controller_with_script_scope.h +++ b/third_party/blink/renderer/core/streams/readable_stream_default_controller_with_script_scope.h
@@ -6,7 +6,7 @@ #define THIRD_PARTY_BLINK_RENDERER_CORE_STREAMS_READABLE_STREAM_DEFAULT_CONTROLLER_WITH_SCRIPT_SCOPE_H_ #include "third_party/blink/renderer/bindings/core/v8/script_value.h" -#include "third_party/blink/renderer/bindings/core/v8/to_v8_for_core.h" +#include "third_party/blink/renderer/bindings/core/v8/to_v8_traits.h" #include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/platform/heap/visitor.h" #include "v8/include/v8.h"
diff --git a/third_party/blink/renderer/core/streams/transferable_streams.cc b/third_party/blink/renderer/core/streams/transferable_streams.cc index 7455c7b4..98087ce 100644 --- a/third_party/blink/renderer/core/streams/transferable_streams.cc +++ b/third_party/blink/renderer/core/streams/transferable_streams.cc
@@ -9,7 +9,7 @@ #include "base/cxx17_backports.h" #include "third_party/blink/renderer/bindings/core/v8/script_function.h" -#include "third_party/blink/renderer/bindings/core/v8/to_v8_for_core.h" +#include "third_party/blink/renderer/bindings/core/v8/to_v8_traits.h" #include "third_party/blink/renderer/bindings/core/v8/v8_dom_exception.h" #include "third_party/blink/renderer/bindings/core/v8/v8_iterator_result_value.h" #include "third_party/blink/renderer/bindings/core/v8/v8_post_message_options.h"
diff --git a/third_party/blink/renderer/core/streams/writable_stream.cc b/third_party/blink/renderer/core/streams/writable_stream.cc index e635e50..038d3ab 100644 --- a/third_party/blink/renderer/core/streams/writable_stream.cc +++ b/third_party/blink/renderer/core/streams/writable_stream.cc
@@ -5,7 +5,7 @@ #include "third_party/blink/renderer/core/streams/writable_stream.h" #include "third_party/blink/renderer/bindings/core/v8/script_value.h" -#include "third_party/blink/renderer/bindings/core/v8/to_v8_for_core.h" +#include "third_party/blink/renderer/bindings/core/v8/to_v8_traits.h" #include "third_party/blink/renderer/bindings/core/v8/v8_queuing_strategy_init.h" #include "third_party/blink/renderer/core/streams/count_queuing_strategy.h" #include "third_party/blink/renderer/core/streams/miscellaneous_operations.h"
diff --git a/third_party/blink/renderer/core/timing/build.gni b/third_party/blink/renderer/core/timing/build.gni index c39d5d3..abc8cd0 100644 --- a/third_party/blink/renderer/core/timing/build.gni +++ b/third_party/blink/renderer/core/timing/build.gni
@@ -5,6 +5,7 @@ blink_core_sources_timing = [ "dom_window_performance.cc", "dom_window_performance.h", + "epoch_time_stamp.h", "event_counts.cc", "event_counts.h", "event_timing.cc",
diff --git a/third_party/blink/renderer/core/timing/epoch_time_stamp.h b/third_party/blink/renderer/core/timing/epoch_time_stamp.h new file mode 100644 index 0000000..d828fa1e --- /dev/null +++ b/third_party/blink/renderer/core/timing/epoch_time_stamp.h
@@ -0,0 +1,22 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_TIMING_EPOCH_TIME_STAMP_H_ +#define THIRD_PARTY_BLINK_RENDERER_CORE_TIMING_EPOCH_TIME_STAMP_H_ + +#include <stdint.h> + +#include "base/time/time.h" + +namespace blink { + +typedef uint64_t EpochTimeStamp; + +inline EpochTimeStamp ConvertTimeToEpochTimeStamp(base::Time time) { + return static_cast<EpochTimeStamp>(time.ToDoubleT() * 1000.0); +} + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_CORE_TIMING_EPOCH_TIME_STAMP_H_
diff --git a/third_party/blink/renderer/core/timing/epoch_time_stamp.idl b/third_party/blink/renderer/core/timing/epoch_time_stamp.idl new file mode 100644 index 0000000..b16a06d --- /dev/null +++ b/third_party/blink/renderer/core/timing/epoch_time_stamp.idl
@@ -0,0 +1,7 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// https://www.w3.org/TR/hr-time-3/#the-epochtimestamp-typedef + +typedef unsigned long long EpochTimeStamp;
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object.cc b/third_party/blink/renderer/modules/accessibility/ax_object.cc index bc95126..f0339f41 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_object.cc +++ b/third_party/blink/renderer/modules/accessibility/ax_object.cc
@@ -1056,7 +1056,7 @@ void AXObject::Serialize(ui::AXNodeData* node_data, ui::AXMode accessibility_mode) { - node_data->role = RoleValue(); + node_data->role = ComputeFinalRoleForSerialization(); node_data->id = AXObjectID(); DCHECK(!IsDetached()) << "Do not serialize detached nodes: " @@ -1727,6 +1727,22 @@ return false; } +ax::mojom::blink::Role AXObject::ComputeFinalRoleForSerialization() const { + // An SVG with no accessible children should be exposed as an image rather + // than a document. See https://github.com/w3c/svg-aam/issues/12. + // We do this check here for performance purposes: When + // AXLayoutObject::RoleFromLayoutObjectOrNode is called, that node's + // accessible children have not been calculated. Rather than force calculation + // there, wait until we have the full tree. + if (role_ == ax::mojom::blink::Role::kSvgRoot && !UnignoredChildCount()) + return ax::mojom::blink::Role::kImage; + + // TODO(accessibility): Consider moving the image vs. image map role logic + // here. Currently it is implemented in AXPlatformNode subclasses and thus + // not available to the InspectorAccessibilityAgent. + return role_; +} + ax::mojom::blink::Role AXObject::RoleValue() const { return role_; }
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object.h b/third_party/blink/renderer/modules/accessibility/ax_object.h index c4c07399..459e8ef 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_object.h +++ b/third_party/blink/renderer/modules/accessibility/ax_object.h
@@ -353,6 +353,14 @@ // Check object role or purpose. ax::mojom::blink::Role RoleValue() const; + // This method is useful in cases where the final role exposed to ATs needs + // to change based on contextual information. For instance, an svgRoot should + // be exposed as an image if it lacks accessible children. Whether or not it + // has accessible children is not known at the time the role is assigned and + // may depend on whether or not a given platform includes children that other + // platforms ignore. + ax::mojom::blink::Role ComputeFinalRoleForSerialization() const; + // Returns true if this object is an ARIA text field, i.e. it is neither an // <input> nor a <textarea>, but it has an ARIA role of textbox, searchbox or // (on certain platforms) combobox.
diff --git a/third_party/blink/renderer/modules/accessibility/inspector_accessibility_agent.cc b/third_party/blink/renderer/modules/accessibility/inspector_accessibility_agent.cc index 40a016c9..fc45597 100644 --- a/third_party/blink/renderer/modules/accessibility/inspector_accessibility_agent.cc +++ b/third_party/blink/renderer/modules/accessibility/inspector_accessibility_agent.cc
@@ -211,7 +211,7 @@ void FillWidgetProperties(AXObject& ax_object, protocol::Array<AXProperty>& properties) { - ax::mojom::Role role = ax_object.RoleValue(); + ax::mojom::blink::Role role = ax_object.ComputeFinalRoleForSerialization(); String autocomplete = ax_object.AutoComplete(); if (!autocomplete.IsEmpty()) properties.emplace_back( @@ -303,7 +303,7 @@ void FillWidgetStates(AXObject& ax_object, protocol::Array<AXProperty>& properties) { - ax::mojom::Role role = ax_object.RoleValue(); + ax::mojom::blink::Role role = ax_object.ComputeFinalRoleForSerialization(); const char* checked_prop_val = nullptr; switch (ax_object.CheckedState()) { case ax::mojom::CheckedState::kTrue: @@ -695,7 +695,7 @@ bool fetch_relatives, std::unique_ptr<protocol::Array<AXNode>>& nodes, AXObjectCacheImpl& cache) const { - ax::mojom::Role role = ax_object.RoleValue(); + ax::mojom::blink::Role role = ax_object.ComputeFinalRoleForSerialization(); std::unique_ptr<AXNode> node_object = AXNode::create() .setNodeId(String::Number(ax_object.AXObjectID())) @@ -957,7 +957,7 @@ namespace { void setNameAndRole(const AXObject& ax_object, std::unique_ptr<AXNode>& node) { - ax::mojom::blink::Role role = ax_object.RoleValue(); + ax::mojom::blink::Role role = ax_object.ComputeFinalRoleForSerialization(); node->setRole(CreateRoleNameValue(role)); AXObject::NameSources name_sources; String computed_name = ax_object.GetName(&name_sources); @@ -1021,7 +1021,8 @@ // if querying by role: skip if role of current object does not match. if (role.isJust() && - role.fromJust() != AXObject::RoleName(ax_object->RoleValue())) { + role.fromJust() != + AXObject::RoleName(ax_object->ComputeFinalRoleForSerialization())) { continue; }
diff --git a/third_party/blink/renderer/modules/breakout_box/media_stream_audio_track_underlying_sink_test.cc b/third_party/blink/renderer/modules/breakout_box/media_stream_audio_track_underlying_sink_test.cc index 309fcc2..9a61f282 100644 --- a/third_party/blink/renderer/modules/breakout_box/media_stream_audio_track_underlying_sink_test.cc +++ b/third_party/blink/renderer/modules/breakout_box/media_stream_audio_track_underlying_sink_test.cc
@@ -11,7 +11,7 @@ #include "third_party/blink/public/platform/modules/mediastream/web_media_stream_audio_sink.h" #include "third_party/blink/public/web/web_heap.h" #include "third_party/blink/renderer/bindings/core/v8/script_promise_tester.h" -#include "third_party/blink/renderer/bindings/core/v8/to_v8_for_core.h" +#include "third_party/blink/renderer/bindings/core/v8/to_v8_traits.h" #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_audio_data.h" #include "third_party/blink/renderer/core/streams/writable_stream.h"
diff --git a/third_party/blink/renderer/modules/geolocation/geolocation.cc b/third_party/blink/renderer/modules/geolocation/geolocation.cc index 4f504ec..854280a 100644 --- a/third_party/blink/renderer/modules/geolocation/geolocation.cc +++ b/third_party/blink/renderer/modules/geolocation/geolocation.cc
@@ -40,6 +40,7 @@ #include "third_party/blink/renderer/core/inspector/console_message.h" #include "third_party/blink/renderer/core/page/page.h" #include "third_party/blink/renderer/core/probe/core_probes.h" +#include "third_party/blink/renderer/core/timing/epoch_time_stamp.h" #include "third_party/blink/renderer/modules/geolocation/geolocation_coordinates.h" #include "third_party/blink/renderer/modules/geolocation/geolocation_error.h" @@ -64,8 +65,7 @@ position.heading >= 0. && position.heading <= 360., position.heading, position.speed >= 0., position.speed); return MakeGarbageCollected<Geoposition>( - coordinates, - ConvertSecondsToDOMTimeStamp(position.timestamp.ToDoubleT())); + coordinates, ConvertTimeToEpochTimeStamp(position.timestamp)); } GeolocationPositionError* CreatePositionError( @@ -307,8 +307,8 @@ return false; if (!options->maximumAge()) return false; - DOMTimeStamp current_time_millis = - ConvertSecondsToDOMTimeStamp(base::Time::Now().ToDoubleT()); + EpochTimeStamp current_time_millis = + ConvertTimeToEpochTimeStamp(base::Time::Now()); return last_position_->timestamp() > current_time_millis - options->maximumAge(); }
diff --git a/third_party/blink/renderer/modules/geolocation/geolocation_position.idl b/third_party/blink/renderer/modules/geolocation/geolocation_position.idl index bc3ba9d4..e6daf9b9 100644 --- a/third_party/blink/renderer/modules/geolocation/geolocation_position.idl +++ b/third_party/blink/renderer/modules/geolocation/geolocation_position.idl
@@ -30,5 +30,5 @@ ImplementedAs=Geoposition ] interface GeolocationPosition { readonly attribute GeolocationCoordinates coords; - readonly attribute DOMTimeStamp timestamp; + readonly attribute EpochTimeStamp timestamp; };
diff --git a/third_party/blink/renderer/modules/geolocation/geoposition.h b/third_party/blink/renderer/modules/geolocation/geoposition.h index 4a2aad5..286e6d6 100644 --- a/third_party/blink/renderer/modules/geolocation/geoposition.h +++ b/third_party/blink/renderer/modules/geolocation/geoposition.h
@@ -26,7 +26,7 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_GEOLOCATION_GEOPOSITION_H_ #define THIRD_PARTY_BLINK_RENDERER_MODULES_GEOLOCATION_GEOPOSITION_H_ -#include "third_party/blink/renderer/core/dom/dom_time_stamp.h" +#include "third_party/blink/renderer/core/timing/epoch_time_stamp.h" #include "third_party/blink/renderer/modules/event_modules.h" #include "third_party/blink/renderer/modules/geolocation/geolocation_coordinates.h" #include "third_party/blink/renderer/platform/bindings/script_wrappable.h" @@ -38,7 +38,7 @@ DEFINE_WRAPPERTYPEINFO(); public: - Geoposition(GeolocationCoordinates* coordinates, DOMTimeStamp timestamp) + Geoposition(GeolocationCoordinates* coordinates, EpochTimeStamp timestamp) : coordinates_(coordinates), timestamp_(timestamp) { DCHECK(coordinates_); } @@ -48,12 +48,12 @@ ScriptWrappable::Trace(visitor); } - DOMTimeStamp timestamp() const { return timestamp_; } + EpochTimeStamp timestamp() const { return timestamp_; } GeolocationCoordinates* coords() const { return coordinates_; } private: Member<GeolocationCoordinates> coordinates_; - DOMTimeStamp timestamp_; + EpochTimeStamp timestamp_; }; } // namespace blink
diff --git a/third_party/blink/renderer/modules/handwriting/handwriting_type_converters_unittest.cc b/third_party/blink/renderer/modules/handwriting/handwriting_type_converters_unittest.cc index b053abf..6c125ad 100644 --- a/third_party/blink/renderer/modules/handwriting/handwriting_type_converters_unittest.cc +++ b/third_party/blink/renderer/modules/handwriting/handwriting_type_converters_unittest.cc
@@ -7,7 +7,7 @@ #include "base/time/time.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/public/mojom/handwriting/handwriting.mojom-blink.h" -#include "third_party/blink/renderer/bindings/core/v8/to_v8_for_core.h" +#include "third_party/blink/renderer/bindings/core/v8/to_v8_traits.h" #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_handwriting_drawing_segment.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_handwriting_feature_query.h"
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_index.cc b/third_party/blink/renderer/modules/indexeddb/idb_index.cc index 59ac7c7..182f321 100644 --- a/third_party/blink/renderer/modules/indexeddb/idb_index.cc +++ b/third_party/blink/renderer/modules/indexeddb/idb_index.cc
@@ -29,7 +29,7 @@ #include <memory> #include <utility> -#include "third_party/blink/renderer/bindings/core/v8/to_v8_for_core.h" +#include "third_party/blink/renderer/bindings/core/v8/to_v8_traits.h" #include "third_party/blink/renderer/bindings/modules/v8/to_v8_for_modules.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_binding_for_modules.h" #include "third_party/blink/renderer/core/execution_context/execution_context.h"
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_key_range.cc b/third_party/blink/renderer/modules/indexeddb/idb_key_range.cc index f9af248..81dc10b 100644 --- a/third_party/blink/renderer/modules/indexeddb/idb_key_range.cc +++ b/third_party/blink/renderer/modules/indexeddb/idb_key_range.cc
@@ -25,7 +25,7 @@ #include "third_party/blink/renderer/modules/indexeddb/idb_key_range.h" -#include "third_party/blink/renderer/bindings/core/v8/to_v8_for_core.h" +#include "third_party/blink/renderer/bindings/core/v8/to_v8_traits.h" #include "third_party/blink/renderer/bindings/modules/v8/to_v8_for_modules.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_binding_for_modules.h" #include "third_party/blink/renderer/core/execution_context/execution_context.h"
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_object_store.cc b/third_party/blink/renderer/modules/indexeddb/idb_object_store.cc index 53b3198..7fc3b6e 100644 --- a/third_party/blink/renderer/modules/indexeddb/idb_object_store.cc +++ b/third_party/blink/renderer/modules/indexeddb/idb_object_store.cc
@@ -37,7 +37,7 @@ #include "third_party/blink/public/mojom/indexeddb/indexeddb.mojom-blink-forward.h" #include "third_party/blink/public/platform/web_blob_info.h" #include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value_factory.h" -#include "third_party/blink/renderer/bindings/core/v8/to_v8_for_core.h" +#include "third_party/blink/renderer/bindings/core/v8/to_v8_traits.h" #include "third_party/blink/renderer/bindings/modules/v8/to_v8_for_modules.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_binding_for_modules.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_union_idbcursor_idbindex_idbobjectstore.h"
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_request.cc b/third_party/blink/renderer/modules/indexeddb/idb_request.cc index e2576cf..df7ea5c 100644 --- a/third_party/blink/renderer/modules/indexeddb/idb_request.cc +++ b/third_party/blink/renderer/modules/indexeddb/idb_request.cc
@@ -33,7 +33,7 @@ #include <utility> #include "third_party/blink/public/platform/web_blob_info.h" -#include "third_party/blink/renderer/bindings/core/v8/to_v8_for_core.h" +#include "third_party/blink/renderer/bindings/core/v8/to_v8_traits.h" #include "third_party/blink/renderer/bindings/modules/v8/to_v8_for_modules.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_binding_for_modules.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_union_idbcursor_idbindex_idbobjectstore.h"
diff --git a/third_party/blink/renderer/modules/mediasession/media_metadata.cc b/third_party/blink/renderer/modules/mediasession/media_metadata.cc index 2c3e465..b0a9f9c88 100644 --- a/third_party/blink/renderer/modules/mediasession/media_metadata.cc +++ b/third_party/blink/renderer/modules/mediasession/media_metadata.cc
@@ -5,7 +5,7 @@ #include "third_party/blink/renderer/modules/mediasession/media_metadata.h" #include "third_party/blink/public/platform/task_type.h" -#include "third_party/blink/renderer/bindings/core/v8/to_v8_for_core.h" +#include "third_party/blink/renderer/bindings/core/v8/to_v8_traits.h" #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_media_metadata_init.h" #include "third_party/blink/renderer/core/execution_context/execution_context.h"
diff --git a/third_party/blink/renderer/modules/mediasource/track_default.cc b/third_party/blink/renderer/modules/mediasource/track_default.cc index 53a2352..63e3de6 100644 --- a/third_party/blink/renderer/modules/mediasource/track_default.cc +++ b/third_party/blink/renderer/modules/mediasource/track_default.cc
@@ -4,7 +4,7 @@ #include "third_party/blink/renderer/modules/mediasource/track_default.h" -#include "third_party/blink/renderer/bindings/core/v8/to_v8_for_core.h" +#include "third_party/blink/renderer/bindings/core/v8/to_v8_traits.h" #include "third_party/blink/renderer/core/html/track/audio_track.h" #include "third_party/blink/renderer/core/html/track/text_track.h" #include "third_party/blink/renderer/core/html/track/video_track.h"
diff --git a/third_party/blink/renderer/modules/payments/payment_event_data_conversion.cc b/third_party/blink/renderer/modules/payments/payment_event_data_conversion.cc index aeacdba..ec005c08 100644 --- a/third_party/blink/renderer/modules/payments/payment_event_data_conversion.cc +++ b/third_party/blink/renderer/modules/payments/payment_event_data_conversion.cc
@@ -5,7 +5,7 @@ #include "third_party/blink/renderer/modules/payments/payment_event_data_conversion.h" #include "third_party/blink/public/mojom/payments/payment_app.mojom-blink.h" -#include "third_party/blink/renderer/bindings/core/v8/to_v8_for_core.h" +#include "third_party/blink/renderer/bindings/core/v8/to_v8_traits.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_payment_currency_amount.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_payment_details_modifier.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_payment_item.h"
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_underlying_sink_test.cc b/third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_underlying_sink_test.cc index ff96c1c8..c049739 100644 --- a/third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_underlying_sink_test.cc +++ b/third_party/blink/renderer/modules/peerconnection/rtc_encoded_audio_underlying_sink_test.cc
@@ -9,7 +9,7 @@ #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h" #include "third_party/blink/renderer/bindings/core/v8/script_promise_tester.h" -#include "third_party/blink/renderer/bindings/core/v8/to_v8_for_core.h" +#include "third_party/blink/renderer/bindings/core/v8/to_v8_traits.h" #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h" #include "third_party/blink/renderer/bindings/core/v8/v8_dom_exception.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_rtc_encoded_audio_frame.h"
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_underlying_sink_test.cc b/third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_underlying_sink_test.cc index 8238bd13..3224dec 100644 --- a/third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_underlying_sink_test.cc +++ b/third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_underlying_sink_test.cc
@@ -9,7 +9,7 @@ #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h" #include "third_party/blink/renderer/bindings/core/v8/script_promise_tester.h" -#include "third_party/blink/renderer/bindings/core/v8/to_v8_for_core.h" +#include "third_party/blink/renderer/bindings/core/v8/to_v8_traits.h" #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h" #include "third_party/blink/renderer/bindings/core/v8/v8_dom_exception.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_rtc_encoded_video_frame.h"
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_test.cc b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_test.cc index 9eb4c6e..370b43b 100644 --- a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_test.cc +++ b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_test.cc
@@ -14,7 +14,7 @@ #include "third_party/blink/public/web/web_heap.h" #include "third_party/blink/public/web/web_script_source.h" #include "third_party/blink/renderer/bindings/core/v8/dictionary.h" -#include "third_party/blink/renderer/bindings/core/v8/to_v8_for_core.h" +#include "third_party/blink/renderer/bindings/core/v8/to_v8_traits.h" #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h" #include "third_party/blink/renderer/bindings/core/v8/v8_void_function.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_rtc_answer_options.h"
diff --git a/third_party/blink/renderer/modules/service_worker/fetch_event.cc b/third_party/blink/renderer/modules/service_worker/fetch_event.cc index 3bab1f7..6df8cc6 100644 --- a/third_party/blink/renderer/modules/service_worker/fetch_event.cc +++ b/third_party/blink/renderer/modules/service_worker/fetch_event.cc
@@ -11,7 +11,7 @@ #include "third_party/blink/public/mojom/timing/worker_timing_container.mojom-blink.h" #include "third_party/blink/public/platform/modules/service_worker/web_service_worker_error.h" #include "third_party/blink/public/platform/web_url_response.h" -#include "third_party/blink/renderer/bindings/core/v8/to_v8_for_core.h" +#include "third_party/blink/renderer/bindings/core/v8/to_v8_traits.h" #include "third_party/blink/renderer/core/dom/abort_signal.h" #include "third_party/blink/renderer/core/execution_context/execution_context.h" #include "third_party/blink/renderer/core/fetch/request.h"
diff --git a/third_party/blink/renderer/modules/service_worker/service_worker_error.cc b/third_party/blink/renderer/modules/service_worker/service_worker_error.cc index 9f1e4c1..5b96b73 100644 --- a/third_party/blink/renderer/modules/service_worker/service_worker_error.cc +++ b/third_party/blink/renderer/modules/service_worker/service_worker_error.cc
@@ -32,7 +32,7 @@ #include "third_party/blink/public/mojom/service_worker/service_worker_error_type.mojom-blink.h" #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h" -#include "third_party/blink/renderer/bindings/core/v8/to_v8_for_core.h" +#include "third_party/blink/renderer/bindings/core/v8/to_v8_traits.h" #include "third_party/blink/renderer/core/dom/dom_exception.h" #include "third_party/blink/renderer/platform/bindings/v8_throw_exception.h" #include "third_party/blink/renderer/platform/heap/heap.h"
diff --git a/third_party/blink/renderer/modules/webaudio/audio_worklet_global_scope_test.cc b/third_party/blink/renderer/modules/webaudio/audio_worklet_global_scope_test.cc index 98c009a..d45ea6fc 100644 --- a/third_party/blink/renderer/modules/webaudio/audio_worklet_global_scope_test.cc +++ b/third_party/blink/renderer/modules/webaudio/audio_worklet_global_scope_test.cc
@@ -16,7 +16,7 @@ #include "third_party/blink/renderer/bindings/core/v8/script_value.h" #include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h" #include "third_party/blink/renderer/bindings/core/v8/source_location.h" -#include "third_party/blink/renderer/bindings/core/v8/to_v8_for_core.h" +#include "third_party/blink/renderer/bindings/core/v8/to_v8_traits.h" #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h" #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h" #include "third_party/blink/renderer/bindings/core/v8/v8_gc_controller.h"
diff --git a/third_party/blink/renderer/modules/webtransport/incoming_stream_test.cc b/third_party/blink/renderer/modules/webtransport/incoming_stream_test.cc index 6b8fadb1..8eaf897 100644 --- a/third_party/blink/renderer/modules/webtransport/incoming_stream_test.cc +++ b/third_party/blink/renderer/modules/webtransport/incoming_stream_test.cc
@@ -12,7 +12,7 @@ #include "third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.h" #include "third_party/blink/renderer/bindings/core/v8/script_promise_tester.h" #include "third_party/blink/renderer/bindings/core/v8/script_value.h" -#include "third_party/blink/renderer/bindings/core/v8/to_v8_for_core.h" +#include "third_party/blink/renderer/bindings/core/v8/to_v8_traits.h" #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h" #include "third_party/blink/renderer/bindings/core/v8/v8_dom_exception.h" #include "third_party/blink/renderer/bindings/core/v8/v8_iterator_result_value.h"
diff --git a/third_party/blink/renderer/modules/webtransport/outgoing_stream_test.cc b/third_party/blink/renderer/modules/webtransport/outgoing_stream_test.cc index 9c4bd35..14ae13a 100644 --- a/third_party/blink/renderer/modules/webtransport/outgoing_stream_test.cc +++ b/third_party/blink/renderer/modules/webtransport/outgoing_stream_test.cc
@@ -11,7 +11,7 @@ #include "third_party/blink/public/platform/task_type.h" #include "third_party/blink/renderer/bindings/core/v8/script_promise_tester.h" #include "third_party/blink/renderer/bindings/core/v8/script_value.h" -#include "third_party/blink/renderer/bindings/core/v8/to_v8_for_core.h" +#include "third_party/blink/renderer/bindings/core/v8/to_v8_traits.h" #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h" #include "third_party/blink/renderer/bindings/core/v8/v8_dom_exception.h" #include "third_party/blink/renderer/core/dom/dom_exception.h"
diff --git a/third_party/blink/renderer/modules/webtransport/web_transport_test.cc b/third_party/blink/renderer/modules/webtransport/web_transport_test.cc index ea770ce..43337a2 100644 --- a/third_party/blink/renderer/modules/webtransport/web_transport_test.cc +++ b/third_party/blink/renderer/modules/webtransport/web_transport_test.cc
@@ -21,7 +21,7 @@ #include "third_party/blink/renderer/bindings/core/v8/native_value_traits_impl.h" #include "third_party/blink/renderer/bindings/core/v8/script_promise_tester.h" #include "third_party/blink/renderer/bindings/core/v8/script_value.h" -#include "third_party/blink/renderer/bindings/core/v8/to_v8_for_core.h" +#include "third_party/blink/renderer/bindings/core/v8/to_v8_traits.h" #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h" #include "third_party/blink/renderer/bindings/core/v8/v8_dom_exception.h" #include "third_party/blink/renderer/bindings/core/v8/v8_gc_controller.h"
diff --git a/third_party/blink/renderer/modules/webusb/usb_device.cc b/third_party/blink/renderer/modules/webusb/usb_device.cc index 7c9fa09..4532b21 100644 --- a/third_party/blink/renderer/modules/webusb/usb_device.cc +++ b/third_party/blink/renderer/modules/webusb/usb_device.cc
@@ -10,7 +10,7 @@ #include "third_party/blink/public/platform/platform.h" #include "third_party/blink/renderer/bindings/core/v8/script_promise.h" #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h" -#include "third_party/blink/renderer/bindings/core/v8/to_v8_for_core.h" +#include "third_party/blink/renderer/bindings/core/v8/to_v8_traits.h" #include "third_party/blink/renderer/bindings/core/v8/v8_union_arraybuffer_arraybufferview.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_usb_control_transfer_parameters.h" #include "third_party/blink/renderer/core/dom/dom_exception.h"
diff --git a/third_party/blink/renderer/platform/fonts/font_cache.cc b/third_party/blink/renderer/platform/fonts/font_cache.cc index e625b63..155cb28 100644 --- a/third_party/blink/renderer/platform/fonts/font_cache.cc +++ b/third_party/blink/renderer/platform/fonts/font_cache.cc
@@ -388,12 +388,6 @@ void FontCache::PurgeFallbackListShaperCache() { TRACE_EVENT0("fonts,ui", "FontCache::PurgeFallbackListShaperCache"); - unsigned items = 0; - FallbackListShaperCache::iterator iter; - for (iter = fallback_list_shaper_cache_.begin(); - iter != fallback_list_shaper_cache_.end(); ++iter) { - items += iter->value->size(); - } fallback_list_shaper_cache_.clear(); }
diff --git a/third_party/blink/renderer/platform/loader/child_url_loader_factory_bundle.cc b/third_party/blink/renderer/platform/loader/child_url_loader_factory_bundle.cc index f7e9689..8be819e 100644 --- a/third_party/blink/renderer/platform/loader/child_url_loader_factory_bundle.cc +++ b/third_party/blink/renderer/platform/loader/child_url_loader_factory_bundle.cc
@@ -137,15 +137,11 @@ std::move(base_factories->pending_scheme_specific_factories()), std::move(base_factories->pending_isolated_world_factories()), base_factories->bypass_redirect_checks()) { - pending_appcache_factory_ = - std::move(base_factories->pending_appcache_factory()); } ChildPendingURLLoaderFactoryBundle::ChildPendingURLLoaderFactoryBundle( mojo::PendingRemote<network::mojom::URLLoaderFactory> pending_default_factory, - mojo::PendingRemote<network::mojom::URLLoaderFactory> - pending_appcache_factory, SchemeMap pending_scheme_specific_factories, OriginMap pending_isolated_world_factories, mojo::PendingRemote<network::mojom::URLLoaderFactory> @@ -157,9 +153,7 @@ std::move(pending_isolated_world_factories), bypass_redirect_checks), pending_prefetch_loader_factory_( - std::move(pending_prefetch_loader_factory)) { - pending_appcache_factory_ = std::move(pending_appcache_factory); -} + std::move(pending_prefetch_loader_factory)) {} ChildPendingURLLoaderFactoryBundle::~ChildPendingURLLoaderFactoryBundle() = default; @@ -168,7 +162,6 @@ ChildPendingURLLoaderFactoryBundle::CreateFactory() { auto other = std::make_unique<ChildPendingURLLoaderFactoryBundle>(); other->pending_default_factory_ = std::move(pending_default_factory_); - other->pending_appcache_factory_ = std::move(pending_appcache_factory_); other->pending_scheme_specific_factories_ = std::move(pending_scheme_specific_factories_); other->pending_isolated_world_factories_ = @@ -238,12 +231,47 @@ std::unique_ptr<network::PendingSharedURLLoaderFactory> ChildURLLoaderFactoryBundle::Clone() { - return CloneInternal(true /* include_appcache */); + mojo::PendingRemote<network::mojom::URLLoaderFactory> + default_factory_pending_remote; + if (default_factory_) { + default_factory_->Clone( + default_factory_pending_remote.InitWithNewPipeAndPassReceiver()); + } + + mojo::PendingRemote<network::mojom::URLLoaderFactory> + pending_prefetch_loader_factory; + if (prefetch_loader_factory_) { + prefetch_loader_factory_->Clone( + pending_prefetch_loader_factory.InitWithNewPipeAndPassReceiver()); + } + + // Currently there is no need to override subresources from workers, + // therefore |subresource_overrides| are not shared with the clones. + + return std::make_unique<ChildPendingURLLoaderFactoryBundle>( + std::move(default_factory_pending_remote), + CloneRemoteMapToPendingRemoteMap(scheme_specific_factories_), + CloneRemoteMapToPendingRemoteMap(isolated_world_factories_), + std::move(pending_prefetch_loader_factory), bypass_redirect_checks_); } -std::unique_ptr<network::PendingSharedURLLoaderFactory> -ChildURLLoaderFactoryBundle::CloneWithoutAppCacheFactory() { - return CloneInternal(false /* include_appcache */); +std::unique_ptr<ChildPendingURLLoaderFactoryBundle> +ChildURLLoaderFactoryBundle::PassInterface() { + mojo::PendingRemote<network::mojom::URLLoaderFactory> pending_default_factory; + if (default_factory_) + pending_default_factory = default_factory_.Unbind(); + + mojo::PendingRemote<network::mojom::URLLoaderFactory> + pending_prefetch_loader_factory; + if (prefetch_loader_factory_) { + pending_prefetch_loader_factory = prefetch_loader_factory_.Unbind(); + } + + return std::make_unique<ChildPendingURLLoaderFactoryBundle>( + std::move(pending_default_factory), + BoundRemoteMapToPendingRemoteMap(std::move(scheme_specific_factories_)), + BoundRemoteMapToPendingRemoteMap(std::move(isolated_world_factories_)), + std::move(pending_prefetch_loader_factory), bypass_redirect_checks_); } void ChildURLLoaderFactoryBundle::Update( @@ -272,62 +300,4 @@ return false; } -std::unique_ptr<network::PendingSharedURLLoaderFactory> -ChildURLLoaderFactoryBundle::CloneInternal(bool include_appcache) { - mojo::PendingRemote<network::mojom::URLLoaderFactory> - default_factory_pending_remote; - if (default_factory_) { - default_factory_->Clone( - default_factory_pending_remote.InitWithNewPipeAndPassReceiver()); - } - - mojo::PendingRemote<network::mojom::URLLoaderFactory> - appcache_factory_pending_remote; - if (appcache_factory_ && include_appcache) { - appcache_factory_->Clone( - appcache_factory_pending_remote.InitWithNewPipeAndPassReceiver()); - } - - mojo::PendingRemote<network::mojom::URLLoaderFactory> - pending_prefetch_loader_factory; - if (prefetch_loader_factory_) { - prefetch_loader_factory_->Clone( - pending_prefetch_loader_factory.InitWithNewPipeAndPassReceiver()); - } - - // Currently there is no need to override subresources from workers, - // therefore |subresource_overrides| are not shared with the clones. - - return std::make_unique<ChildPendingURLLoaderFactoryBundle>( - std::move(default_factory_pending_remote), - std::move(appcache_factory_pending_remote), - CloneRemoteMapToPendingRemoteMap(scheme_specific_factories_), - CloneRemoteMapToPendingRemoteMap(isolated_world_factories_), - std::move(pending_prefetch_loader_factory), bypass_redirect_checks_); -} - -std::unique_ptr<ChildPendingURLLoaderFactoryBundle> -ChildURLLoaderFactoryBundle::PassInterface() { - mojo::PendingRemote<network::mojom::URLLoaderFactory> pending_default_factory; - if (default_factory_) - pending_default_factory = default_factory_.Unbind(); - - mojo::PendingRemote<network::mojom::URLLoaderFactory> - pending_appcache_factory; - if (appcache_factory_) - pending_appcache_factory = appcache_factory_.Unbind(); - - mojo::PendingRemote<network::mojom::URLLoaderFactory> - pending_prefetch_loader_factory; - if (prefetch_loader_factory_) { - pending_prefetch_loader_factory = prefetch_loader_factory_.Unbind(); - } - - return std::make_unique<ChildPendingURLLoaderFactoryBundle>( - std::move(pending_default_factory), std::move(pending_appcache_factory), - BoundRemoteMapToPendingRemoteMap(std::move(scheme_specific_factories_)), - BoundRemoteMapToPendingRemoteMap(std::move(isolated_world_factories_)), - std::move(pending_prefetch_loader_factory), bypass_redirect_checks_); -} - } // namespace blink
diff --git a/third_party/blink/renderer/platform/loader/fetch/url_loader/dedicated_or_shared_worker_fetch_context_impl.cc b/third_party/blink/renderer/platform/loader/fetch/url_loader/dedicated_or_shared_worker_fetch_context_impl.cc index 1ee99ed..aacdcd1 100644 --- a/third_party/blink/renderer/platform/loader/fetch/url_loader/dedicated_or_shared_worker_fetch_context_impl.cc +++ b/third_party/blink/renderer/platform/loader/fetch/url_loader/dedicated_or_shared_worker_fetch_context_impl.cc
@@ -641,7 +641,7 @@ loader_factory_ = network::SharedURLLoaderFactory::Create( subresource_loader_factory_bundle->Clone()); fallback_factory_ = network::SharedURLLoaderFactory::Create( - subresource_loader_factory_bundle->CloneWithoutAppCacheFactory()); + subresource_loader_factory_bundle->Clone()); web_loader_factory_ = std::make_unique<Factory>( loader_factory_, cors_exempt_header_list_, terminate_sync_load_event_); ResetServiceWorkerURLLoaderFactory();
diff --git a/third_party/blink/renderer/platform/loader/tracked_child_url_loader_factory_bundle.cc b/third_party/blink/renderer/platform/loader/tracked_child_url_loader_factory_bundle.cc index 6f0425d..8c206d4 100644 --- a/third_party/blink/renderer/platform/loader/tracked_child_url_loader_factory_bundle.cc +++ b/third_party/blink/renderer/platform/loader/tracked_child_url_loader_factory_bundle.cc
@@ -19,8 +19,6 @@ TrackedChildPendingURLLoaderFactoryBundle( mojo::PendingRemote<network::mojom::URLLoaderFactory> pending_default_factory, - mojo::PendingRemote<network::mojom::URLLoaderFactory> - pending_appcache_factory, SchemeMap pending_scheme_specific_factories, OriginMap pending_isolated_world_factories, mojo::PendingRemote<network::mojom::URLLoaderFactory> @@ -29,7 +27,6 @@ bool bypass_redirect_checks) : ChildPendingURLLoaderFactoryBundle( std::move(pending_default_factory), - std::move(pending_appcache_factory), std::move(pending_scheme_specific_factories), std::move(pending_isolated_world_factories), std::move(pending_prefetch_loader_factory), @@ -48,7 +45,6 @@ TrackedChildPendingURLLoaderFactoryBundle::CreateFactory() { auto other = std::make_unique<TrackedChildPendingURLLoaderFactoryBundle>(); other->pending_default_factory_ = std::move(pending_default_factory_); - other->pending_appcache_factory_ = std::move(pending_appcache_factory_); other->pending_scheme_specific_factories_ = std::move(pending_scheme_specific_factories_); other->pending_isolated_world_factories_ = @@ -91,7 +87,6 @@ return std::make_unique<TrackedChildPendingURLLoaderFactoryBundle>( std::move(pending_factories->pending_default_factory()), - std::move(pending_factories->pending_appcache_factory()), std::move(pending_factories->pending_scheme_specific_factories()), std::move(pending_factories->pending_isolated_world_factories()), std::move(pending_factories->pending_prefetch_loader_factory()), @@ -156,29 +151,6 @@ return std::make_unique<TrackedChildPendingURLLoaderFactoryBundle>( std::move(pending_factories->pending_default_factory()), - std::move(pending_factories->pending_appcache_factory()), - std::move(pending_factories->pending_scheme_specific_factories()), - std::move(pending_factories->pending_isolated_world_factories()), - std::move(pending_factories->pending_prefetch_loader_factory()), - std::move(main_thread_host_bundle_clone), - pending_factories->bypass_redirect_checks()); -} - -std::unique_ptr<network::PendingSharedURLLoaderFactory> -HostChildURLLoaderFactoryBundle::CloneWithoutAppCacheFactory() { - auto pending_factories = - base::WrapUnique(static_cast<ChildPendingURLLoaderFactoryBundle*>( - ChildURLLoaderFactoryBundle::CloneWithoutAppCacheFactory() - .release())); - - DCHECK(base::SequencedTaskRunnerHandle::IsSet()); - auto main_thread_host_bundle_clone = std::make_unique< - TrackedChildURLLoaderFactoryBundle::HostPtrAndTaskRunner>(AsWeakPtr(), - task_runner_); - - return std::make_unique<TrackedChildPendingURLLoaderFactoryBundle>( - std::move(pending_factories->pending_default_factory()), - std::move(pending_factories->pending_appcache_factory()), std::move(pending_factories->pending_scheme_specific_factories()), std::move(pending_factories->pending_isolated_world_factories()), std::move(pending_factories->pending_prefetch_loader_factory()),
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 index 71fb2b2..227ebe54 100644 --- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 +++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -1207,7 +1207,7 @@ }, { name: "InteractionId", - status: "experimental", + status: "stable", }, { name: "InterestCohortAPI", @@ -2413,7 +2413,7 @@ name: "WebAuth", status: "stable", }, - // When enabled adds the authenticator attachment used for registration and + // When enabled adds the authenticator attachment used for registration and // authentication to the public key credential response. { name: "WebAuthAuthenticatorAttachment",
diff --git a/third_party/blink/tools/blinkpy/common/system/filesystem_mock.py b/third_party/blink/tools/blinkpy/common/system/filesystem_mock.py index 5ba35e8..bae4308 100644 --- a/third_party/blink/tools/blinkpy/common/system/filesystem_mock.py +++ b/third_party/blink/tools/blinkpy/common/system/filesystem_mock.py
@@ -533,7 +533,8 @@ class ReadableTextFileObject(ReadableBinaryFileObject): def __init__(self, fs, path, data): - super(ReadableTextFileObject, self).__init__(fs, path, StringIO(data)) + super(ReadableTextFileObject, + self).__init__(fs, path, StringIO(data.decode(encoding='utf-8'))) def close(self): self.data.close()
diff --git a/third_party/blink/tools/blinkpy/w3c/wpt_github.py b/third_party/blink/tools/blinkpy/w3c/wpt_github.py index e11747c..a9adf91 100644 --- a/third_party/blink/tools/blinkpy/w3c/wpt_github.py +++ b/third_party/blink/tools/blinkpy/w3c/wpt_github.py
@@ -7,9 +7,11 @@ import json import logging import re +import six from collections import namedtuple from six.moves.urllib.error import HTTPError +from six.moves.urllib.error import URLError from six.moves.urllib.parse import quote from blinkpy.common.memoized import memoized @@ -48,7 +50,8 @@ def auth_token(self): assert self.has_credentials() - return base64.b64encode('{}:{}'.format(self.user, self.token)) + data = '{}:{}'.format(self.user, self.token).encode('utf-8') + return base64.b64encode(data).decode('utf-8') def request(self, path, method, body=None, accept_header=None): """Sends a request to GitHub API and deserializes the response. @@ -368,18 +371,27 @@ """ path = '/repos/%s/%s/pulls/%d/merge' % (WPT_GH_ORG, WPT_GH_REPO_NAME, pr_number) - try: - response = self.request(path, method='GET') - if response.status_code == 204: - return True - else: - raise GitHubError(204, response.status_code, - 'check if PR %d is merged' % pr_number) - except HTTPError as e: - if e.code == 404: - return False - else: - raise + cached_error = None + for i in range(5): + try: + response = self.request(path, method='GET') + if response.status_code == 204: + return True + else: + raise GitHubError(204, response.status_code, + 'check if PR %d is merged' % pr_number) + except HTTPError as e: + if e.code == 404: + return False + else: + raise + except URLError as e: + # After migrate to py3 we met random timeout issue here, + # Retry this request in this case + _log.warning("Meet URLError...") + cached_error = e + else: + raise cached_error def merge_pr(self, pr_number): """Merges a PR. @@ -470,7 +482,10 @@ """Gets the value of the header with the given name. Delegates to HTTPMessage.getheader(), which is case-insensitive.""" - return self._raw_response.info().getheader(header) + if six.PY3: + return self._raw_response.getheader(header) + else: + return self._raw_response.info().getheader(header) class GitHubError(Exception):
diff --git a/third_party/blink/web_tests/FlagExpectations/composite-after-paint b/third_party/blink/web_tests/FlagExpectations/composite-after-paint index f9df09c..0584a88 100644 --- a/third_party/blink/web_tests/FlagExpectations/composite-after-paint +++ b/third_party/blink/web_tests/FlagExpectations/composite-after-paint
@@ -36,6 +36,7 @@ crbug.com/1183814 external/wpt/svg/extensibility/foreignObject/scroll-transform-nested-stacked-children.html [ Pass ] crbug.com/1167352 external/wpt/css/css-will-change/will-change-transform-add-content.html [ Pass ] crbug.com/1062984 external/wpt/paint-timing/fcp-only/fcp-out-of-bounds-translate.html [ Pass ] +virtual/layout_ng_block_frag/external/wpt/css/css-break/out-of-flow-in-multicolumn-075.html [ Pass ] # Outline paints incorrectly with columns. Needs LayoutNGBlockFragmentation. crbug.com/1047358 paint/pagination/composited-paginated-outlined-box.html [ Failure ]
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index 5d9dc095..0a07e2c 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -360,6 +360,7 @@ crbug.com/624233 virtual/gpu-rasterization/images/color-profile-background-clip-text.html [ Failure Pass ] crbug.com/757605 virtual/gpu-rasterization/images/jpeg-yuv-progressive-image.html [ Failure Pass ] crbug.com/1223284 [ Win7 ] virtual/gpu-rasterization/images/color-profile-background-image-cross-fade.html [ Failure Pass ] +crbug.com/1223284 [ Mac11-arm64 ] virtual/gpu-rasterization/images/color-profile-background-image-cross-fade.html [ Failure Pass ] ########## Bugs to fix ########## # This is a missing event and increasing the timeout or using run-after-layout-and-paint doesn't @@ -2914,6 +2915,13 @@ crbug.com/626703 external/wpt/service-workers/service-worker/worker-interception.https.html [ Failure ] crbug.com/626703 virtual/plz-dedicated-worker/external/wpt/service-workers/service-worker/worker-interception.https.html [ Pass ] +# ====== Test expectations added to unblock wpt-importer ====== +crbug.com/626703 external/wpt/service-workers/service-worker/navigation-timing-extended.https.html [ Failure ] +crbug.com/626703 fast/animation/scroll-animations/scroll-animation-lifetime.html [ Failure ] +crbug.com/626703 fast/animation/scroll-animations/scroll-timeline-snapshotting.html [ Failure ] +crbug.com/626703 fast/animation/scroll-animations/scrolltimeline-root-scroller-quirks-mode.html [ Failure ] +crbug.com/626703 virtual/plz-dedicated-worker/external/wpt/service-workers/service-worker/navigation-timing-extended.https.html [ Failure ] + # ====== New tests from wpt-importer added here ====== crbug.com/626703 [ Linux ] external/wpt/webauthn/createcredential-attachment.https.html [ Crash ] crbug.com/626703 [ Mac11.0 ] external/wpt/webauthn/createcredential-attachment.https.html [ Crash ] @@ -3214,10 +3222,12 @@ crbug.com/626703 [ Mac11-arm64 ] external/wpt/webrtc/RTCSctpTransport-events.html [ Timeout ] crbug.com/626703 [ Mac10.14 ] virtual/webrtc-wpt-plan-b/external/wpt/webrtc/getstats.html [ Timeout ] crbug.com/626703 [ Mac11.0 ] virtual/webrtc-wpt-plan-b/external/wpt/webrtc/getstats.html [ Timeout ] +crbug.com/626703 [ Mac11-arm64 ] virtual/webrtc-wpt-plan-b/external/wpt/webrtc/getstats.html [ Timeout ] crbug.com/626703 [ Mac10.14 ] external/wpt/webrtc/RTCDataChannel-send.html [ Skip Timeout ] crbug.com/626703 [ Mac11.0 ] external/wpt/webrtc/RTCDataChannel-send.html [ Skip Timeout ] crbug.com/626703 [ Mac10.14 ] external/wpt/webrtc/RTCDataChannel-iceRestart.html [ Skip Timeout ] crbug.com/626703 [ Mac11.0 ] external/wpt/webrtc/RTCDataChannel-iceRestart.html [ Skip Timeout ] +crbug.com/626703 [ Mac11-arm64 ] external/wpt/webrtc/RTCDataChannel-iceRestart.html [ Skip Timeout ] crbug.com/626703 [ Mac10.14 ] external/wpt/webrtc/RTCPeerConnection-createDataChannel.html [ Skip Timeout ] crbug.com/626703 [ Mac11.0 ] external/wpt/webrtc/RTCPeerConnection-createDataChannel.html [ Skip Timeout ] crbug.com/626703 [ Mac10.14 ] external/wpt/webrtc-encoded-transform/RTCPeerConnection-insertable-streams-legacy.https.html [ Timeout ] @@ -3278,6 +3288,7 @@ crbug.com/626703 [ Mac11.0 ] external/wpt/webrtc/RTCPeerConnection-connectionState.https.html [ Timeout ] crbug.com/626703 [ Mac11.0 ] external/wpt/webrtc/RTCDataChannel-close.html [ Skip Timeout ] crbug.com/626703 [ Mac11.0 ] external/wpt/webrtc-encoded-transform/RTCPeerConnection-insertable-streams-worker.https.html [ Timeout ] +crbug.com/626703 [ Mac11-arm64 ] external/wpt/webrtc-encoded-transform/RTCPeerConnection-insertable-streams-worker.https.html [ Timeout ] crbug.com/626703 [ Mac11.0 ] virtual/webrtc-wpt-plan-b/external/wpt/webrtc/RTCPeerConnection-connectionState.https.html [ Timeout ] crbug.com/626703 [ Mac11.0 ] external/wpt/webrtc/simulcast/vp8.https.html [ Skip Timeout ] crbug.com/626703 [ Mac11.0 ] external/wpt/webrtc/protocol/handover-datachannel.html [ Timeout ] @@ -3305,6 +3316,7 @@ crbug.com/626703 [ Mac11.0 ] external/wpt/webrtc/promises-call.html [ Timeout ] crbug.com/626703 [ Mac11.0 ] virtual/webrtc-wpt-plan-b/external/wpt/webrtc/RTCPeerConnection-createDataChannel.html [ Skip Timeout ] crbug.com/626703 [ Mac11.0 ] external/wpt/webrtc/RTCPeerConnection-addIceCandidate-connectionSetup.html [ Skip Timeout ] +crbug.com/626703 [ Mac11-arm64 ] external/wpt/webrtc/RTCPeerConnection-addIceCandidate-connectionSetup.html [ Skip Timeout ] crbug.com/626703 [ Mac11.0 ] virtual/webrtc-wpt-plan-b/external/wpt/webrtc/RTCPeerConnection-getStats.https.html [ Skip Timeout ] crbug.com/626703 [ Mac11-arm64 ] virtual/webrtc-wpt-plan-b/external/wpt/webrtc/RTCPeerConnection-getStats.https.html [ Skip Timeout ] crbug.com/626703 [ Mac11.0 ] external/wpt/video-rvfc/request-video-frame-callback-webrtc.https.html [ Timeout ] @@ -3919,6 +3931,7 @@ crbug.com/829028 external/wpt/css/css-break/out-of-flow-in-multicolumn-066.html [ Failure ] crbug.com/829028 external/wpt/css/css-break/out-of-flow-in-multicolumn-071.html [ Failure ] crbug.com/829028 external/wpt/css/css-break/out-of-flow-in-multicolumn-073.html [ Failure ] +crbug.com/829028 external/wpt/css/css-break/out-of-flow-in-multicolumn-075.html [ Failure ] crbug.com/829028 external/wpt/css/css-break/overflow-clip-000.html [ Failure ] crbug.com/829028 external/wpt/css/css-break/overflow-clip-001.html [ Failure ] crbug.com/829028 external/wpt/css/css-break/overflow-clip-010.html [ Failure ] @@ -6545,8 +6558,10 @@ # Sheriff 2021-06-02 crbug.com/1215575 [ Mac11.0 ] fast/peerconnection/RTCPeerConnection-applyConstraints-remoteVideoTrack.html [ Pass Timeout ] +crbug.com/1215575 [ Mac11-arm64 ] fast/peerconnection/RTCPeerConnection-applyConstraints-remoteVideoTrack.html [ Pass Timeout ] crbug.com/1215575 [ Mac11.0 ] fast/peerconnection/RTCPeerConnection-createDTMFSender.html [ Failure Pass ] crbug.com/1215575 [ Mac11.0 ] fast/peerconnection/RTCPeerConnection-datachannel.html [ Pass Timeout ] +crbug.com/1215575 [ Mac11-arm64 ] fast/peerconnection/RTCPeerConnection-datachannel.html [ Pass Timeout ] crbug.com/1215575 [ Mac11.0 ] fast/peerconnection/RTCPeerConnection-lifetime.html [ Pass Timeout ] crbug.com/1215575 [ Mac11-arm64 ] fast/peerconnection/RTCPeerConnection-lifetime.html [ Pass Timeout ] crbug.com/1215584 [ Mac11.0 ] inspector-protocol/layout-fonts/lang-fallback.js [ Failure Pass ] @@ -6943,6 +6958,7 @@ crbug.com/1249176 [ Mac11-arm64 ] fast/forms/color/color-picker-escape-cancellation-revert.html [ Failure ] crbug.com/1249176 [ Mac11-arm64 ] fast/css/focus-display-block-inline.html [ Failure ] crbug.com/1249176 [ Mac11-arm64 ] fast/dom/geometry-interfaces-dom-matrix-rotate.html [ Failure ] +crbug.com/1249176 [ Mac11-arm64 ] http/tests/devtools/tracing/timeline-paint/timeline-paint-image.js [ Failure ] # Following tests timeout on mac11-arm64 crbug.com/1249176 [ Mac11-arm64 ] external/wpt/focus/focus-already-focused-iframe-deep-same-site.html [ Timeout ] @@ -7035,6 +7051,9 @@ crbug.com/1249176 [ Mac11-arm64 ] external/wpt/css/css-shapes/shape-outside/shape-image/shape-image-003.html [ Failure Pass ] crbug.com/1249176 [ Mac11-arm64 ] external/wpt/css/css-shapes/shape-outside/shape-image/shape-image-014.html [ Failure Pass ] crbug.com/1249176 [ Mac11-arm64 ] virtual/gpu-rasterization/images/color-profile-image-filter-all.html [ Failure Pass ] +crbug.com/1249176 [ Mac11-arm64 ] virtual/scalefactor200withoutzoom/external/wpt/largest-contentful-paint/multiple-redirects-TAO.html [ Failure Pass ] +crbug.com/1249176 [ Mac11-arm64 ] virtual/webrtc-wpt-plan-b/external/wpt/webrtc/protocol/split.https.html [ Timeout Pass ] + # mac-arm CI 10-01-2021 crbug.com/1249176 [ Mac11-arm64 ] editing/text-iterator/beforematch-async.html [ Failure ] crbug.com/1249176 [ Mac11-arm64 ] external/wpt/event-timing/click-interactionid.html [ Timeout ] @@ -7201,3 +7220,5 @@ crbug.com/1259133 [ Mac10.14 ] external/wpt/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.commit.html [ Failure Pass ] crbug.com/1259133 [ Mac10.14 ] virtual/no-alloc-direct-call/external/wpt/html/canvas/offscreen/manual/the-offscreen-canvas/offscreencanvas.commit.html [ Failure Pass ] crbug.com/1259167 [ Mac ] virtual/threaded/external/wpt/scroll-animations/scroll-animation-inactive-timeline.html [ Failure Pass ] +crbug.com/1259188 [ Mac10.14 ] virtual/gpu-rasterization/images/color-profile-animate.html [ Failure Pass ] +crbug.com/1259255 [ Win7 ] virtual/scroll-unification/fast/events/mouse-cursor-no-mousemove.html [ Failure Pass ]
diff --git a/third_party/blink/web_tests/VirtualTestSuites b/third_party/blink/web_tests/VirtualTestSuites index 1ebd08a7..b6dea7d 100644 --- a/third_party/blink/web_tests/VirtualTestSuites +++ b/third_party/blink/web_tests/VirtualTestSuites
@@ -121,8 +121,7 @@ }, { "prefix": "stable", - "bases": ["external/wpt/css/css-cascade/presentational-hints-cascade.html", - "fast/css3-text/css3-text-decoration/stable", + "bases": ["fast/css3-text/css3-text-decoration/stable", "fast/dom/Window", "http/tests/navigation", "http/tests/sendbeacon", @@ -1119,5 +1118,10 @@ "prefix": "fenced-frame-mparch", "bases": ["fenced_frame", "wpt_internal/fenced_frame"], "args": ["--enable-features=FencedFrames:implementation_type/mparch"] + }, + { + "prefix": "disable-custom-element-default-style", + "bases": ["external/wpt/css/css-cascade/presentational-hints-cascade.html"], + "args": ["--disable-blink-features=CustomElementDefaultStyle"] } ]
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json index 415182c..31e27a5 100644 --- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json +++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
@@ -2414,13 +2414,15 @@ ] }, "scroll-animations": { - "null-scroll-source-crash.html": [ - "53ad0d92850992ca00b157f83b7d45c867c3f475", - [ - null, - {} + "scroll-timelines": { + "null-scroll-source-crash.html": [ + "53ad0d92850992ca00b157f83b7d45c867c3f475", + [ + null, + {} + ] ] - ] + } }, "selection": { "selection-select-all-move-input-crash.html": [ @@ -113619,8 +113621,21 @@ {} ] ], - "grid-placement-items-spanning-multiple-rows.html": [ - "f03c5f1d9e879b8d2ece5a3c18a1e964909024a9", + "grid-placement-items-spanning-multiple-rows-001.html": [ + "de6398e324b93d58f54b449118feb8b0c69250af", + [ + null, + [ + [ + "/css/reference/ref-filled-green-100px-square.xht", + "==" + ] + ], + {} + ] + ], + "grid-placement-items-spanning-multiple-rows-002.html": [ + "f055340a3a3c014626700986aadcf1042b2b3fec", [ null, [ @@ -118936,6 +118951,21 @@ ] ] }, + "css-inline": { + "empty-text-node-001.html": [ + "eddf31ec59ccc206975b9947d1b4bf75e88063ed", + [ + null, + [ + [ + "/css/css-inline/empty-text-node-001-ref.html", + "==" + ] + ], + {} + ] + ] + }, "css-layout-api": { "auto-block-size": { "absolute.https.html": [ @@ -202873,6 +202903,19 @@ ] ] }, + "input-checkbox-disabled-checked.html": [ + "f72fdf62fdcc148a0799b06bde02ccaf4186c8fb", + [ + null, + [ + [ + "/html/rendering/widgets/input-checkbox-disabled-checked-notref.html", + "!=" + ] + ], + {} + ] + ], "input-date-baseline.html": [ "0d8f46c06421d22d9d680a83785460bfa865dc81", [ @@ -202899,6 +202942,19 @@ {} ] ], + "input-radio-disabled-checked.html": [ + "3ac2a37199b653ab4e1dd5d098bce9bb9e83dc44", + [ + null, + [ + [ + "/html/rendering/widgets/input-radio-disabled-checked-notref.html", + "!=" + ] + ], + {} + ] + ], "input-time-content-size.html": [ "4a378f6923a8910b96f8afa84125a8fbac4a5d05", [ @@ -208236,136 +208292,138 @@ ] }, "scroll-animations": { - "animation-with-animatable-interface.html": [ - "7d9b11fbefdc0f65d5037b82afa4e2d819a133b2", - [ - null, + "scroll-timelines": { + "animation-with-animatable-interface.html": [ + "7d9b11fbefdc0f65d5037b82afa4e2d819a133b2", [ + null, [ - "/scroll-animations/animation-ref.html", - "==" - ] - ], - {} - ] - ], - "animation-with-display-none.html": [ - "85cebad50be37a6b856e72d424b84b0d6d57cc9d", - [ - null, + [ + "/scroll-animations/scroll-timelines/animation-ref.html", + "==" + ] + ], + {} + ] + ], + "animation-with-display-none.html": [ + "85cebad50be37a6b856e72d424b84b0d6d57cc9d", [ + null, [ - "/scroll-animations/animation-ref.html", - "==" - ] - ], - {} - ] - ], - "animation-with-overflow-hidden.html": [ - "5a0bbfb53a4e2fcd2e2934af379eb99271c4c7dd", - [ - null, + [ + "/scroll-animations/scroll-timelines/animation-ref.html", + "==" + ] + ], + {} + ] + ], + "animation-with-overflow-hidden.html": [ + "5a0bbfb53a4e2fcd2e2934af379eb99271c4c7dd", [ + null, [ - "/scroll-animations/animation-with-overflow-hidden-ref.html", - "==" - ] - ], - {} - ] - ], - "animation-with-root-scroller.html": [ - "21225146fb44001aec892c10029c83b05a8bd25d", - [ - null, + [ + "/scroll-animations/scroll-timelines/animation-with-overflow-hidden-ref.html", + "==" + ] + ], + {} + ] + ], + "animation-with-root-scroller.html": [ + "21225146fb44001aec892c10029c83b05a8bd25d", [ + null, [ - "/scroll-animations/animation-with-root-scroller-ref.html", - "==" - ] - ], - {} - ] - ], - "animation-with-transform.html": [ - "e6472cac1261965d4cbdc87852fb4cb40a6ade29", - [ - null, + [ + "/scroll-animations/scroll-timelines/animation-with-root-scroller-ref.html", + "==" + ] + ], + {} + ] + ], + "animation-with-transform.html": [ + "e6472cac1261965d4cbdc87852fb4cb40a6ade29", [ + null, [ - "/scroll-animations/animation-ref.html", - "==" - ] - ], - {} - ] - ], - "layout-changes-on-percentage-based-timeline.html": [ - "f97358144b0c199e7c08252cb96162ca3502f7a9", - [ - null, + [ + "/scroll-animations/scroll-timelines/animation-ref.html", + "==" + ] + ], + {} + ] + ], + "layout-changes-on-percentage-based-timeline.html": [ + "f97358144b0c199e7c08252cb96162ca3502f7a9", [ + null, [ - "/scroll-animations/animation-ref.html", - "==" - ] - ], - {} - ] - ], - "progress-based-effect-delay.tentative.html": [ - "f92a3c6c99a74770016c23961c2c267c3fd4a209", - [ - null, + [ + "/scroll-animations/scroll-timelines/animation-ref.html", + "==" + ] + ], + {} + ] + ], + "progress-based-effect-delay.tentative.html": [ + "f92a3c6c99a74770016c23961c2c267c3fd4a209", [ + null, [ - "/scroll-animations/progress-based-effect-delay-ref.html", - "==" - ] - ], - {} - ] - ], - "set-current-time-before-play.html": [ - "0d7e08d3320c8c29904a798546138ca8db9f2398", - [ - null, + [ + "/scroll-animations/scroll-timelines/progress-based-effect-delay-ref.html", + "==" + ] + ], + {} + ] + ], + "set-current-time-before-play.html": [ + "0d7e08d3320c8c29904a798546138ca8db9f2398", [ + null, [ - "/scroll-animations/animation-ref.html", - "==" - ] - ], - {} - ] - ], - "two-animations-attach-to-same-scroll-timeline-cancel-one.html": [ - "9071df4f7315f1d960c28dbcec68bc30d6871bf8", - [ - null, + [ + "/scroll-animations/scroll-timelines/animation-ref.html", + "==" + ] + ], + {} + ] + ], + "two-animations-attach-to-same-scroll-timeline-cancel-one.html": [ + "9071df4f7315f1d960c28dbcec68bc30d6871bf8", [ + null, [ - "/scroll-animations/animation-ref.html", - "==" - ] - ], - {} - ] - ], - "two-animations-attach-to-same-scroll-timeline.html": [ - "885898d26f39c6c691146dbe46e73d202ec1ed97", - [ - null, + [ + "/scroll-animations/scroll-timelines/animation-ref.html", + "==" + ] + ], + {} + ] + ], + "two-animations-attach-to-same-scroll-timeline.html": [ + "885898d26f39c6c691146dbe46e73d202ec1ed97", [ + null, [ - "/scroll-animations/animation-ref.html", - "==" - ] - ], - {} + [ + "/scroll-animations/scroll-timelines/animation-ref.html", + "==" + ] + ], + {} + ] ] - ] + } }, "selection": { "caret": { @@ -235490,11 +235548,11 @@ [] ], "font-palette-computed-expected.txt": [ - "dee166afbcf41df2364be766bd45add367ee68b8", + "cb95d39877d98351ba2554847535f893422bc1c9", [] ], "font-palette-valid-expected.txt": [ - "2d88f5719bf349c9b7db5725b06215f66f9748a8", + "a500af93d356c334ca369067255a7fa117740f8b", [] ], "font-palette-values-invalid-expected.txt": [ @@ -244346,6 +244404,10 @@ "42e669d316d4f470cf4d339fce632a6a69c583ca", [] ], + "empty-text-node-001-ref.html": [ + "7ec7f1bdb0b910cb1b525535d3cc1a280a3b6136", + [] + ], "inheritance-expected.txt": [ "04a22e0fee19d37384921ec696fe9e6148e04bdc", [] @@ -279919,6 +279981,10 @@ [] ] }, + "input-checkbox-disabled-checked-notref.html": [ + "8caced027a54676335db3b2199e85cbafba2abee", + [] + ], "input-date-baseline-ref.html": [ "dcef656bad00792262e05ab643195ef6804d5336", [] @@ -279927,6 +279993,10 @@ "18019c56b1bd2535b998c05f301fca3abc8ae1bb", [] ], + "input-radio-disabled-checked-notref.html": [ + "987e03cd92d7824e61cc75bbd723bd9583ab8fe1", + [] + ], "input-time-content-size-ref.html": [ "938d2659a8a8c02230c92db5b575818a5d056809", [] @@ -288143,7 +288213,7 @@ ] }, "lint.ignore": [ - "960c1837285bb57ed7cd27818c610baf2276b02c", + "38229b4ce7a4b170d6455e6f7ce0936aa44b8465", [] ], "loading": { @@ -290903,7 +290973,7 @@ [] ], "unload-bubbles.html": [ - "44f0c0cef319f279435bb38f670ed96d00ebcd17", + "cc9e14f787190efb3dd16f434636a831fd57c18d", [] ], "unload.html": [ @@ -295001,18 +295071,6 @@ "c7f0e4903b5ad46b411f0f0741112af80661cfc7", [] ], - "animation-ref.html": [ - "91587153215d4dd9ea952631464f6c4acd3d7208", - [] - ], - "animation-with-overflow-hidden-ref.html": [ - "c045f1a1c9520312db6fd68afd7f6201ce574fbb", - [] - ], - "animation-with-root-scroller-ref.html": [ - "58435be6312cb06f936117c631679663c4ed2b07", - [] - ], "css": { "scroll-timeline-cssom.tentative-expected.txt": [ "116f38ce142edb0efb004461c1a8a9a314c36283", @@ -295023,14 +295081,32 @@ "130fdb6c1b681ccf9b172eebc705737ab8bbea13", [] ], - "progress-based-effect-delay-ref.html": [ - "59366a88dde86d0deedce5eeea58b9d6c98e0913", - [] - ], - "testcommon.js": [ - "891e1f68699d2e879b360d44aecdb6425140d7fe", - [] - ] + "scroll-timelines": { + "animation-ref.html": [ + "91587153215d4dd9ea952631464f6c4acd3d7208", + [] + ], + "animation-with-overflow-hidden-ref.html": [ + "c045f1a1c9520312db6fd68afd7f6201ce574fbb", + [] + ], + "animation-with-root-scroller-ref.html": [ + "58435be6312cb06f936117c631679663c4ed2b07", + [] + ], + "idlharness.window-expected.txt": [ + "130fdb6c1b681ccf9b172eebc705737ab8bbea13", + [] + ], + "progress-based-effect-delay-ref.html": [ + "59366a88dde86d0deedce5eeea58b9d6c98e0913", + [] + ], + "testcommon.js": [ + "891e1f68699d2e879b360d44aecdb6425140d7fe", + [] + ] + } }, "scroll-to-text-fragment": { "DIR_METADATA": [ @@ -296390,10 +296466,6 @@ "3fe3911ad6b7f708251a686c5bf2fd575db2f67d", [] ], - "fetch-request-css-base-url.https-expected.txt": [ - "441ac917dc1cd52a30d72cfb570b2fca1155cac3", - [] - ], "fetch-request-xhr-sync-error.https.window-expected.txt": [ "f9ed9ece338caa4fe85b2af0bae8ea5c15c4789f", [] @@ -297020,7 +297092,7 @@ [] ], "fetch-request-css-base-url-worker.js": [ - "10d3b1880934e633ecaaf9a0dc590547ce46e462", + "f3d6a73bdde8ad26e00125c655450ccdc0f0baf8", [] ], "fetch-request-css-cross-origin-mime-check-cross.css": [ @@ -297383,6 +297455,10 @@ "6f2a8ae1d749bb58e547bdb511b895b0e6bdee43", [] ], + "navigation-timing-worker-extended.js": [ + "79c54088ff6004e2b836ab0d4cba613182379410", + [] + ], "navigation-timing-worker.js": [ "8539b40066dd91bbfaf7ef240b8104dcb2ab3b27", [] @@ -303946,10 +304022,6 @@ "01137479f933ad7649b9aa7029d4643bab92494f", [] ], - "sdes-dont-dont-dont-expected.txt": [ - "efdc199bdf252230d68403272860b9c84f7e1680", - [] - ], "vp8-fmtp-expected.txt": [ "812fedeeb10405b2948d70825e901e1581886e9b", [] @@ -344910,21 +344982,21 @@ ] ], "font-palette-computed.html": [ - "325875d3f044c4178f9e3fb324ce39e9abaafcf6", + "b73013c14756e302ef8de59344a70f4a07a2c7df", [ null, {} ] ], "font-palette-invalid.html": [ - "faba2b1f6d79fac31c66c4d6f00a494bd718a906", + "1944831bf30448cfc2e70521f1ba7ab0a420b9ef", [ null, {} ] ], "font-palette-valid.html": [ - "4a3a34ba8c489297bcdbbfb2f7a31c841176449e", + "68636ece472fd745ba8153ce6f1d1b49fa1eb6e7", [ null, {} @@ -455750,7 +455822,7 @@ ] ], "unload-bubbles.html": [ - "41f40c5bcf7abbf03f7f1fe8e1cd6822654fdde6", + "19b169c5e653a8d190fb000298f5dd33c7412436", [ null, {} @@ -475288,27 +475360,6 @@ ] }, "scroll-animations": { - "cancel-animation.html": [ - "9b578e664c7da500b1ccad1038f5783c1d23b611", - [ - null, - {} - ] - ], - "constructor-no-document.html": [ - "2062d91b1d694ab397cdd93b9b2ff06801cb5dc0", - [ - null, - {} - ] - ], - "constructor.html": [ - "02f29a0da9a8bbbd59e9bffabf1bea4ee51ac181", - [ - null, - {} - ] - ], "css": { "animation-shorthand.html": [ "7b30ec611f50c8b9bee8b28187cd9d39612b6f8d", @@ -475381,7 +475432,7 @@ ] ], "at-scroll-timeline-ignored.tentative.html": [ - "bb8b44f6c278d88a0a3a894a4d13483011c39f3e", + "dfb6ba3ceeda6c5cdd79fbc8eb688e31d797477f", [ null, {} @@ -475402,7 +475453,7 @@ ] ], "at-scroll-timeline-offset-invalidation.tentative.html": [ - "25d2484159df69e18bf21e1fd82c67ce9bac4fe3", + "13d816a062009742ab7db36026e115deb432734f", [ null, {} @@ -475423,7 +475474,7 @@ ] ], "at-scroll-timeline-source-invalidation.tentative.html": [ - "6f9ce7a85a52529f29cdf78c91972cf0a2f1e60b", + "fee39eb08b77114f2c0f88726acb0a298f0ba9e1", [ null, {} @@ -475465,217 +475516,240 @@ ] ] }, - "current-time-nan.html": [ - "48b44071681c1556ebad8d019fe00a1a1b2cac14", - [ - null, - {} - ] - ], - "current-time-root-scroller.html": [ - "6d39afaa7408099ab5f3a807c1cac3cea4da8467", - [ - null, - {} - ] - ], - "current-time-writing-modes.html": [ - "0361272d6fef22692e05a5cc8db4fa1fd02e0377", - [ - null, - {} - ] - ], - "current-time.html": [ - "ed3ed49eef78247c23885dddfed43901e3aa959b", - [ - null, - {} - ] - ], - "effect-updateTiming.html": [ - "cd5e33542b8a7ed7aa6250f82d9ef929af8d669a", - [ - null, - {} - ] - ], - "element-based-offset-clamp.html": [ - "46e65f34b7501df8ccb847bc15c2ff161a95f391", - [ - null, - {} - ] - ], - "element-based-offset-unresolved.html": [ - "29c7fa88c0b87b12946874289e5f83f9168f6438", - [ - null, - {} - ] - ], - "element-based-offset.html": [ - "355b2ab03ca29799499ecb62998e1d37bc100352", - [ - null, - {} - ] - ], - "finish-animation.html": [ - "ca46d15f5a5075d42d35e71a802608424ce6f7c3", - [ - null, - {} - ] - ], - "idlharness.window.js": [ - "90157580ce00716403346f369b1e25bba8db23c2", - [ - "scroll-animations/idlharness.window.html", - { - "script_metadata": [ - [ - "script", - "/resources/WebIDLParser.js" - ], - [ - "script", - "/resources/idlharness.js" + "scroll-timelines": { + "cancel-animation.html": [ + "9b578e664c7da500b1ccad1038f5783c1d23b611", + [ + null, + {} + ] + ], + "constructor-no-document.html": [ + "2062d91b1d694ab397cdd93b9b2ff06801cb5dc0", + [ + null, + {} + ] + ], + "constructor.html": [ + "02f29a0da9a8bbbd59e9bffabf1bea4ee51ac181", + [ + null, + {} + ] + ], + "current-time-nan.html": [ + "48b44071681c1556ebad8d019fe00a1a1b2cac14", + [ + null, + {} + ] + ], + "current-time-root-scroller.html": [ + "6d39afaa7408099ab5f3a807c1cac3cea4da8467", + [ + null, + {} + ] + ], + "current-time-writing-modes.html": [ + "0361272d6fef22692e05a5cc8db4fa1fd02e0377", + [ + null, + {} + ] + ], + "current-time.html": [ + "ed3ed49eef78247c23885dddfed43901e3aa959b", + [ + null, + {} + ] + ], + "effect-updateTiming.html": [ + "cd5e33542b8a7ed7aa6250f82d9ef929af8d669a", + [ + null, + {} + ] + ], + "element-based-offset-clamp.html": [ + "46e65f34b7501df8ccb847bc15c2ff161a95f391", + [ + null, + {} + ] + ], + "element-based-offset-unresolved.html": [ + "29c7fa88c0b87b12946874289e5f83f9168f6438", + [ + null, + {} + ] + ], + "element-based-offset.html": [ + "355b2ab03ca29799499ecb62998e1d37bc100352", + [ + null, + {} + ] + ], + "finish-animation.html": [ + "ca46d15f5a5075d42d35e71a802608424ce6f7c3", + [ + null, + {} + ] + ], + "idlharness.window.js": [ + "90157580ce00716403346f369b1e25bba8db23c2", + [ + "scroll-animations/scroll-timelines/idlharness.window.html", + { + "script_metadata": [ + [ + "script", + "/resources/WebIDLParser.js" + ], + [ + "script", + "/resources/idlharness.js" + ] ] - ] - } + } + ] + ], + "multiple-scroll-offsets.html": [ + "09a3b14c189ea809c4af5f6f3749a61a8f9d9bcb", + [ + null, + {} + ] + ], + "pause-animation.html": [ + "9486788e3fe7e685ff10b44efb36d48a5a09dcdc", + [ + null, + {} + ] + ], + "play-animation.html": [ + "522bdc48829a25707b32afe0f00385265221fc36", + [ + null, + {} + ] + ], + "progress-based-current-time.tentative.html": [ + "afd7e82b6cd71edf0613274a9d568c0b1ca3284e", + [ + null, + {} + ] + ], + "reverse-animation.html": [ + "0e9fbf28828a2304fb6121870784728ce2b1f742", + [ + null, + {} + ] + ], + "scroll-animation-effect-phases.tentative.html": [ + "ba4c692c087f438c95bff36571a6c6f7d8e85bc6", + [ + null, + { + "timeout": "long" + } + ] + ], + "scroll-animation-inactive-timeline.html": [ + "257f94d26f611c63b9558a3ad6bd501b76290256", + [ + null, + {} + ] + ], + "scroll-animation.html": [ + "102f846b3fe45839cefec9c9c9568fc166d25f0e", + [ + null, + {} + ] + ], + "scroll-timeline-invalidation.html": [ + "d5c8750dcdf8212f16e57f0f1f9ae313ae8fe169", + [ + null, + {} + ] + ], + "scroll-timeline-phases.tentative.html": [ + "6e5c752d59905ae49b7087cf356dee76b12c0f9e", + [ + null, + {} + ] + ], + "scroll-timeline-snapshotting.html": [ + "4398de6265c07488b0017fda7adfda9dd01c09e2", + [ + null, + { + "testdriver": true + } + ] + ], + "setting-current-time.html": [ + "8573a7aa49fdfdf3fd418c506df7130b2c0bbe4b", + [ + null, + {} + ] + ], + "setting-playback-rate.html": [ + "5bac2712bfda14b2530eaea70297991b131e6224", + [ + null, + {} + ] + ], + "setting-start-time.html": [ + "2cf1ddb9b38d2fe6383505bed8898bcf79177fde", + [ + null, + {} + ] + ], + "setting-timeline.tentative.html": [ + "ae29dc3fe2d8771844fd457f95ec12e6d83fdfe1", + [ + null, + {} + ] + ], + "source-quirks-mode.html": [ + "0614509e4583897bbc82798160c4f8b34a31f118", + [ + null, + {} + ] + ], + "update-playback-rate.html": [ + "1db31602f312c44906a3a14e8ef542d355f31a1f", + [ + null, + {} + ] + ], + "updating-the-finished-state.html": [ + "184b8699170d02f7ad300b909b6a69f404d5d460", + [ + null, + {} + ] ] - ], - "multiple-scroll-offsets.html": [ - "09a3b14c189ea809c4af5f6f3749a61a8f9d9bcb", - [ - null, - {} - ] - ], - "pause-animation.html": [ - "9486788e3fe7e685ff10b44efb36d48a5a09dcdc", - [ - null, - {} - ] - ], - "play-animation.html": [ - "522bdc48829a25707b32afe0f00385265221fc36", - [ - null, - {} - ] - ], - "progress-based-current-time.tentative.html": [ - "afd7e82b6cd71edf0613274a9d568c0b1ca3284e", - [ - null, - {} - ] - ], - "reverse-animation.html": [ - "0e9fbf28828a2304fb6121870784728ce2b1f742", - [ - null, - {} - ] - ], - "scroll-animation-effect-phases.tentative.html": [ - "ba4c692c087f438c95bff36571a6c6f7d8e85bc6", - [ - null, - { - "timeout": "long" - } - ] - ], - "scroll-animation-inactive-timeline.html": [ - "257f94d26f611c63b9558a3ad6bd501b76290256", - [ - null, - {} - ] - ], - "scroll-animation.html": [ - "102f846b3fe45839cefec9c9c9568fc166d25f0e", - [ - null, - {} - ] - ], - "scroll-timeline-invalidation.html": [ - "d5c8750dcdf8212f16e57f0f1f9ae313ae8fe169", - [ - null, - {} - ] - ], - "scroll-timeline-phases.tentative.html": [ - "6e5c752d59905ae49b7087cf356dee76b12c0f9e", - [ - null, - {} - ] - ], - "scroll-timeline-snapshotting.html": [ - "4398de6265c07488b0017fda7adfda9dd01c09e2", - [ - null, - { - "testdriver": true - } - ] - ], - "setting-current-time.html": [ - "8573a7aa49fdfdf3fd418c506df7130b2c0bbe4b", - [ - null, - {} - ] - ], - "setting-playback-rate.html": [ - "5bac2712bfda14b2530eaea70297991b131e6224", - [ - null, - {} - ] - ], - "setting-start-time.html": [ - "2cf1ddb9b38d2fe6383505bed8898bcf79177fde", - [ - null, - {} - ] - ], - "setting-timeline.tentative.html": [ - "ae29dc3fe2d8771844fd457f95ec12e6d83fdfe1", - [ - null, - {} - ] - ], - "source-quirks-mode.html": [ - "0614509e4583897bbc82798160c4f8b34a31f118", - [ - null, - {} - ] - ], - "update-playback-rate.html": [ - "1db31602f312c44906a3a14e8ef542d355f31a1f", - [ - null, - {} - ] - ], - "updating-the-finished-state.html": [ - "184b8699170d02f7ad300b909b6a69f404d5d460", - [ - null, - {} - ] - ] + } }, "scroll-to-text-fragment": { "find-range-from-text-directive.html": [ @@ -478817,6 +478891,13 @@ } ] ], + "navigation-timing-extended.https.html": [ + "acb02c6fe1f56ae9cf4d61516fdbf05306050914", + [ + null, + {} + ] + ], "navigation-timing.https.html": [ "6b51a5c2da213eb27cf0d9fd401b7c49b5349950", [
diff --git a/third_party/blink/web_tests/external/wpt/css/css-break/out-of-flow-in-multicolumn-075.html b/third_party/blink/web_tests/external/wpt/css/css-break/out-of-flow-in-multicolumn-075.html new file mode 100644 index 0000000..34cf1ea --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-break/out-of-flow-in-multicolumn-075.html
@@ -0,0 +1,29 @@ +<!DOCTYPE html> +<title> + Out-of-flow positioned in non-containing-block in multicol. +</title> +<link rel="help" href="https://www.w3.org/TR/css-position-3/#abspos-breaking"> +<link rel="match" href="../reference/ref-filled-green-100px-square.xht"> +<style> + .multicol { + column-count: 4; + column-gap: 0px; + width: 100px; + } + .abs { + position: absolute; + background-color: green; + height: 400px; + width: 25px; + top: 0; + } +</style> +<p>Test passes if there is a filled green square and <strong>no red</strong>.</p> +<div class="multicol"> + <div style="position: relative;"> + <div style="height: 400px; background: red"></div> + <div style="will-change: opacity"> + <div class="abs"></div> + </div> + </div> +</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-cascade/layer-basic-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-cascade/layer-basic-expected.txt deleted file mode 100644 index 0cc2db7f..0000000 --- a/third_party/blink/web_tests/external/wpt/css/css-cascade/layer-basic-expected.txt +++ /dev/null
@@ -1,37 +0,0 @@ -This is a testharness.js-based test. -PASS A1 Anonymous layers -FAIL A2 Anonymous layers assert_equals: A2 Anonymous layers, target 'first' expected "rgb(0, 128, 0)" but got "rgb(255, 0, 0)" -FAIL A3 Anonymous layers assert_equals: A3 Anonymous layers, target 'first' expected "rgb(0, 128, 0)" but got "rgb(255, 0, 0)" -PASS A4 Anonymous layers -PASS A5 Anonymous layers -PASS A6 Anonymous layers -PASS A7 Anonymous layers -PASS A8 Anonymous layers -PASS A9 Anonymous layers -PASS B1 Named layers -FAIL B2 Named layers assert_equals: B2 Named layers, target 'first' expected "rgb(0, 128, 0)" but got "rgb(255, 0, 0)" -PASS B3 Named layers -PASS B4 Named layers -PASS B5 Named layers -PASS B6 Named layers -PASS B7 Named layers -PASS B8 Named layers -PASS B9 Named layers -PASS B10 Named layers -PASS C1 Named layers shorthand -PASS C2 Named layers shorthand -PASS C3 Named layers shorthand -PASS C4 Named layers shorthand -PASS C5 Named layers shorthand -PASS D1 Mixed named and anonymous layers -PASS D2 Mixed named and anonymous layers -PASS D3 Mixed named and anonymous layers -PASS D4 Mixed named and anonymous layers -PASS D5 Mixed named and anonymous layers -PASS E1 Statement syntax -PASS E2 Statement syntax -PASS E3 Statement syntax -PASS E4 Statement syntax -PASS E5 Statement syntax -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/external/wpt/css/css-cascade/layer-basic.html b/third_party/blink/web_tests/external/wpt/css/css-cascade/layer-basic.html index f92e142..e214bff 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-cascade/layer-basic.html +++ b/third_party/blink/web_tests/external/wpt/css/css-cascade/layer-basic.html
@@ -56,9 +56,9 @@ title: 'A5 Anonymous layers', style: ` @layer { - target { color: red; } + target { color: green; } @layer { - target { color: green; } + target { color: red; } } } `, @@ -68,9 +68,9 @@ style: ` @layer { @layer { - target { color: green; } + target { color: red; } } - target { color: red; } + target { color: green; } } `, }, @@ -85,9 +85,9 @@ } @layer { @layer { - target { color: green; } + target { color: red; } } - target { color: red; } + target { color: green; } } `, }, @@ -104,9 +104,9 @@ } @layer { @layer { - target { color: green; } + target { color: red; } } - target { color: red; } + target { color: green; } } `, }, @@ -122,10 +122,10 @@ @layer { @layer { @layer { - target { color: green; } + target { color: red; } } } - target { color: red; } + target { color: green; } } `, }, @@ -175,9 +175,9 @@ title: 'B5 Named layers', style: ` @layer A { - target { color: red; } + target { color: green; } @layer A { - target { color: green; } + target { color: red; } } } `, @@ -362,11 +362,11 @@ style: ` @layer A { @layer { - target { color: green; } + target { color: red; } } } @layer A { - target { color: red; } + target { color: green; } } `, },
diff --git a/third_party/blink/web_tests/external/wpt/css/css-cascade/layer-counter-style-override.html b/third_party/blink/web_tests/external/wpt/css/css-cascade/layer-counter-style-override.html index 7ffd358..1720898 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-cascade/layer-counter-style-override.html +++ b/third_party/blink/web_tests/external/wpt/css/css-cascade/layer-counter-style-override.html
@@ -35,20 +35,20 @@ const testCases = [ { - title: '@counter-style layered overrides unlayered', + title: '@counter-style unlayered overrides layered', style: ` #target::before { content: counter(dont-care, custom-counter-style); } - @layer { - @counter-style custom-counter-style { - system: extends four; - } + @counter-style custom-counter-style { + system: extends four; } - @counter-style custom-counter-style { - system: extends three; + @layer { + @counter-style custom-counter-style { + system: extends three; + } } ` },
diff --git a/third_party/blink/web_tests/external/wpt/css/css-cascade/layer-font-face-override.html b/third_party/blink/web_tests/external/wpt/css/css-cascade/layer-font-face-override.html index 8275b08..d35caca 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-cascade/layer-font-face-override.html +++ b/third_party/blink/web_tests/external/wpt/css/css-cascade/layer-font-face-override.html
@@ -24,17 +24,17 @@ font-family: custom-font; } + @font-face { + font-family: custom-font; + src: url('/fonts/Ahem.ttf'); + } + @layer { @font-face { font-family: custom-font; src: url('/fonts/noto/noto-sans-v8-latin-regular.woff') format('woff'); } } - - @font-face { - font-family: custom-font; - src: url('/fonts/Ahem.ttf'); - } ` },
diff --git a/third_party/blink/web_tests/external/wpt/css/css-cascade/layer-import-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-cascade/layer-import-expected.txt deleted file mode 100644 index 1fc7e1b..0000000 --- a/third_party/blink/web_tests/external/wpt/css/css-cascade/layer-import-expected.txt +++ /dev/null
@@ -1,26 +0,0 @@ -This is a testharness.js-based test. -FAIL A1 Layer rules with import assert_equals: A1 Layer rules with import, target 'first' expected "rgb(0, 128, 0)" but got "rgb(255, 0, 0)" -FAIL A2 Layer rules with import assert_equals: A2 Layer rules with import, target 'first' expected "rgb(0, 128, 0)" but got "rgb(255, 0, 0)" -FAIL A3 Layer rules with import assert_equals: A3 Layer rules with import, target 'first' expected "rgb(0, 128, 0)" but got "rgb(255, 0, 0)" -PASS A4 Layer rules with import -FAIL B1 Anonymous imports assert_equals: B1 Anonymous imports, target 'first' expected "rgb(0, 128, 0)" but got "rgb(255, 0, 0)" -PASS B2 Anonymous imports -PASS B3 Anonymous imports -PASS B4 Anonymous imports -FAIL C1 Named imports assert_equals: C1 Named imports, target 'first' expected "rgb(0, 128, 0)" but got "rgb(255, 0, 0)" -PASS C2 Named imports -PASS C3 Named imports -PASS C4 Named imports -PASS C5 Named imports -PASS C6 Named imports -PASS C7 Named imports -PASS C8 Named imports -PASS C9 Named imports -PASS D1 Layer statement with imports -PASS D2 Layer statement with imports -PASS D3 Layer statement with imports -PASS D4 Layer statement with imports -PASS D5 Layer statement with imports -PASS D6 Layer statement with imports -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/external/wpt/css/css-cascade/layer-import.html b/third_party/blink/web_tests/external/wpt/css/css-cascade/layer-import.html index 935659a..0406f02 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-cascade/layer-import.html +++ b/third_party/blink/web_tests/external/wpt/css/css-cascade/layer-import.html
@@ -145,9 +145,9 @@ { title: 'C4 Named imports', style: ` - @import url(layer-green.css) layer(A); + @import url(layer-red.css) layer(A); @layer A { - target { color: red; } + target { color: green; } } ` }, @@ -192,8 +192,8 @@ title: 'C9 Named imports', style: ` @import url(basic-red.css) layer(A); - @import url(basic-green.css) layer(B.A); - @import url(basic-red.css) layer(B); + @import url(basic-red.css) layer(B.A); + @import url(basic-green.css) layer(B); ` }, {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-cascade/layer-keyframes-override-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-cascade/layer-keyframes-override-expected.txt deleted file mode 100644 index 1d5989f..0000000 --- a/third_party/blink/web_tests/external/wpt/css/css-cascade/layer-keyframes-override-expected.txt +++ /dev/null
@@ -1,7 +0,0 @@ -This is a testharness.js-based test. -FAIL @keyframes unlayered overrides layered assert_equals: expected "rgb(0, 128, 0)" but got "rgb(255, 0, 0)" -PASS @keyframes override between layers -PASS @keyframes override update with appended sheet 1 -PASS @keyframes override update with appended sheet 2 -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/external/wpt/css/css-cascade/layer-keyframes-override.html b/third_party/blink/web_tests/external/wpt/css/css-cascade/layer-keyframes-override.html index f896303..d0f4044 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-cascade/layer-keyframes-override.html +++ b/third_party/blink/web_tests/external/wpt/css/css-cascade/layer-keyframes-override.html
@@ -29,15 +29,15 @@ animation: anim 1s paused; } + @keyframes anim { + from { background-color: green; } + } + @layer { @keyframes anim { from { background-color: red; } } } - - @keyframes anim { - from { background-color: green; } - } ` },
diff --git a/third_party/blink/web_tests/external/wpt/css/css-cascade/layer-property-override.html b/third_party/blink/web_tests/external/wpt/css/css-cascade/layer-property-override.html index f0f8d83..9d3f9cb 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-cascade/layer-property-override.html +++ b/third_party/blink/web_tests/external/wpt/css/css-cascade/layer-property-override.html
@@ -23,26 +23,26 @@ const testCases = [ { - title: '@property layered overrides unlayered', + title: '@property unlayered overrides layered', style: ` #target { background-color: var(--foo); } + @property --foo { + syntax: '<color>'; + inherits: false; + initial-value: green; + } + @layer { @property --foo { syntax: '<color>'; inherits: false; - initial-value: green; + initial-value: red; } } - - @property --foo { - syntax: '<color>'; - inherits: false; - initial-value: red; - } - ` + ` }, {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-cascade/layer-scroll-timeline-override.html b/third_party/blink/web_tests/external/wpt/css/css-cascade/layer-scroll-timeline-override.html index 9a50914..59b8590 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-cascade/layer-scroll-timeline-override.html +++ b/third_party/blink/web_tests/external/wpt/css/css-cascade/layer-scroll-timeline-override.html
@@ -46,25 +46,25 @@ const testCases = [ { - title: '@scroll-timeline layered overrides unlayered', + title: '@scroll-timeline unlayered overrides layered', style: ` #target { animation-timeline: timeline; } + @scroll-timeline timeline { + source: selector(#scroller); + start: 0px; + end: 50px; + } + @layer { @scroll-timeline timeline { source: selector(#scroller); start: 0px; - end: 50px; + end: 100px; } } - - @scroll-timeline timeline { - source: selector(#scroller); - start: 0px; - end: 100px; - } ` },
diff --git a/third_party/blink/web_tests/external/wpt/css/css-cascade/presentational-hints-cascade.html b/third_party/blink/web_tests/external/wpt/css/css-cascade/presentational-hints-cascade.html index 729dc71..c3188fd 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-cascade/presentational-hints-cascade.html +++ b/third_party/blink/web_tests/external/wpt/css/css-cascade/presentational-hints-cascade.html
@@ -12,10 +12,17 @@ #target1 { width: 100px; } + +@layer { + #target3 { + width: 100px; + } +} </style> <img class=test id=target1 width=200> <img class=test id=target2 width=200 style="width: 100px"> +<img class=test id=target3 width=200> <script> test(() => { @@ -25,4 +32,8 @@ test(() => { assert_equals(getComputedStyle(target2).width, '100px'); }, 'Presentational hints have lower precedence than the style attribute'); + +test(() => { + assert_equals(getComputedStyle(target3).width, '100px'); +}, 'Presentational hints have lower precedence than layered style'); </script>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-fonts/parsing/font-palette-computed-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-fonts/parsing/font-palette-computed-expected.txt index dee166af..cb95d39 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-fonts/parsing/font-palette-computed-expected.txt +++ b/third_party/blink/web_tests/external/wpt/css/css-fonts/parsing/font-palette-computed-expected.txt
@@ -1,5 +1,4 @@ This is a testharness.js-based test. -FAIL Property font-palette value 'none' assert_true: font-palette doesn't seem to be supported in the computed style expected true got false FAIL Property font-palette value 'normal' assert_true: font-palette doesn't seem to be supported in the computed style expected true got false FAIL Property font-palette value 'light' assert_true: font-palette doesn't seem to be supported in the computed style expected true got false FAIL Property font-palette value 'dark' assert_true: font-palette doesn't seem to be supported in the computed style expected true got false
diff --git a/third_party/blink/web_tests/external/wpt/css/css-fonts/parsing/font-palette-computed.html b/third_party/blink/web_tests/external/wpt/css/css-fonts/parsing/font-palette-computed.html index 325875d..b73013c 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-fonts/parsing/font-palette-computed.html +++ b/third_party/blink/web_tests/external/wpt/css/css-fonts/parsing/font-palette-computed.html
@@ -12,7 +12,6 @@ <body> <div id="target"></div> <script> -test_computed_value('font-palette', 'none'); test_computed_value('font-palette', 'normal'); test_computed_value('font-palette', 'light'); test_computed_value('font-palette', 'dark');
diff --git a/third_party/blink/web_tests/external/wpt/css/css-fonts/parsing/font-palette-invalid.html b/third_party/blink/web_tests/external/wpt/css/css-fonts/parsing/font-palette-invalid.html index faba2b1..1944831 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-fonts/parsing/font-palette-invalid.html +++ b/third_party/blink/web_tests/external/wpt/css/css-fonts/parsing/font-palette-invalid.html
@@ -13,6 +13,7 @@ <script> test_invalid_value('font-palette', 'normal none'); test_invalid_value('font-palette', 'none, light'); +test_invalid_value('font-palette', 'none'); </script> </body> </html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-fonts/parsing/font-palette-valid-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-fonts/parsing/font-palette-valid-expected.txt index 2d88f57..a500af9 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-fonts/parsing/font-palette-valid-expected.txt +++ b/third_party/blink/web_tests/external/wpt/css/css-fonts/parsing/font-palette-valid-expected.txt
@@ -1,5 +1,4 @@ This is a testharness.js-based test. -FAIL e.style['font-palette'] = "none" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['font-palette'] = "normal" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['font-palette'] = "light" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['font-palette'] = "dark" should set the property value assert_not_equals: property should be set got disallowed value ""
diff --git a/third_party/blink/web_tests/external/wpt/css/css-fonts/parsing/font-palette-valid.html b/third_party/blink/web_tests/external/wpt/css/css-fonts/parsing/font-palette-valid.html index 4a3a34b..68636ece 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-fonts/parsing/font-palette-valid.html +++ b/third_party/blink/web_tests/external/wpt/css/css-fonts/parsing/font-palette-valid.html
@@ -4,14 +4,13 @@ <meta charset="utf-8"> <title>CSS Fonts Module Level 4: parsing font-palette with valid values</title> <link rel="help" href="https://drafts.csswg.org/css-fonts/#font-palette-prop"> -<meta name="assert" content="font-palette supports the full grammar 'none | normal | light | dark | <palette-identifier>'."> +<meta name="assert" content="font-palette supports the full grammar 'normal | light | dark | <palette-identifier>'."> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> <script src="/css/support/parsing-testcommon.js"></script> </head> <body> <script> -test_valid_value('font-palette', 'none'); test_valid_value('font-palette', 'normal'); test_valid_value('font-palette', 'light'); test_valid_value('font-palette', 'dark');
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/empty-text-node-001-ref.html b/third_party/blink/web_tests/external/wpt/css/css-inline/empty-text-node-001-ref.html new file mode 100644 index 0000000..7ec7f1bd --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-inline/empty-text-node-001-ref.html
@@ -0,0 +1,46 @@ +<!DOCTYPE html> +<html lang=en> +<meta charset="utf-8"> +<title>CSS Inline reference</title> +<link rel="author" title="Jonathan Kew" href="mailto:jkew@mozilla.com"> +<style> +.green { color: green; } +.red { color: red; } +.ref { + display: inline-block; +} +div div { + width: 50px; + height: 0px; + border: 20px solid green; + margin: 10px; +} +</style> +<p>Test passes if the <span class=green>green</span> boxes have <span class=red>no red</span> in the middle.</p> + +<div class=ref> + <div></div> + <div></div> + <div></div> + <div></div> + <div></div> + <div></div> +</div> + +<div class=ref> + <div></div> + <div></div> + <div></div> + <div></div> + <div></div> + <div></div> +</div> + +<div class=ref> + <div></div> + <div></div> + <div></div> + <div></div> + <div></div> + <div></div> +</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/empty-text-node-001.html b/third_party/blink/web_tests/external/wpt/css/css-inline/empty-text-node-001.html new file mode 100644 index 0000000..eddf31e --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-inline/empty-text-node-001.html
@@ -0,0 +1,65 @@ +<!DOCTYPE html> +<html lang=en> +<meta charset="utf-8"> +<title>CSS Inline test: empty text node</title> +<link rel="author" title="Jonathan Kew" href="mailto:jkew@mozilla.com"> +<link rel="help" title="2.1. Layout of Line Boxes" href="https://drafts.csswg.org/css-inline/#line-boxes"> +<link rel="match" href="empty-text-node-001-ref.html"> +<meta name="assert" content="Empty text node in a line box is treated as zero height."> +<style> +.green { color: green; } +.red { color: red; } +.testContent, .testBefore, .testAfter { + display: inline-block; +} +div div { + width: 50px; + line-height: 30px; + border: 20px solid green; + background-color: red; + margin: 10px; +} +.testBefore div::before { + content: ""; +} +.testAfter div::after { + content: ""; +} +.normal { white-space: normal; } +.nowrap { white-space: nowrap; } +.pre { white-space: pre; } +.prewrap { white-space: pre-wrap; } +.preline { white-space: pre-line; } +.breakspaces { white-space: break-spaces; } +</style> +<p>Test passes if the <span class=green>green</span> boxes have <span class=red>no red</span> in the middle.</p> + +<div class=testContent> + <div class=normal></div> + <div class=nowrap></div> + <div class=pre></div> + <div class=prewrap></div> + <div class=preline></div> + <div class=breakspaces></div> + <script> + [...document.querySelectorAll(".testContent div")].forEach((node, i) => node.appendChild(document.createTextNode(""))); + </script> +</div> + +<div class=testBefore> + <div class=normal></div> + <div class=nowrap></div> + <div class=pre></div> + <div class=prewrap></div> + <div class=preline></div> + <div class=breakspaces></div> +</div> + +<div class=testAfter> + <div class=normal></div> + <div class=nowrap></div> + <div class=pre></div> + <div class=prewrap></div> + <div class=preline></div> + <div class=breakspaces></div> +</div>
diff --git a/third_party/blink/web_tests/external/wpt/html/rendering/widgets/input-checkbox-disabled-checked-notref.html b/third_party/blink/web_tests/external/wpt/html/rendering/widgets/input-checkbox-disabled-checked-notref.html new file mode 100644 index 0000000..8caced0 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/rendering/widgets/input-checkbox-disabled-checked-notref.html
@@ -0,0 +1,2 @@ +<!doctype html> +<input type=checkbox disabled>
diff --git a/third_party/blink/web_tests/external/wpt/html/rendering/widgets/input-checkbox-disabled-checked.html b/third_party/blink/web_tests/external/wpt/html/rendering/widgets/input-checkbox-disabled-checked.html new file mode 100644 index 0000000..f72fdf62 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/rendering/widgets/input-checkbox-disabled-checked.html
@@ -0,0 +1,5 @@ +<!doctype html> +<title>checkbox with disabled and checked attributes renders differently than unchecked</title> +<link rel=help href="https://bugzilla.mozilla.org/show_bug.cgi?id=1735077"> +<link rel=mismatch href="input-checkbox-disabled-checked-notref.html"> +<input type=checkbox disabled checked>
diff --git a/third_party/blink/web_tests/external/wpt/html/rendering/widgets/input-radio-disabled-checked-notref.html b/third_party/blink/web_tests/external/wpt/html/rendering/widgets/input-radio-disabled-checked-notref.html new file mode 100644 index 0000000..987e03c --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/rendering/widgets/input-radio-disabled-checked-notref.html
@@ -0,0 +1,2 @@ +<!doctype html> +<input type=radio disabled>
diff --git a/third_party/blink/web_tests/external/wpt/html/rendering/widgets/input-radio-disabled-checked.html b/third_party/blink/web_tests/external/wpt/html/rendering/widgets/input-radio-disabled-checked.html new file mode 100644 index 0000000..3ac2a37 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/rendering/widgets/input-radio-disabled-checked.html
@@ -0,0 +1,5 @@ +<!doctype html> +<title>radio with disabled and checked attributes renders differently than unchecked</title> +<link rel=help href="https://bugzilla.mozilla.org/show_bug.cgi?id=1735077"> +<link rel=mismatch href="input-radio-disabled-checked-notref.html"> +<input type=radio disabled checked>
diff --git a/third_party/blink/web_tests/external/wpt/lint.ignore b/third_party/blink/web_tests/external/wpt/lint.ignore index 960c1837..38229b4 100644 --- a/third_party/blink/web_tests/external/wpt/lint.ignore +++ b/third_party/blink/web_tests/external/wpt/lint.ignore
@@ -798,7 +798,7 @@ TESTHARNESS-IN-OTHER-TYPE: html/semantics/text-level-semantics/the-ruby-element/rt-without-ruby-crash.html TESTHARNESS-IN-OTHER-TYPE: portals/portals-no-frame-crash.html TESTHARNESS-IN-OTHER-TYPE: quirks/table-replaced-descendant-percentage-height-crash.html -TESTHARNESS-IN-OTHER-TYPE: scroll-animations/null-scroll-source-crash.html +TESTHARNESS-IN-OTHER-TYPE: scroll-animations/scroll-timelines/null-scroll-source-crash.html TESTHARNESS-IN-OTHER-TYPE: svg/extensibility/foreignObject/foreign-object-circular-filter-reference-crash.html TESTHARNESS-IN-OTHER-TYPE: svg/extensibility/foreignObject/foreign-object-under-clip-path-crash.html TESTHARNESS-IN-OTHER-TYPE: svg/extensibility/foreignObject/foreign-object-under-defs-crash.html
diff --git a/third_party/blink/web_tests/external/wpt/page-visibility/resources/unload-bubbles.html b/third_party/blink/web_tests/external/wpt/page-visibility/resources/unload-bubbles.html index 44f0c0c..cc9e14f7 100644 --- a/third_party/blink/web_tests/external/wpt/page-visibility/resources/unload-bubbles.html +++ b/third_party/blink/web_tests/external/wpt/page-visibility/resources/unload-bubbles.html
@@ -5,8 +5,12 @@ <h1>Document</h1> <script> window.addEventListener("load", function() { - window.addEventListener("visibilitychange", function() { - opener.postMessage(document.visibilityState, "*"); + window.addEventListener("visibilitychange", event => { + opener.postMessage({ + target: event.target.nodeName, + state: document.visibilityState, + bubbles: event.bubbles + }, "*"); }); opener.postMessage("close", "*"); });
diff --git a/third_party/blink/web_tests/external/wpt/page-visibility/unload-bubbles.html b/third_party/blink/web_tests/external/wpt/page-visibility/unload-bubbles.html index 41f40c5..19b169c 100644 --- a/third_party/blink/web_tests/external/wpt/page-visibility/unload-bubbles.html +++ b/third_party/blink/web_tests/external/wpt/page-visibility/unload-bubbles.html
@@ -11,7 +11,11 @@ w.close(); return; } - assert_equals(event.data, "hidden"); + + const {state, target, bubbles} = event.data + assert_equals(state, "hidden"); + assert_equals(target, "#document"); + assert_equals(bubbles, true); t.done(); }); });
diff --git a/third_party/blink/web_tests/external/wpt/scroll-animations/css/at-scroll-timeline-ignored.tentative.html b/third_party/blink/web_tests/external/wpt/scroll-animations/css/at-scroll-timeline-ignored.tentative.html index bb8b44f6..dfb6ba3 100644 --- a/third_party/blink/web_tests/external/wpt/scroll-animations/css/at-scroll-timeline-ignored.tentative.html +++ b/third_party/blink/web_tests/external/wpt/scroll-animations/css/at-scroll-timeline-ignored.tentative.html
@@ -42,7 +42,7 @@ width: 0px; height: 20px; animation-name: expand; - animation-duration: 1e10s; + animation-duration: 1000s; animation-timing-function: linear; animation-timeline: timeline1; }
diff --git a/third_party/blink/web_tests/external/wpt/scroll-animations/css/at-scroll-timeline-offset-invalidation.tentative.html b/third_party/blink/web_tests/external/wpt/scroll-animations/css/at-scroll-timeline-offset-invalidation.tentative.html index 25d2484..13d816a 100644 --- a/third_party/blink/web_tests/external/wpt/scroll-animations/css/at-scroll-timeline-offset-invalidation.tentative.html +++ b/third_party/blink/web_tests/external/wpt/scroll-animations/css/at-scroll-timeline-offset-invalidation.tentative.html
@@ -25,7 +25,7 @@ #element { width: 0px; height: 20px; - animation: expand 1e10s linear; + animation: expand 1000s linear; animation-timeline: timeline; } /* Ensure stable expectations if feature is not supported */
diff --git a/third_party/blink/web_tests/external/wpt/scroll-animations/css/at-scroll-timeline-source-invalidation.tentative.html b/third_party/blink/web_tests/external/wpt/scroll-animations/css/at-scroll-timeline-source-invalidation.tentative.html index 6f9ce7a8..fee39eb 100644 --- a/third_party/blink/web_tests/external/wpt/scroll-animations/css/at-scroll-timeline-source-invalidation.tentative.html +++ b/third_party/blink/web_tests/external/wpt/scroll-animations/css/at-scroll-timeline-source-invalidation.tentative.html
@@ -29,7 +29,7 @@ #element { width: 0px; height: 20px; - animation: expand 1e10s linear; + animation: expand 1000s linear; animation-timeline: timeline; } /* Ensure stable expectations if feature is not supported */
diff --git a/third_party/blink/web_tests/external/wpt/scroll-animations/animation-ref.html b/third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/animation-ref.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/scroll-animations/animation-ref.html rename to third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/animation-ref.html
diff --git a/third_party/blink/web_tests/external/wpt/scroll-animations/animation-with-animatable-interface.html b/third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/animation-with-animatable-interface.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/scroll-animations/animation-with-animatable-interface.html rename to third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/animation-with-animatable-interface.html
diff --git a/third_party/blink/web_tests/external/wpt/scroll-animations/animation-with-display-none.html b/third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/animation-with-display-none.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/scroll-animations/animation-with-display-none.html rename to third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/animation-with-display-none.html
diff --git a/third_party/blink/web_tests/external/wpt/scroll-animations/animation-with-overflow-hidden-ref.html b/third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/animation-with-overflow-hidden-ref.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/scroll-animations/animation-with-overflow-hidden-ref.html rename to third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/animation-with-overflow-hidden-ref.html
diff --git a/third_party/blink/web_tests/external/wpt/scroll-animations/animation-with-overflow-hidden.html b/third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/animation-with-overflow-hidden.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/scroll-animations/animation-with-overflow-hidden.html rename to third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/animation-with-overflow-hidden.html
diff --git a/third_party/blink/web_tests/external/wpt/scroll-animations/animation-with-root-scroller-ref.html b/third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/animation-with-root-scroller-ref.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/scroll-animations/animation-with-root-scroller-ref.html rename to third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/animation-with-root-scroller-ref.html
diff --git a/third_party/blink/web_tests/external/wpt/scroll-animations/animation-with-root-scroller.html b/third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/animation-with-root-scroller.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/scroll-animations/animation-with-root-scroller.html rename to third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/animation-with-root-scroller.html
diff --git a/third_party/blink/web_tests/external/wpt/scroll-animations/animation-with-transform.html b/third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/animation-with-transform.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/scroll-animations/animation-with-transform.html rename to third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/animation-with-transform.html
diff --git a/third_party/blink/web_tests/external/wpt/scroll-animations/cancel-animation.html b/third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/cancel-animation.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/scroll-animations/cancel-animation.html rename to third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/cancel-animation.html
diff --git a/third_party/blink/web_tests/external/wpt/scroll-animations/constructor-no-document.html b/third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/constructor-no-document.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/scroll-animations/constructor-no-document.html rename to third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/constructor-no-document.html
diff --git a/third_party/blink/web_tests/external/wpt/scroll-animations/constructor.html b/third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/constructor.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/scroll-animations/constructor.html rename to third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/constructor.html
diff --git a/third_party/blink/web_tests/external/wpt/scroll-animations/current-time-nan.html b/third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/current-time-nan.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/scroll-animations/current-time-nan.html rename to third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/current-time-nan.html
diff --git a/third_party/blink/web_tests/external/wpt/scroll-animations/current-time-root-scroller.html b/third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/current-time-root-scroller.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/scroll-animations/current-time-root-scroller.html rename to third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/current-time-root-scroller.html
diff --git a/third_party/blink/web_tests/external/wpt/scroll-animations/current-time-writing-modes.html b/third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/current-time-writing-modes.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/scroll-animations/current-time-writing-modes.html rename to third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/current-time-writing-modes.html
diff --git a/third_party/blink/web_tests/external/wpt/scroll-animations/current-time.html b/third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/current-time.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/scroll-animations/current-time.html rename to third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/current-time.html
diff --git a/third_party/blink/web_tests/external/wpt/scroll-animations/effect-updateTiming.html b/third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/effect-updateTiming.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/scroll-animations/effect-updateTiming.html rename to third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/effect-updateTiming.html
diff --git a/third_party/blink/web_tests/external/wpt/scroll-animations/element-based-offset-clamp.html b/third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/element-based-offset-clamp.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/scroll-animations/element-based-offset-clamp.html rename to third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/element-based-offset-clamp.html
diff --git a/third_party/blink/web_tests/external/wpt/scroll-animations/element-based-offset-unresolved.html b/third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/element-based-offset-unresolved.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/scroll-animations/element-based-offset-unresolved.html rename to third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/element-based-offset-unresolved.html
diff --git a/third_party/blink/web_tests/external/wpt/scroll-animations/element-based-offset.html b/third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/element-based-offset.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/scroll-animations/element-based-offset.html rename to third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/element-based-offset.html
diff --git a/third_party/blink/web_tests/external/wpt/scroll-animations/finish-animation.html b/third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/finish-animation.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/scroll-animations/finish-animation.html rename to third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/finish-animation.html
diff --git a/third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/idlharness.window-expected.txt b/third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/idlharness.window-expected.txt new file mode 100644 index 0000000..130fdb6c --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/idlharness.window-expected.txt
@@ -0,0 +1,11 @@ +This is a testharness.js-based test. +FAIL idl_test setup promise_test: Unhandled rejection with value: object "CSSScrollTimelineRule inherits CSSRule, but CSSRule is undefined." +PASS idl_test validation +PASS Partial interface Element: member names are unique +PASS Element includes Animatable: member names are unique +PASS Element includes ParentNode: member names are unique +PASS Element includes NonDocumentTypeChildNode: member names are unique +PASS Element includes ChildNode: member names are unique +PASS Element includes Slottable: member names are unique +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/scroll-animations/idlharness.window.js b/third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/idlharness.window.js similarity index 100% rename from third_party/blink/web_tests/external/wpt/scroll-animations/idlharness.window.js rename to third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/idlharness.window.js
diff --git a/third_party/blink/web_tests/external/wpt/scroll-animations/layout-changes-on-percentage-based-timeline.html b/third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/layout-changes-on-percentage-based-timeline.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/scroll-animations/layout-changes-on-percentage-based-timeline.html rename to third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/layout-changes-on-percentage-based-timeline.html
diff --git a/third_party/blink/web_tests/external/wpt/scroll-animations/multiple-scroll-offsets.html b/third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/multiple-scroll-offsets.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/scroll-animations/multiple-scroll-offsets.html rename to third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/multiple-scroll-offsets.html
diff --git a/third_party/blink/web_tests/external/wpt/scroll-animations/null-scroll-source-crash.html b/third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/null-scroll-source-crash.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/scroll-animations/null-scroll-source-crash.html rename to third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/null-scroll-source-crash.html
diff --git a/third_party/blink/web_tests/external/wpt/scroll-animations/pause-animation.html b/third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/pause-animation.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/scroll-animations/pause-animation.html rename to third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/pause-animation.html
diff --git a/third_party/blink/web_tests/external/wpt/scroll-animations/play-animation.html b/third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/play-animation.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/scroll-animations/play-animation.html rename to third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/play-animation.html
diff --git a/third_party/blink/web_tests/external/wpt/scroll-animations/progress-based-current-time.tentative.html b/third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/progress-based-current-time.tentative.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/scroll-animations/progress-based-current-time.tentative.html rename to third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/progress-based-current-time.tentative.html
diff --git a/third_party/blink/web_tests/external/wpt/scroll-animations/progress-based-effect-delay-ref.html b/third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/progress-based-effect-delay-ref.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/scroll-animations/progress-based-effect-delay-ref.html rename to third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/progress-based-effect-delay-ref.html
diff --git a/third_party/blink/web_tests/external/wpt/scroll-animations/progress-based-effect-delay.tentative.html b/third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/progress-based-effect-delay.tentative.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/scroll-animations/progress-based-effect-delay.tentative.html rename to third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/progress-based-effect-delay.tentative.html
diff --git a/third_party/blink/web_tests/external/wpt/scroll-animations/reverse-animation.html b/third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/reverse-animation.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/scroll-animations/reverse-animation.html rename to third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/reverse-animation.html
diff --git a/third_party/blink/web_tests/external/wpt/scroll-animations/scroll-animation-effect-phases.tentative.html b/third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/scroll-animation-effect-phases.tentative.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/scroll-animations/scroll-animation-effect-phases.tentative.html rename to third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/scroll-animation-effect-phases.tentative.html
diff --git a/third_party/blink/web_tests/external/wpt/scroll-animations/scroll-animation-inactive-timeline.html b/third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/scroll-animation-inactive-timeline.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/scroll-animations/scroll-animation-inactive-timeline.html rename to third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/scroll-animation-inactive-timeline.html
diff --git a/third_party/blink/web_tests/external/wpt/scroll-animations/scroll-animation.html b/third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/scroll-animation.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/scroll-animations/scroll-animation.html rename to third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/scroll-animation.html
diff --git a/third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timeline-invalidation.html b/third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/scroll-timeline-invalidation.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timeline-invalidation.html rename to third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/scroll-timeline-invalidation.html
diff --git a/third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timeline-phases.tentative.html b/third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/scroll-timeline-phases.tentative.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timeline-phases.tentative.html rename to third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/scroll-timeline-phases.tentative.html
diff --git a/third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timeline-snapshotting.html b/third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/scroll-timeline-snapshotting.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timeline-snapshotting.html rename to third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/scroll-timeline-snapshotting.html
diff --git a/third_party/blink/web_tests/external/wpt/scroll-animations/set-current-time-before-play.html b/third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/set-current-time-before-play.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/scroll-animations/set-current-time-before-play.html rename to third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/set-current-time-before-play.html
diff --git a/third_party/blink/web_tests/external/wpt/scroll-animations/setting-current-time.html b/third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/setting-current-time.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/scroll-animations/setting-current-time.html rename to third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/setting-current-time.html
diff --git a/third_party/blink/web_tests/external/wpt/scroll-animations/setting-playback-rate.html b/third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/setting-playback-rate.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/scroll-animations/setting-playback-rate.html rename to third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/setting-playback-rate.html
diff --git a/third_party/blink/web_tests/external/wpt/scroll-animations/setting-start-time.html b/third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/setting-start-time.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/scroll-animations/setting-start-time.html rename to third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/setting-start-time.html
diff --git a/third_party/blink/web_tests/external/wpt/scroll-animations/setting-timeline.tentative.html b/third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/setting-timeline.tentative.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/scroll-animations/setting-timeline.tentative.html rename to third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/setting-timeline.tentative.html
diff --git a/third_party/blink/web_tests/external/wpt/scroll-animations/source-quirks-mode.html b/third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/source-quirks-mode.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/scroll-animations/source-quirks-mode.html rename to third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/source-quirks-mode.html
diff --git a/third_party/blink/web_tests/external/wpt/scroll-animations/testcommon.js b/third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/testcommon.js similarity index 100% rename from third_party/blink/web_tests/external/wpt/scroll-animations/testcommon.js rename to third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/testcommon.js
diff --git a/third_party/blink/web_tests/external/wpt/scroll-animations/two-animations-attach-to-same-scroll-timeline-cancel-one.html b/third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/two-animations-attach-to-same-scroll-timeline-cancel-one.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/scroll-animations/two-animations-attach-to-same-scroll-timeline-cancel-one.html rename to third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/two-animations-attach-to-same-scroll-timeline-cancel-one.html
diff --git a/third_party/blink/web_tests/external/wpt/scroll-animations/two-animations-attach-to-same-scroll-timeline.html b/third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/two-animations-attach-to-same-scroll-timeline.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/scroll-animations/two-animations-attach-to-same-scroll-timeline.html rename to third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/two-animations-attach-to-same-scroll-timeline.html
diff --git a/third_party/blink/web_tests/external/wpt/scroll-animations/update-playback-rate.html b/third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/update-playback-rate.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/scroll-animations/update-playback-rate.html rename to third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/update-playback-rate.html
diff --git a/third_party/blink/web_tests/external/wpt/scroll-animations/updating-the-finished-state.html b/third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/updating-the-finished-state.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/scroll-animations/updating-the-finished-state.html rename to third_party/blink/web_tests/external/wpt/scroll-animations/scroll-timelines/updating-the-finished-state.html
diff --git a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/navigation-timing-extended.https.html b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/navigation-timing-extended.https.html new file mode 100644 index 0000000..acb02c6 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/navigation-timing-extended.https.html
@@ -0,0 +1,55 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/test-helpers.sub.js"></script> + +<script> +const timingEventOrder = [ + 'startTime', + 'workerStart', + 'fetchStart', + 'requestStart', + 'responseStart', + 'responseEnd', +]; + +function navigate_in_frame(frame, url) { + frame.contentWindow.location = url; + return new Promise((resolve) => { + frame.addEventListener('load', () => { + const timing = frame.contentWindow.performance.getEntriesByType('navigation')[0]; + const {timeOrigin} = frame.contentWindow.performance; + resolve({ + workerStart: timing.workerStart + timeOrigin, + fetchStart: timing.fetchStart + timeOrigin + }) + }); + }); +} + +const worker_url = 'resources/navigation-timing-worker-extended.js'; + +promise_test(async (t) => { + const scope = 'resources/timings/dummy.html'; + const registration = await service_worker_unregister_and_register(t, worker_url, scope); + t.add_cleanup(() => registration.unregister()); + await wait_for_state(t, registration.installing, 'activating'); + const frame = await with_iframe('resources/empty.html'); + t.add_cleanup(() => frame.remove()); + + const [timingFromEntry, timingFromWorker] = await Promise.all([ + navigate_in_frame(frame, scope), + new Promise(resolve => { + window.addEventListener('message', m => { + resolve(m.data) + }) + })]) + + assert_greater_than(timingFromWorker.activateWorkerEnd, timingFromEntry.workerStart, + 'workerStart marking should not wait for worker activation to finish'); + assert_greater_than(timingFromEntry.fetchStart, timingFromWorker.activateWorkerEnd, + 'fetchStart should be marked once the worker is activated'); + assert_greater_than(timingFromWorker.handleFetchEvent, timingFromEntry.fetchStart, + 'fetchStart should be marked before the Fetch event handler is called'); +}, 'Service worker controlled navigation timing'); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/navigation-timing-worker-extended.js b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/navigation-timing-worker-extended.js new file mode 100644 index 0000000..79c54088 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/service-workers/service-worker/resources/navigation-timing-worker-extended.js
@@ -0,0 +1,22 @@ +importScripts("/resources/testharness.js"); +const timings = {} + +const DELAY_ACTIVATION = 500 + +self.addEventListener('activate', event => { + event.waitUntil(new Promise(resolve => { + timings.activateWorkerStart = performance.now() + performance.timeOrigin; + + // This gives us enough time to ensure activation would delay fetch handling + step_timeout(resolve, DELAY_ACTIVATION); + }).then(() => timings.activateWorkerEnd = performance.now() + performance.timeOrigin)); +}) + +self.addEventListener('fetch', event => { + timings.handleFetchEvent = performance.now() + performance.timeOrigin; + event.respondWith(Promise.resolve(new Response(new Blob([` + <script> + parent.postMessage(${JSON.stringify(timings)}, "*") + </script> + `])))); +});
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/accessibility/accessibility-ignoredNodes-expected.txt b/third_party/blink/web_tests/http/tests/inspector-protocol/accessibility/accessibility-ignoredNodes-expected.txt index fe46ec6..2f1cc512 100644 --- a/third_party/blink/web_tests/http/tests/inspector-protocol/accessibility/accessibility-ignoredNodes-expected.txt +++ b/third_party/blink/web_tests/http/tests/inspector-protocol/accessibility/accessibility-ignoredNodes-expected.txt
@@ -16,7 +16,7 @@ RootWebArea img - *SvgRoot + *img { childIds : <object> domNode : svg @@ -47,8 +47,8 @@ properties : [ ] role : { - type : internalRole - value : SvgRoot + type : role + value : img } }
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/accessibility/accessibility-nameSources-img-figure-expected.txt b/third_party/blink/web_tests/http/tests/inspector-protocol/accessibility/accessibility-nameSources-img-figure-expected.txt index 6200b57..24e03bce 100644 --- a/third_party/blink/web_tests/http/tests/inspector-protocol/accessibility/accessibility-nameSources-img-figure-expected.txt +++ b/third_party/blink/web_tests/http/tests/inspector-protocol/accessibility/accessibility-nameSources-img-figure-expected.txt
@@ -671,8 +671,8 @@ } ] role : { - type : internalRole - value : SvgRoot + type : role + value : img } }
diff --git a/third_party/blink/web_tests/http/tests/serviceworker/resources/register-service-worker-verify-third-party-use-counter.html b/third_party/blink/web_tests/http/tests/serviceworker/resources/register-service-worker-verify-third-party-use-counter.html index 07afd02..1b154b4 100644 --- a/third_party/blink/web_tests/http/tests/serviceworker/resources/register-service-worker-verify-third-party-use-counter.html +++ b/third_party/blink/web_tests/http/tests/serviceworker/resources/register-service-worker-verify-third-party-use-counter.html
@@ -20,11 +20,8 @@ return reg.unregister(); }) .then(successful => { - if (successful) { - msg.source.postMessage('unregister_done', '*'); - } else { - msg.source.postMessage('unregister_failed', '*'); - } + // Report "done" as long as unregister completed. + msg.source.postMessage('unregister_done', '*'); }); } else { msg.source.postMessage('unexpected_message', '*');
diff --git a/third_party/blink/web_tests/platform/linux/external/wpt/service-workers/service-worker/navigation-timing-extended.https-expected.txt b/third_party/blink/web_tests/platform/linux/external/wpt/service-workers/service-worker/navigation-timing-extended.https-expected.txt new file mode 100644 index 0000000..d8073bf --- /dev/null +++ b/third_party/blink/web_tests/platform/linux/external/wpt/service-workers/service-worker/navigation-timing-extended.https-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL Service worker controlled navigation timing assert_greater_than: workerStart marking should not wait for worker activation to finish expected a number greater than 1634042632175.5 but got 1634042632172.9001 +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/linux/virtual/plz-dedicated-worker/external/wpt/service-workers/service-worker/navigation-timing-extended.https-expected.txt b/third_party/blink/web_tests/platform/linux/virtual/plz-dedicated-worker/external/wpt/service-workers/service-worker/navigation-timing-extended.https-expected.txt new file mode 100644 index 0000000..f1572277 --- /dev/null +++ b/third_party/blink/web_tests/platform/linux/virtual/plz-dedicated-worker/external/wpt/service-workers/service-worker/navigation-timing-extended.https-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL Service worker controlled navigation timing assert_greater_than: workerStart marking should not wait for worker activation to finish expected a number greater than 1634041957803.2998 but got 1634041957802 +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/external/wpt/service-workers/service-worker/navigation-timing-extended.https-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.12/external/wpt/service-workers/service-worker/navigation-timing-extended.https-expected.txt new file mode 100644 index 0000000..9cda153d --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac10.12/external/wpt/service-workers/service-worker/navigation-timing-extended.https-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL Service worker controlled navigation timing assert_greater_than: workerStart marking should not wait for worker activation to finish expected a number greater than 1634043231901 but got 1634043231899.8 +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac-mac10.12/virtual/plz-dedicated-worker/external/wpt/service-workers/service-worker/navigation-timing-extended.https-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/plz-dedicated-worker/external/wpt/service-workers/service-worker/navigation-timing-extended.https-expected.txt new file mode 100644 index 0000000..dc46c023 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac10.12/virtual/plz-dedicated-worker/external/wpt/service-workers/service-worker/navigation-timing-extended.https-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL Service worker controlled navigation timing assert_greater_than: workerStart marking should not wait for worker activation to finish expected a number greater than 1634042877263.6 but got 1634042877262.9 +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac-mac10.13/external/wpt/service-workers/service-worker/navigation-timing-extended.https-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.13/external/wpt/service-workers/service-worker/navigation-timing-extended.https-expected.txt new file mode 100644 index 0000000..2c799ac --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac10.13/external/wpt/service-workers/service-worker/navigation-timing-extended.https-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL Service worker controlled navigation timing assert_greater_than: workerStart marking should not wait for worker activation to finish expected a number greater than 1634043126416.2002 but got 1634043126415.5 +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac-mac10.13/virtual/plz-dedicated-worker/external/wpt/service-workers/service-worker/navigation-timing-extended.https-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.13/virtual/plz-dedicated-worker/external/wpt/service-workers/service-worker/navigation-timing-extended.https-expected.txt new file mode 100644 index 0000000..092c930 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac10.13/virtual/plz-dedicated-worker/external/wpt/service-workers/service-worker/navigation-timing-extended.https-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL Service worker controlled navigation timing assert_greater_than: workerStart marking should not wait for worker activation to finish expected a number greater than 1634042822263.3 but got 1634042822262.5999 +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac-mac10.14/external/wpt/service-workers/service-worker/navigation-timing-extended.https-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.14/external/wpt/service-workers/service-worker/navigation-timing-extended.https-expected.txt new file mode 100644 index 0000000..d4bcd6d5 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac10.14/external/wpt/service-workers/service-worker/navigation-timing-extended.https-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL Service worker controlled navigation timing assert_greater_than: workerStart marking should not wait for worker activation to finish expected a number greater than 1634043416168.2998 but got 1634043416167.4001 +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac-mac10.14/virtual/plz-dedicated-worker/external/wpt/service-workers/service-worker/navigation-timing-extended.https-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.14/virtual/plz-dedicated-worker/external/wpt/service-workers/service-worker/navigation-timing-extended.https-expected.txt new file mode 100644 index 0000000..f7bbaf1 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac10.14/virtual/plz-dedicated-worker/external/wpt/service-workers/service-worker/navigation-timing-extended.https-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL Service worker controlled navigation timing assert_greater_than: workerStart marking should not wait for worker activation to finish expected a number greater than 1634042744462.5 but got 1634042744461.8 +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac-mac10.15/external/wpt/service-workers/service-worker/navigation-timing-extended.https-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.15/external/wpt/service-workers/service-worker/navigation-timing-extended.https-expected.txt new file mode 100644 index 0000000..d6b1510 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac10.15/external/wpt/service-workers/service-worker/navigation-timing-extended.https-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL Service worker controlled navigation timing assert_greater_than: workerStart marking should not wait for worker activation to finish expected a number greater than 1634043667232.9 but got 1634043667232.2 +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac-mac10.15/virtual/plz-dedicated-worker/external/wpt/service-workers/service-worker/navigation-timing-extended.https-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.15/virtual/plz-dedicated-worker/external/wpt/service-workers/service-worker/navigation-timing-extended.https-expected.txt new file mode 100644 index 0000000..d5246e9 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac10.15/virtual/plz-dedicated-worker/external/wpt/service-workers/service-worker/navigation-timing-extended.https-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL Service worker controlled navigation timing assert_greater_than: workerStart marking should not wait for worker activation to finish expected a number greater than 1634043281629.2 but got 1634043281628.7002 +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/external/wpt/service-workers/service-worker/navigation-timing-extended.https-expected.txt b/third_party/blink/web_tests/platform/mac-mac11-arm64/external/wpt/service-workers/service-worker/navigation-timing-extended.https-expected.txt new file mode 100644 index 0000000..e4ff24ec --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac11-arm64/external/wpt/service-workers/service-worker/navigation-timing-extended.https-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL Service worker controlled navigation timing assert_greater_than: workerStart marking should not wait for worker activation to finish expected a number greater than 1634043925788.1 but got 1634043925788 +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac-mac11-arm64/virtual/plz-dedicated-worker/external/wpt/service-workers/service-worker/navigation-timing-extended.https-expected.txt b/third_party/blink/web_tests/platform/mac-mac11-arm64/virtual/plz-dedicated-worker/external/wpt/service-workers/service-worker/navigation-timing-extended.https-expected.txt new file mode 100644 index 0000000..f169810 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac-mac11-arm64/virtual/plz-dedicated-worker/external/wpt/service-workers/service-worker/navigation-timing-extended.https-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL Service worker controlled navigation timing assert_greater_than: workerStart marking should not wait for worker activation to finish expected a number greater than 1634043763019.1 but got 1634043763018.9 +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac/external/wpt/css/css-cascade/layer-font-face-override-expected.txt b/third_party/blink/web_tests/platform/mac/external/wpt/css/css-cascade/layer-font-face-override-expected.txt deleted file mode 100644 index 8d7e1ec..0000000 --- a/third_party/blink/web_tests/platform/mac/external/wpt/css/css-cascade/layer-font-face-override-expected.txt +++ /dev/null
@@ -1,7 +0,0 @@ -This is a testharness.js-based test. -FAIL @font-face unlayered overrides layered assert_equals: expected "80px" but got "38.5156px" -PASS @font-face override between layers -PASS @font-face override update with appended sheet 1 -PASS @font-face override update with appended sheet 2 -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/platform/mac/external/wpt/service-workers/service-worker/navigation-timing-extended.https-expected.txt b/third_party/blink/web_tests/platform/mac/external/wpt/service-workers/service-worker/navigation-timing-extended.https-expected.txt new file mode 100644 index 0000000..fcd4d8b --- /dev/null +++ b/third_party/blink/web_tests/platform/mac/external/wpt/service-workers/service-worker/navigation-timing-extended.https-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL Service worker controlled navigation timing assert_greater_than: workerStart marking should not wait for worker activation to finish expected a number greater than 1634043789619.9001 but got 1634043789618.7002 +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/mac/virtual/plz-dedicated-worker/external/wpt/service-workers/service-worker/navigation-timing-extended.https-expected.txt b/third_party/blink/web_tests/platform/mac/virtual/plz-dedicated-worker/external/wpt/service-workers/service-worker/navigation-timing-extended.https-expected.txt new file mode 100644 index 0000000..56be6f9 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac/virtual/plz-dedicated-worker/external/wpt/service-workers/service-worker/navigation-timing-extended.https-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL Service worker controlled navigation timing assert_greater_than: workerStart marking should not wait for worker activation to finish expected a number greater than 1634043753605.8 but got 1634043753605.0999 +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/win/external/wpt/css/css-cascade/layer-font-face-override-expected.txt b/third_party/blink/web_tests/platform/win/external/wpt/css/css-cascade/layer-font-face-override-expected.txt deleted file mode 100644 index 53dda9f..0000000 --- a/third_party/blink/web_tests/platform/win/external/wpt/css/css-cascade/layer-font-face-override-expected.txt +++ /dev/null
@@ -1,7 +0,0 @@ -This is a testharness.js-based test. -FAIL @font-face unlayered overrides layered assert_equals: expected "80px" but got "38px" -PASS @font-face override between layers -PASS @font-face override update with appended sheet 1 -PASS @font-face override update with appended sheet 2 -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/platform/win/external/wpt/service-workers/service-worker/navigation-timing-extended.https-expected.txt b/third_party/blink/web_tests/platform/win/external/wpt/service-workers/service-worker/navigation-timing-extended.https-expected.txt new file mode 100644 index 0000000..669bb6e0 --- /dev/null +++ b/third_party/blink/web_tests/platform/win/external/wpt/service-workers/service-worker/navigation-timing-extended.https-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL Service worker controlled navigation timing assert_greater_than: workerStart marking should not wait for worker activation to finish expected a number greater than 1634044893684.5999 but got 1634044893683.9001 +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/win/virtual/plz-dedicated-worker/external/wpt/service-workers/service-worker/navigation-timing-extended.https-expected.txt b/third_party/blink/web_tests/platform/win/virtual/plz-dedicated-worker/external/wpt/service-workers/service-worker/navigation-timing-extended.https-expected.txt new file mode 100644 index 0000000..2cd089c --- /dev/null +++ b/third_party/blink/web_tests/platform/win/virtual/plz-dedicated-worker/external/wpt/service-workers/service-worker/navigation-timing-extended.https-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL Service worker controlled navigation timing assert_greater_than: workerStart marking should not wait for worker activation to finish expected a number greater than 1634044522887.2998 but got 1634044522886.8 +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/win7/external/wpt/service-workers/service-worker/navigation-timing-extended.https-expected.txt b/third_party/blink/web_tests/platform/win7/external/wpt/service-workers/service-worker/navigation-timing-extended.https-expected.txt new file mode 100644 index 0000000..f8bae45b7 --- /dev/null +++ b/third_party/blink/web_tests/platform/win7/external/wpt/service-workers/service-worker/navigation-timing-extended.https-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL Service worker controlled navigation timing assert_greater_than: workerStart marking should not wait for worker activation to finish expected a number greater than 1634044577107.8 but got 1634044577107.5 +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/platform/win7/virtual/plz-dedicated-worker/external/wpt/service-workers/service-worker/navigation-timing-extended.https-expected.txt b/third_party/blink/web_tests/platform/win7/virtual/plz-dedicated-worker/external/wpt/service-workers/service-worker/navigation-timing-extended.https-expected.txt new file mode 100644 index 0000000..4c65b86 --- /dev/null +++ b/third_party/blink/web_tests/platform/win7/virtual/plz-dedicated-worker/external/wpt/service-workers/service-worker/navigation-timing-extended.https-expected.txt
@@ -0,0 +1,4 @@ +This is a testharness.js-based test. +FAIL Service worker controlled navigation timing assert_greater_than: workerStart marking should not wait for worker activation to finish expected a number greater than 1634044394837.3 but got 1634044394837 +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/virtual/disable-custom-element-default-style/external/wpt/css/css-cascade/README.txt b/third_party/blink/web_tests/virtual/disable-custom-element-default-style/external/wpt/css/css-cascade/README.txt new file mode 100644 index 0000000..1500620 --- /dev/null +++ b/third_party/blink/web_tests/virtual/disable-custom-element-default-style/external/wpt/css/css-cascade/README.txt
@@ -0,0 +1,2 @@ +This suite runs the wpt/css/css-cascade tests with flag +"disable-blink-features=CustomElementDefaultStyle".
diff --git a/third_party/blink/web_tests/virtual/stable/external/wpt/css/css-cascade/README.txt b/third_party/blink/web_tests/virtual/stable/external/wpt/css/css-cascade/README.txt deleted file mode 100644 index 1a9c2e4..0000000 --- a/third_party/blink/web_tests/virtual/stable/external/wpt/css/css-cascade/README.txt +++ /dev/null
@@ -1,2 +0,0 @@ -This suite runs the wpt/css/css-cascade tests without experimental web -platform features enabled.
diff --git a/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt b/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt index e6f91c5..986c961 100644 --- a/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt +++ b/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt
@@ -5250,6 +5250,7 @@ interface PerformanceEventTiming : PerformanceEntry attribute @@toStringTag getter cancelable + getter interactionId getter processingEnd getter processingStart getter target
diff --git a/third_party/ijar/BUILD.gn b/third_party/ijar/BUILD.gn index 9ad722f..99ede3a 100644 --- a/third_party/ijar/BUILD.gn +++ b/third_party/ijar/BUILD.gn
@@ -5,6 +5,12 @@ # A tool that removes all non-interface-specific parts from a .jar file. if (is_linux || is_chromeos) { + config("ijar_compiler_flags") { + if (is_clang) { + cflags = [ "-Wno-unused-but-set-variable" ] + } + } + executable("ijar") { sources = [ "classfile.cc", @@ -22,6 +28,8 @@ deps = [ "//third_party/zlib" ] + configs += [ ":ijar_compiler_flags" ] + # Always build release since this is a build tool. if (is_debug) { configs -= [ "//build/config:debug" ]
diff --git a/third_party/minizip/BUILD.gn b/third_party/minizip/BUILD.gn index 619b059..00fbcf4 100644 --- a/third_party/minizip/BUILD.gn +++ b/third_party/minizip/BUILD.gn
@@ -9,6 +9,7 @@ cflags = [ # mz_zip.c does |UINT_MAX == UINT16_MAX && ...|. "-Wno-unreachable-code", + "-Wno-unused-but-set-variable", "-Wno-unused-function", "-Wno-implicit-fallthrough", ]
diff --git a/third_party/tflite/BUILD.gn b/third_party/tflite/BUILD.gn index e9d0df2c1..a241181 100644 --- a/third_party/tflite/BUILD.gn +++ b/third_party/tflite/BUILD.gn
@@ -33,6 +33,7 @@ "-Wno-sign-compare", "-Wno-gnu-inline-cpp-without-extern", "-Wno-loop-analysis", + "-Wno-unused-but-set-variable", # TODO(thakis): Remove once # https://github.com/tensorflow/tensorflow/pull/50528 is rolled in.
diff --git a/third_party/zlib/BUILD.gn b/third_party/zlib/BUILD.gn index a3378e4..49f52e1f 100644 --- a/third_party/zlib/BUILD.gn +++ b/third_party/zlib/BUILD.gn
@@ -496,6 +496,9 @@ "//testing/gtest", ] + configs -= [ "//build/config/compiler:chromium_code" ] + configs += [ "//build/config/compiler:no_chromium_code" ] + include_dirs = [ "//third_party/googletest/src/googletest/include/gtest", ".",
diff --git a/tools/clang/pylib/clang/PRESUBMIT.py b/tools/clang/pylib/clang/PRESUBMIT.py index f7fea30..6315b5a 100644 --- a/tools/clang/pylib/clang/PRESUBMIT.py +++ b/tools/clang/pylib/clang/PRESUBMIT.py
@@ -10,7 +10,10 @@ results = [] # Run the unit tests. - results.extend(input_api.canned_checks.RunUnitTestsInDirectory( - input_api, output_api, '.', [ r'^.+_test\.py$'])) + results.extend( + input_api.canned_checks.RunUnitTestsInDirectory(input_api, + output_api, + '.', [r'^.+_test\.py$'], + skip_shebang_check=True)) return results
diff --git a/tools/find_runtime_symbols/PRESUBMIT.py b/tools/find_runtime_symbols/PRESUBMIT.py index 74b631d..01cb877 100644 --- a/tools/find_runtime_symbols/PRESUBMIT.py +++ b/tools/find_runtime_symbols/PRESUBMIT.py
@@ -32,7 +32,8 @@ input_api, output_api, input_api.os_path.join(input_api.PresubmitLocalPath(), 'tests'), - files_to_check=[r'.+_test\.py$'])) + files_to_check=[r'.+_test\.py$'], + skip_shebang_check=True)) if input_api.is_committing: output.extend(input_api.canned_checks.PanProjectChecks(input_api,
diff --git a/tools/find_runtime_symbols/tests/reduce_debugline_test.py b/tools/find_runtime_symbols/tests/reduce_debugline_test.py index 1e3a21a..a7f3e306 100755 --- a/tools/find_runtime_symbols/tests/reduce_debugline_test.py +++ b/tools/find_runtime_symbols/tests/reduce_debugline_test.py
@@ -3,13 +3,14 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import cStringIO import logging import os import sys import textwrap import unittest +from six import StringIO + ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) sys.path.insert(0, ROOT_DIR) @@ -55,7 +56,7 @@ def test(self): ranges_dict = reduce_debugline.reduce_decoded_debugline( - cStringIO.StringIO(self._DECODED_DEBUGLINE)) + StringIO(self._DECODED_DEBUGLINE)) self.assertEqual(self._EXPECTED_REDUCED_DEBUGLINE, ranges_dict)
diff --git a/tools/grit/PRESUBMIT.py b/tools/grit/PRESUBMIT.py index 54a8b3a..655929c5b 100644 --- a/tools/grit/PRESUBMIT.py +++ b/tools/grit/PRESUBMIT.py
@@ -20,7 +20,8 @@ input_api.os_path.join(input_api.PresubmitLocalPath(), 'preprocess_if_expr_test.py') ], - run_on_python2=False) + run_on_python2=False, + skip_shebang_check=True) def CheckChangeOnUpload(input_api, output_api):
diff --git a/tools/gritsettings/resource_ids.spec b/tools/gritsettings/resource_ids.spec index 4e80d8d..26a258b 100644 --- a/tools/gritsettings/resource_ids.spec +++ b/tools/gritsettings/resource_ids.spec
@@ -125,10 +125,6 @@ "META": {"sizes": {"includes": [10],}}, "includes": [1320], }, - "<(SHARED_INTERMEDIATE_DIR)/chrome/browser/resources/chromeos/enterprise_casting/resources.grd": { - "META": {"sizes": {"includes": [50]}}, - "includes": [1340], - }, "<(SHARED_INTERMEDIATE_DIR)/chrome/browser/resources/chromeos/emoji_picker/resources.grd": { "META": {"sizes": {"includes": [20]}}, "includes": [1360], @@ -170,6 +166,10 @@ "META": {"sizes": {"includes": [50],}}, "includes": [1580], }, + "<(SHARED_INTERMEDIATE_DIR)/chrome/browser/resources/enterprise_casting/resources.grd": { + "META": {"sizes": {"includes": [50]}}, + "includes": [1590], + }, "<(SHARED_INTERMEDIATE_DIR)/chrome/browser/resources/extensions/extensions_resources.grd": { "META": {"sizes": {"includes": [50],}}, "includes": [1600],
diff --git a/tools/linux/PRESUBMIT.py b/tools/linux/PRESUBMIT.py index bb47057..fb3e64e 100644 --- a/tools/linux/PRESUBMIT.py +++ b/tools/linux/PRESUBMIT.py
@@ -31,7 +31,8 @@ input_api, output_api, input_api.os_path.join(input_api.PresubmitLocalPath(), 'tests'), - files_to_check=[r'.+_tests\.py$'])) + files_to_check=[r'.+_tests\.py$'], + skip_shebang_check=True)) if input_api.is_committing: output.extend(input_api.canned_checks.PanProjectChecks(input_api,
diff --git a/tools/linux/tests/procfs_tests.py b/tools/linux/tests/procfs_tests.py index c829199..dd8ebc8 100755 --- a/tools/linux/tests/procfs_tests.py +++ b/tools/linux/tests/procfs_tests.py
@@ -3,12 +3,13 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import cStringIO import logging import os import sys import unittest +from six import StringIO + ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) sys.path.insert(0, ROOT_DIR) @@ -77,26 +78,26 @@ } def test_load(self): - maps = ProcMaps.load_file(cStringIO.StringIO(self._TEST_PROCMAPS)) + maps = ProcMaps.load_file(StringIO(self._TEST_PROCMAPS)) for index, entry in enumerate(maps): self.assertEqual(entry.as_dict(), self._expected_as_dict(index)) def test_constants(self): - maps = ProcMaps.load_file(cStringIO.StringIO(self._TEST_PROCMAPS)) + maps = ProcMaps.load_file(StringIO(self._TEST_PROCMAPS)) selected = [0, 2, 4, 7] for index, entry in enumerate(maps.iter(ProcMaps.constants)): self.assertEqual(entry.as_dict(), self._expected_as_dict(selected[index])) def test_executable(self): - maps = ProcMaps.load_file(cStringIO.StringIO(self._TEST_PROCMAPS)) + maps = ProcMaps.load_file(StringIO(self._TEST_PROCMAPS)) selected = [1, 3, 6, 9] for index, entry in enumerate(maps.iter(ProcMaps.executable)): self.assertEqual(entry.as_dict(), self._expected_as_dict(selected[index])) def test_executable_and_constants(self): - maps = ProcMaps.load_file(cStringIO.StringIO(self._TEST_PROCMAPS)) + maps = ProcMaps.load_file(StringIO(self._TEST_PROCMAPS)) selected = [0, 1, 2, 3, 4, 6, 7, 9] for index, entry in enumerate(maps.iter(ProcMaps.executable_and_constants)): self.assertEqual(entry.as_dict(),
diff --git a/tools/mb/PRESUBMIT.py b/tools/mb/PRESUBMIT.py index aa560e72..d3a1e45 100644 --- a/tools/mb/PRESUBMIT.py +++ b/tools/mb/PRESUBMIT.py
@@ -13,8 +13,12 @@ results.extend(input_api.RunTests(pylint_checks)) # Run the MB unittests. - results.extend(input_api.canned_checks.RunUnitTestsInDirectory( - input_api, output_api, '.', [ r'^.+_unittest\.py$'])) + results.extend( + input_api.canned_checks.RunUnitTestsInDirectory(input_api, + output_api, + '.', + [r'^.+_unittest\.py$'], + skip_shebang_check=True)) # Validate the format of the mb_config.pyl file. cmd = [input_api.python_executable, 'mb.py', 'validate']
diff --git a/tools/metrics/common/etree_util.py b/tools/metrics/common/etree_util.py index e8ff91a..b5be692 100644 --- a/tools/metrics/common/etree_util.py +++ b/tools/metrics/common/etree_util.py
@@ -69,7 +69,7 @@ first_tag_line = 0 first_tag_column = 0 try: - xml.sax.parseString(file_content, handler) + xml.sax.parseString(file_content.encode('utf-8'), handler) except _FirstTagFoundError: # This is the expected case, it means a tag was found in the doc. first_tag_line = handler.GetFirstTagLine() @@ -93,7 +93,7 @@ def ParseXMLString(raw_xml): """Parses raw_xml and returns an ElementTree node that includes comments.""" if sys.version_info.major == 2: - return ET.fromstring(raw_xml, _CommentedXMLParser()) + return ET.fromstring(raw_xml.encode('utf-8'), _CommentedXMLParser()) else: return ET.fromstring( raw_xml, ET.XMLParser(target=ET.TreeBuilder(insert_comments=True)))
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index 0ca17d5f..afd4a01 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -49663,6 +49663,7 @@ <int value="-714710496" label="VideoFullscreenOrientationLock:disabled"/> <int value="-714543772" label="enable-gpu-service-logging"/> <int value="-714043324" label="OutOfBlinkCORS:enabled"/> + <int value="-713705575" label="PhoneHubCallNotification:enabled"/> <int value="-713104676" label="DisablePeripheralDataAccessProtection:enabled"/> <int value="-711991950" label="SiteExplorationUi:enabled"/> @@ -50241,6 +50242,7 @@ <int value="-250822813" label="PwaImprovedSplashScreen:enabled"/> <int value="-250721831" label="AndroidAutofillAccessibility:disabled"/> <int value="-250543540" label="DeferAllScript:enabled"/> + <int value="-249443346" label="PhoneHubCallNotification:disabled"/> <int value="-249415830" label="FilteringScrollPrediction:disabled"/> <int value="-248223420" label="AutofillKeyboardAccessory:disabled"/> <int value="-247542772" label="CheckOfflineCapability:enabled"/> @@ -53165,6 +53167,8 @@ <int value="1991771852" label="LeftToRightUrls:enabled"/> <int value="1991912338" label="ModuleScriptsDynamicImport:enabled"/> <int value="1992466116" label="enable-passive-event-listeners-due-to-fling"/> + <int value="1993161713" + label="enable-experimental-accessibility-switch-access-multistep-automation"/> <int value="1993258379" label="enable-icon-ntp"/> <int value="1994431722" label="MaterialDesignUserMenu:disabled"/> <int value="1995322219" label="EmojiHandwritingVoiceInput:enabled"/> @@ -74842,6 +74846,9 @@ </enum> <enum name="ScheduledTaskInvokedReason"> + <obsolete> + Deprecated in M97. + </obsolete> <int value="0" label="Stopped"/> <int value="1" label="Rescheduled"/> <int value="2" label="Ready"/>
diff --git a/tools/metrics/histograms/merge_xml.py b/tools/metrics/histograms/merge_xml.py index ad8f2865..bd8b9188 100755 --- a/tools/metrics/histograms/merge_xml.py +++ b/tools/metrics/histograms/merge_xml.py
@@ -160,9 +160,9 @@ # doesn't build indexes for later lookup. And thus, we need to convert the # merged |doc| to a xml string and convert it back to force it to build # indexes for the merged |doc|. - doc = xml.dom.minidom.parseString(doc.toxml()) + doc = xml.dom.minidom.parseString(doc.toxml().encode('utf-8')) # Only perform fancy operations after |doc| becomes stable. This helps improve - # the runtime perforamnce. + # the runtime performance. if should_expand_owners: for histograms in doc.getElementsByTagName('histograms'): expand_owners.ExpandHistogramsOWNERS(histograms)
diff --git a/tools/metrics/histograms/metadata/history/histograms.xml b/tools/metrics/histograms/metadata/history/histograms.xml index e7c6bb3..f4ec421 100644 --- a/tools/metrics/histograms/metadata/history/histograms.xml +++ b/tools/metrics/histograms/metadata/history/histograms.xml
@@ -38,7 +38,7 @@ </histogram> <histogram name="History.BrowsingDataLifetime.Duration.BrowserShutdownDeletion" - units="ms" expires_after="2021-11-01"> + units="ms" expires_after="2022-10-01"> <owner>ydago@chromium.org</owner> <owner>dullweber@chromium.org</owner> <summary> @@ -49,7 +49,7 @@ <histogram name="History.BrowsingDataLifetime.Duration.Scheduled{DeletionType}Deletion" - units="ms" expires_after="2021-11-01"> + units="ms" expires_after="2022-10-01"> <owner>ydago@chromium.org</owner> <owner>dullweber@chromium.org</owner> <summary> @@ -64,7 +64,7 @@ </histogram> <histogram name="History.BrowsingDataLifetime.State.BrowserShutdownDeletion" - enum="BooleanStartedCompleted" expires_after="2021-11-01"> + enum="BooleanStartedCompleted" expires_after="2022-10-01"> <owner>ydago@chromium.org</owner> <owner>dullweber@chromium.org</owner> <summary>The states in which a deletion on shutdown went through.</summary> @@ -72,7 +72,7 @@ <histogram name="History.BrowsingDataLifetime.State.Scheduled{DeletionType}Deletion" - enum="BooleanStartedCompleted" expires_after="2021-11-01"> + enum="BooleanStartedCompleted" expires_after="2022-10-01"> <owner>ydago@chromium.org</owner> <owner>dullweber@chromium.org</owner> <summary>
diff --git a/tools/metrics/histograms/metadata/media/histograms.xml b/tools/metrics/histograms/metadata/media/histograms.xml index 4c9afaf..0857a4e 100644 --- a/tools/metrics/histograms/metadata/media/histograms.xml +++ b/tools/metrics/histograms/metadata/media/histograms.xml
@@ -514,7 +514,7 @@ </histogram> <histogram name="Media.Audio.Capture.Win.{AudioProcessingMode}EffectType" - enum="AudioEffectType" expires_after="2021-10-22"> + enum="AudioEffectType" expires_after="2022-10-22"> <owner>henrika@chromium.org</owner> <owner>media-dev@chromium.org</owner> <summary>
diff --git a/tools/metrics/histograms/metadata/oobe/histograms.xml b/tools/metrics/histograms/metadata/oobe/histograms.xml index 03578c5..c9fcc95 100644 --- a/tools/metrics/histograms/metadata/oobe/histograms.xml +++ b/tools/metrics/histograms/metadata/oobe/histograms.xml
@@ -468,6 +468,9 @@ <histogram name="OOBE.WebUIToViewsSwitch.Duration" units="ms" expires_after="2021-11-21"> + <obsolete> + Removed in M97. + </obsolete> <owner>rsorokin@chromium.org</owner> <owner>cros-oac@google.com</owner> <summary>
diff --git a/tools/metrics/histograms/metadata/others/histograms.xml b/tools/metrics/histograms/metadata/others/histograms.xml index b11b3d6..9a650f6 100644 --- a/tools/metrics/histograms/metadata/others/histograms.xml +++ b/tools/metrics/histograms/metadata/others/histograms.xml
@@ -17104,7 +17104,7 @@ </histogram> <histogram name="SupervisedUsers.PerAppTimeLimits.AppsWithTimeLimit" - units="Apps" expires_after="2022-04-24"> + units="Apps" expires_after="2022-10-11"> <owner>agawronska@chromium.org</owner> <owner>yilkal@chromium.org</owner> <owner>cros-families@google.com</owner> @@ -17115,7 +17115,7 @@ </histogram> <histogram name="SupervisedUsers.PerAppTimeLimits.BlockedAppsCount" - units="Apps" expires_after="2022-01-16"> + units="Apps" expires_after="2022-10-11"> <owner>agawronska@chromium.org</owner> <owner>yilkal@chromium.org</owner> <owner>cros-families@google.com</owner> @@ -17126,7 +17126,7 @@ </histogram> <histogram name="SupervisedUsers.PerAppTimeLimits.Engagement" units="Apps" - expires_after="2022-04-24"> + expires_after="2022-10-11"> <owner>agawronska@chromium.org</owner> <owner>yilkal@chromium.org</owner> <owner>cros-families@google.com</owner> @@ -17138,7 +17138,7 @@ </histogram> <histogram name="SupervisedUsers.PerAppTimeLimits.PolicyChangeCount" - units="Changes" expires_after="2021-11-21"> + units="Changes" expires_after="2022-10-11"> <owner>agawronska@chromium.org</owner> <owner>yilkal@chromium.org</owner> <owner>cros-families@google.com</owner> @@ -19081,6 +19081,36 @@ </summary> </histogram> +<histogram name="Viz.FileDescriptorTracking.TimeToCompute" units="microseconds" + expires_after="2022-01-09"> + <owner>petermcneeley@chromium.org</owner> + <owner>rjkroege@chromium.org</owner> + <summary> + Time spent computing the number of active File Descriptors. This is logged + once every 5 minutes as the cost of this computation is estimated to be at + least 1ms. Currently only recorded for LaCros delegated compositing. + + Warning: This metric does not include reports from clients with + low-resolution clocks. + </summary> +</histogram> + +<histogram name="Viz.FileDescriptorTracking.{FdStat}" units="units" + expires_after="2022-01-09"> + <owner>petermcneeley@chromium.org</owner> + <owner>rjkroege@chromium.org</owner> + <summary> + {FdStat} File Descriptors for the GPU process. This is logged once every 5 + minutes as the cost of this computation is estimated to be at least 1ms. + Currently only recorded for LaCros delegated compositing. + </summary> + <token key="FdStat"> + <variant name="NumActive" summary="Current number of active"/> + <variant name="NumSoftMax" summary="Maximum number of"/> + <variant name="PercentageUsed" summary="Percentage of in use"/> + </token> +</histogram> + <histogram name="Viz.FrameSinkVideoCapturer.I420.CaptureDuration" units="ms" expires_after="2021-03-07"> <owner>samans@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/password/histograms.xml b/tools/metrics/histograms/metadata/password/histograms.xml index 579657e..b511398 100644 --- a/tools/metrics/histograms/metadata/password/histograms.xml +++ b/tools/metrics/histograms/metadata/password/histograms.xml
@@ -2979,6 +2979,25 @@ </summary> </histogram> +<histogram name="PasswordProtection.{TriggerType}.UserPopulation{Moment}" + enum="SafeBrowsingUserPopulation" expires_after="M98"> + <owner>drubery@chromium.org</owner> + <owner>chrome-safebrowsing-core@chromium.org</owner> + <summary> + Records the user population for the profile triggering a password protection + check, due to {TriggerType}, {Moment}. + </summary> + <token key="TriggerType"> + <variant name="OnFocus" summary="focusing on an unfamiliar login page"/> + <variant name="PasswordEntry" + summary="entering a password on the wrong login page"/> + </token> + <token key="Moment"> + <variant name="OnPing" summary="when we decide to contact Safe Browsing"/> + <variant name="Start" summary="when the check is triggered"/> + </token> +</histogram> + </histograms> </histogram-configuration>
diff --git a/tools/metrics/histograms/metadata/renderer/histograms.xml b/tools/metrics/histograms/metadata/renderer/histograms.xml index f9baa9cc..205d4ee 100644 --- a/tools/metrics/histograms/metadata/renderer/histograms.xml +++ b/tools/metrics/histograms/metadata/renderer/histograms.xml
@@ -51,7 +51,7 @@ <histogram name="Renderer.DelegatedInkTrail.LatencyImprovement.{Renderer}.{Prediction}" - units="ms" expires_after="M98"> + units="ms" expires_after="M108"> <owner>jonross@chromium.org</owner> <owner>joalmei@microsoft.com</owner> <summary> @@ -73,7 +73,7 @@ <histogram name="Renderer.DelegatedInkTrail.LatencyImprovementWithPrediction.Experiment{Number}" - units="ms" expires_after="M98"> + units="ms" expires_after="M108"> <owner>jonross@chromium.org</owner> <owner>joalmei@microsoft.com</owner> <summary> @@ -94,7 +94,7 @@ </histogram> <histogram name="Renderer.DelegatedInkTrail.Prediction.WrongDirection" - enum="BooleanDirection" expires_after="M98"> + enum="BooleanDirection" expires_after="M108"> <owner>jonross@chromium.org</owner> <owner>joalmei@microsoft.com</owner> <summary> @@ -109,7 +109,7 @@ </histogram> <histogram name="Renderer.DelegatedInkTrail.Prediction.{Direction}Prediction" - units="pixels" expires_after="M98"> + units="pixels" expires_after="M108"> <owner>jonross@chromium.org</owner> <owner>joalmei@microsoft.com</owner> <summary> @@ -127,7 +127,7 @@ </histogram> <histogram name="Renderer.DelegatedInkTrail.Prediction.{Type}Jitter" - units="pixels" expires_after="M98"> + units="pixels" expires_after="M108"> <owner>jonross@chromium.org</owner> <owner>joalmei@microsoft.com</owner> <summary> @@ -148,7 +148,7 @@ <histogram name="Renderer.DelegatedInkTrail.PredictionExperiment{Number}.Frame{ScoreType}" - units="pixels" expires_after="M98"> + units="pixels" expires_after="M108"> <owner>jonross@chromium.org</owner> <owner>joalmei@microsoft.com</owner> <summary> @@ -176,7 +176,7 @@ <histogram name="Renderer.DelegatedInkTrail.PredictionExperiment{Number}.WrongDirection" - enum="BooleanDirection" expires_after="M98"> + enum="BooleanDirection" expires_after="M108"> <owner>jonross@chromium.org</owner> <owner>joalmei@microsoft.com</owner> <summary> @@ -196,7 +196,7 @@ <histogram name="Renderer.DelegatedInkTrail.PredictionExperiment{Number}.{ScoreType}" - units="pixels" expires_after="M98"> + units="pixels" expires_after="M108"> <owner>jonross@chromium.org</owner> <owner>joalmei@microsoft.com</owner> <summary> @@ -221,7 +221,7 @@ <histogram name="Renderer.DelegatedInkTrail.PredictionExperiment{Number}.{Type}Jitter" - units="pixels" expires_after="M98"> + units="pixels" expires_after="M108"> <owner>jonross@chromium.org</owner> <owner>joalmei@microsoft.com</owner> <summary>
diff --git a/tools/metrics/histograms/metadata/scheduler/histograms.xml b/tools/metrics/histograms/metadata/scheduler/histograms.xml index 55dcb1d..5582878d 100644 --- a/tools/metrics/histograms/metadata/scheduler/histograms.xml +++ b/tools/metrics/histograms/metadata/scheduler/histograms.xml
@@ -139,6 +139,9 @@ <histogram name="Scheduler.TimerBase.ScheduledTaskInvokedReason" enum="ScheduledTaskInvokedReason" expires_after="M95"> + <obsolete> + Deprecated in M97. + </obsolete> <owner>pmonette@chromium.org</owner> <owner>chrome-catan@google.com</owner> <summary>
diff --git a/tools/origin_trials/generate_token.py b/tools/origin_trials/generate_token.py index 6e49fbf..4f932f3 100755 --- a/tools/origin_trials/generate_token.py +++ b/tools/origin_trials/generate_token.py
@@ -28,7 +28,12 @@ import struct import sys import time -import urlparse + +try: + from urllib.parse import urlparse +except ImportError: + # ToDo: Remove Exception case upon full migration to Python 3 + from urlparse import urlparse script_dir = os.path.dirname(os.path.realpath(__file__)) sys.path.insert(0, os.path.join(script_dir, 'third_party', 'ed25519')) @@ -87,7 +92,7 @@ if hostname: return "https://" + hostname + ":443" # If not, try to construct an origin URL from the argument - origin = urlparse.urlparse(arg) + origin = urlparse(arg) if not origin or not origin.scheme or not origin.netloc: raise argparse.ArgumentTypeError("%s is not a hostname or a URL" % arg) # HTTPS or HTTP only @@ -242,7 +247,7 @@ # Verify that that the signature is correct before printing it. try: ed25519.checkvalid(signature, data_to_sign, private_key[32:]) - except Exception, exc: + except Exception as exc: print("There was an error generating the signature.") print("(The original error was: %s)" % exc) sys.exit(1)
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json index eb5f0ab..357aa4f 100644 --- a/tools/perf/core/perfetto_binary_roller/binary_deps.json +++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -5,12 +5,12 @@ "remote_path": "perfetto_binaries/trace_processor_shell/linux_arm/49b4b5dcbc312d8d2c3751cf29238b8efeb4e494/trace_processor_shell" }, "win": { - "hash": "52f421824816597171d49ad99769576b6eb8c1e8", - "remote_path": "perfetto_binaries/trace_processor_shell/win/9709a3d80cc9e2ac3e6d808638334f7510ddc59a/trace_processor_shell.exe" + "hash": "0c618e76ac4cfb99a59e915f8e9f714e5f321744", + "remote_path": "perfetto_binaries/trace_processor_shell/win/251c5dd034fdc7ce2578f2b5fd112e2fc0fa0e8e/trace_processor_shell.exe" }, "mac": { "hash": "c23e575ca7971342be4b254789513a3d9e75e19f", - "remote_path": "perfetto_binaries/trace_processor_shell/mac/a380238d9c232c8be236d141d0c81ca358a2597e/trace_processor_shell" + "remote_path": "perfetto_binaries/trace_processor_shell/mac/9709a3d80cc9e2ac3e6d808638334f7510ddc59a/trace_processor_shell" }, "linux_arm64": { "hash": "5074025a2898ec41a872e70a5719e417acb0a380", @@ -18,7 +18,7 @@ }, "linux": { "hash": "8edbb2d758502c92df982ea5aac42e7db953b4f0", - "remote_path": "perfetto_binaries/trace_processor_shell/linux/9709a3d80cc9e2ac3e6d808638334f7510ddc59a/trace_processor_shell" + "remote_path": "perfetto_binaries/trace_processor_shell/linux/251c5dd034fdc7ce2578f2b5fd112e2fc0fa0e8e/trace_processor_shell" } }, "power_profile.sql": {
diff --git a/tools/polymer/PRESUBMIT.py b/tools/polymer/PRESUBMIT.py index 530a3adb..251e609 100644 --- a/tools/polymer/PRESUBMIT.py +++ b/tools/polymer/PRESUBMIT.py
@@ -15,7 +15,10 @@ presubmit_path = input_api.PresubmitLocalPath() sources = ['polymer_test.py'] tests = [input_api.os_path.join(presubmit_path, s) for s in sources] - return input_api.canned_checks.RunUnitTests(input_api, output_api, tests) + return input_api.canned_checks.RunUnitTests(input_api, + output_api, + tests, + skip_shebang_check=True) def _CheckChangeOnUploadOrCommit(input_api, output_api):
diff --git a/tools/resources/PRESUBMIT.py b/tools/resources/PRESUBMIT.py index 1f71cc8..12fccbe 100644 --- a/tools/resources/PRESUBMIT.py +++ b/tools/resources/PRESUBMIT.py
@@ -20,6 +20,9 @@ if any(f for f in files if f.startswith('svgo_presubmit')): tests = [path.join(cwd, 'svgo_presubmit_test.py')] - return input_api.canned_checks.RunUnitTests(input_api, output_api, tests) + return input_api.canned_checks.RunUnitTests(input_api, + output_api, + tests, + skip_shebang_check=True) return []
diff --git a/tools/typescript/PRESUBMIT.py b/tools/typescript/PRESUBMIT.py index 9a080c3..05046d6 100644 --- a/tools/typescript/PRESUBMIT.py +++ b/tools/typescript/PRESUBMIT.py
@@ -14,7 +14,10 @@ presubmit_path = input_api.PresubmitLocalPath() sources = ['ts_library_test.py'] tests = [input_api.os_path.join(presubmit_path, s) for s in sources] - return input_api.canned_checks.RunUnitTests(input_api, output_api, tests) + return input_api.canned_checks.RunUnitTests(input_api, + output_api, + tests, + skip_shebang_check=True) def _CheckChangeOnUploadOrCommit(input_api, output_api):
diff --git a/ui/accessibility/accessibility_switches.cc b/ui/accessibility/accessibility_switches.cc index fbcbad2..734765a 100644 --- a/ui/accessibility/accessibility_switches.cc +++ b/ui/accessibility/accessibility_switches.cc
@@ -41,6 +41,11 @@ // zooming in. const char kEnableMagnifierDebugDrawRect[] = "enable-magnifier-debug-draw-rect"; +// Enables multistep automation for Switch Access, which is a 2021 accessibility +// sprint project and hasn't launched yet. +const char kEnableExperimentalAccessibilitySwitchAccessMultistepAutomation[] = + "enable-experimental-accessibility-switch-access-multistep-automation"; + bool IsExperimentalAccessibilityDictationExtensionEnabled() { return base::CommandLine::ForCurrentProcess()->HasSwitch( ::switches::kEnableExperimentalAccessibilityDictationExtension); @@ -66,6 +71,12 @@ ::switches::kEnableMagnifierDebugDrawRect); } +bool IsExperimentalAccessibilitySwitchAccessMultistepAutomationEnabled() { + return base::CommandLine::ForCurrentProcess()->HasSwitch( + ::switches:: + kEnableExperimentalAccessibilitySwitchAccessMultistepAutomation); +} + #if defined(OS_WIN) // Enables UI Automation platform API in addition to the IAccessible API. const char kEnableExperimentalUIAutomation[] =
diff --git a/ui/accessibility/accessibility_switches.h b/ui/accessibility/accessibility_switches.h index 5547b03e..1ad17812 100644 --- a/ui/accessibility/accessibility_switches.h +++ b/ui/accessibility/accessibility_switches.h
@@ -22,6 +22,8 @@ kEnableExperimentalAccessibilityLanguageDetectionDynamic[]; AX_BASE_EXPORT extern const char kEnableExperimentalAccessibilitySwitchAccessText[]; +AX_BASE_EXPORT extern const char + kEnableExperimentalAccessibilitySwitchAccessMultistepAutomation[]; // Returns true if experimental accessibility dictation extension is enabled. AX_BASE_EXPORT bool IsExperimentalAccessibilityDictationExtensionEnabled(); @@ -37,6 +39,11 @@ // Returns true if experimental accessibility Switch Access text is enabled. AX_BASE_EXPORT bool IsExperimentalAccessibilitySwitchAccessTextEnabled(); +// Returns true if experimental accessibility Switch Access multistep automation +// is enabled. +AX_BASE_EXPORT bool +IsExperimentalAccessibilitySwitchAccessMultistepAutomationEnabled(); + #if defined(OS_WIN) AX_BASE_EXPORT extern const char kEnableExperimentalUIAutomation[]; #endif
diff --git a/ui/display/mac/display_link_mac.cc b/ui/display/mac/display_link_mac.cc index b517816..d106bc4 100644 --- a/ui/display/mac/display_link_mac.cc +++ b/ui/display/mac/display_link_mac.cc
@@ -82,7 +82,25 @@ ret = CVDisplayLinkCreateWithCGDisplay(display_id, display_link.InitializeInto()); if (ret != kCVReturnSuccess) { - LOG(ERROR) << "CVDisplayLinkCreateWithActiveCGDisplays failed: " << ret; + LOG(ERROR) << "CVDisplayLinkCreateWithCGDisplay failed: " << ret; + return nullptr; + } + + // Workaround for bug https://crbug.com/1218720. According to + // https://hg.mozilla.org/releases/mozilla-esr68/rev/db0628eadb86, + // CVDisplayLinkCreateWithCGDisplays() + // (called by CVDisplayLinkCreateWithCGDisplay()) sometimes + // creates a CVDisplayLinkRef with an uninitialized (nulled) internal + // pointer. If we continue to use this CVDisplayLinkRef, we will + // eventually crash in CVCGDisplayLink::getDisplayTimes(), where the + // internal pointer is dereferenced. Fortunately, when this happens + // another internal variable is also left uninitialized (zeroed), + // which is accessible via CVDisplayLinkGetCurrentCGDisplay(). In + // normal conditions the current display is never zero. + if ((ret == kCVReturnSuccess) && + (CVDisplayLinkGetCurrentCGDisplay(display_link) == 0)) { + LOG(ERROR) + << "CVDisplayLinkCreateWithCGDisplay failed (no current display)"; return nullptr; }
diff --git a/ui/ozone/platform/wayland/host/wayland_screen.cc b/ui/ozone/platform/wayland/host/wayland_screen.cc index bac7711..c998095 100644 --- a/ui/ozone/platform/wayland/host/wayland_screen.cc +++ b/ui/ozone/platform/wayland/host/wayland_screen.cc
@@ -234,7 +234,8 @@ // the last known cursor position. Otherwise, return such a point, which is // not contained by any of the windows. auto* cursor_position = connection_->wayland_cursor_position(); - if (connection_->wayland_window_manager()->GetCurrentFocusedWindow() && + if (connection_->wayland_window_manager() + ->GetCurrentPointerOrTouchFocusedWindow() && cursor_position) return cursor_position->GetCursorSurfacePoint(); @@ -249,8 +250,8 @@ const gfx::Point& point) const { // It is safe to check only for focused windows and test if they contain the // point or not. - auto* window = - connection_->wayland_window_manager()->GetCurrentFocusedWindow(); + auto* window = connection_->wayland_window_manager() + ->GetCurrentPointerOrTouchFocusedWindow(); if (window && window->GetBoundsInDIP().Contains(point)) return window->GetWidget(); return gfx::kNullAcceleratedWidget;
diff --git a/ui/ozone/platform/wayland/host/wayland_window_drag_controller.cc b/ui/ozone/platform/wayland/host/wayland_window_drag_controller.cc index ef4f090..13e208e 100644 --- a/ui/ozone/platform/wayland/host/wayland_window_drag_controller.cc +++ b/ui/ozone/platform/wayland/host/wayland_window_drag_controller.cc
@@ -102,7 +102,7 @@ if (state_ != State::kIdle) return true; - origin_window_ = window_manager_->GetCurrentFocusedWindow(); + origin_window_ = window_manager_->GetCurrentPointerOrTouchFocusedWindow(); if (!origin_window_) { LOG(ERROR) << "Failed to get origin window."; return false; @@ -175,7 +175,8 @@ // snapped into a tab strip. So switch to |kAttached| state, store the focused // window as the pointer grabber and ask to quit the nested loop. state_ = State::kAttaching; - pointer_grab_owner_ = window_manager_->GetCurrentFocusedWindow(); + pointer_grab_owner_ = + window_manager_->GetCurrentPointerOrTouchFocusedWindow(); DCHECK(pointer_grab_owner_); QuitLoop(); }
diff --git a/ui/ozone/platform/wayland/host/wayland_window_drag_controller_unittest.cc b/ui/ozone/platform/wayland/host/wayland_window_drag_controller_unittest.cc index 28d84dd..efa9bf9 100644 --- a/ui/ozone/platform/wayland/host/wayland_window_drag_controller_unittest.cc +++ b/ui/ozone/platform/wayland/host/wayland_window_drag_controller_unittest.cc
@@ -71,7 +71,8 @@ EXPECT_CALL(*delegate, DispatchEvent(_)).Times(1); WaylandDragDropTest::SendPointerEnter(window, delegate); Sync(); - EXPECT_EQ(window, window_manager()->GetCurrentFocusedWindow()); + EXPECT_EQ(window, + window_manager()->GetCurrentPointerOrTouchFocusedWindow()); } void SendPointerLeave(WaylandWindow* window, @@ -79,7 +80,8 @@ EXPECT_CALL(*delegate, DispatchEvent(_)).Times(1); WaylandDragDropTest::SendPointerLeave(window, delegate); Sync(); - EXPECT_EQ(nullptr, window_manager()->GetCurrentFocusedWindow()); + EXPECT_EQ(nullptr, + window_manager()->GetCurrentPointerOrTouchFocusedWindow()); } void SendPointerPress(WaylandWindow* window, @@ -90,7 +92,8 @@ EXPECT_CALL(*delegate, DispatchEvent(_)).Times(1); Sync(); - EXPECT_EQ(window, window_manager()->GetCurrentFocusedWindow()); + EXPECT_EQ(window, + window_manager()->GetCurrentPointerOrTouchFocusedWindow()); } void SendPointerMotion(WaylandWindow* window, @@ -129,7 +132,8 @@ EXPECT_CALL(*delegate, DispatchEvent(_)).Times(1); Sync(); - EXPECT_EQ(window, window_manager()->GetCurrentFocusedWindow()); + EXPECT_EQ(window, + window_manager()->GetCurrentPointerOrTouchFocusedWindow()); } void SendTouchMotion(WaylandWindow* window, MockPlatformWindowDelegate* delegate, @@ -154,7 +158,7 @@ // 3. Run move loop, drag it within the window bounds and drop. TEST_P(WaylandWindowDragControllerTest, DragInsideWindowAndDrop) { // Ensure there is no window currently focused - EXPECT_FALSE(window_manager()->GetCurrentFocusedWindow()); + EXPECT_FALSE(window_manager()->GetCurrentPointerOrTouchFocusedWindow()); EXPECT_EQ(gfx::kNullAcceleratedWidget, screen_->GetLocalProcessWidgetAtPoint({10, 10}, {})); @@ -230,7 +234,8 @@ Sync(); EXPECT_EQ(State::kIdle, drag_controller()->state()); - EXPECT_EQ(window_.get(), window_manager()->GetCurrentFocusedWindow()); + EXPECT_EQ(window_.get(), + window_manager()->GetCurrentPointerOrTouchFocusedWindow()); EXPECT_EQ(window_->GetWidget(), screen_->GetLocalProcessWidgetAtPoint({20, 20}, {})); } @@ -244,7 +249,7 @@ ASSERT_TRUE(GetWaylandExtension(*window_)); // Ensure there is no window currently focused - EXPECT_FALSE(window_manager()->GetCurrentFocusedWindow()); + EXPECT_FALSE(window_manager()->GetCurrentPointerOrTouchFocusedWindow()); EXPECT_EQ(gfx::kNullAcceleratedWidget, screen_->GetLocalProcessWidgetAtPoint({10, 10}, {})); @@ -310,7 +315,8 @@ Sync(); EXPECT_EQ(State::kIdle, drag_controller()->state()); - EXPECT_EQ(window_.get(), window_manager()->GetCurrentFocusedWindow()); + EXPECT_EQ(window_.get(), + window_manager()->GetCurrentPointerOrTouchFocusedWindow()); EXPECT_EQ(window_->GetWidget(), screen_->GetLocalProcessWidgetAtPoint({20, 20}, {})); } @@ -324,7 +330,7 @@ // happens outside the bounds of any surface. TEST_P(WaylandWindowDragControllerTest, DragExitWindowAndDrop) { // Ensure there is no window currently focused - EXPECT_FALSE(window_manager()->GetCurrentFocusedWindow()); + EXPECT_FALSE(window_manager()->GetCurrentPointerOrTouchFocusedWindow()); EXPECT_EQ(gfx::kNullAcceleratedWidget, screen_->GetLocalProcessWidgetAtPoint({10, 10}, {})); @@ -400,7 +406,8 @@ Sync(); EXPECT_EQ(State::kIdle, drag_controller()->state()); - EXPECT_EQ(window_.get(), window_manager()->GetCurrentFocusedWindow()); + EXPECT_EQ(window_.get(), + window_manager()->GetCurrentPointerOrTouchFocusedWindow()); EXPECT_EQ(window_->GetWidget(), screen_->GetLocalProcessWidgetAtPoint({20, 20}, {})); } @@ -424,7 +431,7 @@ Sync(); // Ensure there is no window currently focused - EXPECT_FALSE(window_manager()->GetCurrentFocusedWindow()); + EXPECT_FALSE(window_manager()->GetCurrentPointerOrTouchFocusedWindow()); EXPECT_EQ(gfx::kNullAcceleratedWidget, screen_->GetLocalProcessWidgetAtPoint({10, 10}, {})); @@ -538,7 +545,8 @@ case kSnapped: EXPECT_EQ(ET_MOUSE_RELEASED, event->type()); EXPECT_EQ(State::kDropped, drag_controller()->state()); - EXPECT_EQ(target_window, window_manager()->GetCurrentFocusedWindow()); + EXPECT_EQ(target_window, + window_manager()->GetCurrentPointerOrTouchFocusedWindow()); test_step = kDone; break; default: @@ -550,7 +558,8 @@ Sync(); SendPointerEnter(target_window, &delegate_); - EXPECT_EQ(target_window, window_manager()->GetCurrentFocusedWindow()); + EXPECT_EQ(target_window, + window_manager()->GetCurrentPointerOrTouchFocusedWindow()); EXPECT_EQ(target_window->GetWidget(), screen_->GetLocalProcessWidgetAtPoint({20, 20}, {})); } @@ -574,7 +583,7 @@ Sync(); // Ensure there is no window currently focused - EXPECT_FALSE(window_manager()->GetCurrentFocusedWindow()); + EXPECT_FALSE(window_manager()->GetCurrentPointerOrTouchFocusedWindow()); EXPECT_EQ(gfx::kNullAcceleratedWidget, screen_->GetLocalProcessWidgetAtPoint({10, 10}, {})); @@ -660,7 +669,8 @@ case kSnapped: EXPECT_EQ(ET_TOUCH_RELEASED, event->type()); EXPECT_EQ(State::kDropped, drag_controller()->state()); - EXPECT_EQ(target_window, window_manager()->GetCurrentFocusedWindow()); + EXPECT_EQ(target_window, + window_manager()->GetCurrentPointerOrTouchFocusedWindow()); test_step = kDone; break; default: @@ -689,14 +699,14 @@ ScheduleTestTask(task_2); base::RunLoop().RunUntilIdle(); - EXPECT_FALSE(window_manager()->GetCurrentFocusedWindow()); + EXPECT_FALSE(window_manager()->GetCurrentPointerOrTouchFocusedWindow()); } // Verifies wl_data_device::leave events are properly handled and propagated // while in window dragging "attached" mode. TEST_P(WaylandWindowDragControllerTest, DragExitAttached) { // Ensure there is no window currently focused - EXPECT_FALSE(window_manager()->GetCurrentFocusedWindow()); + EXPECT_FALSE(window_manager()->GetCurrentPointerOrTouchFocusedWindow()); EXPECT_EQ(gfx::kNullAcceleratedWidget, screen_->GetLocalProcessWidgetAtPoint({10, 10}, {})); @@ -735,7 +745,8 @@ SendPointerEnter(window_.get(), &delegate_); Sync(); - EXPECT_EQ(window_.get(), window_manager()->GetCurrentFocusedWindow()); + EXPECT_EQ(window_.get(), + window_manager()->GetCurrentPointerOrTouchFocusedWindow()); EXPECT_EQ(window_->GetWidget(), screen_->GetLocalProcessWidgetAtPoint({20, 20}, {})); } @@ -785,7 +796,7 @@ // https://crbug.com/1148021. TEST_P(WaylandWindowDragControllerTest, IgnorePointerEventsUntilDrop) { // Ensure there is no window currently focused - EXPECT_FALSE(window_manager()->GetCurrentFocusedWindow()); + EXPECT_FALSE(window_manager()->GetCurrentPointerOrTouchFocusedWindow()); EXPECT_EQ(gfx::kNullAcceleratedWidget, screen_->GetLocalProcessWidgetAtPoint({200, 200}, {})); @@ -874,7 +885,8 @@ Sync(); EXPECT_EQ(State::kIdle, drag_controller()->state()); - EXPECT_EQ(window_.get(), window_manager()->GetCurrentFocusedWindow()); + EXPECT_EQ(window_.get(), + window_manager()->GetCurrentPointerOrTouchFocusedWindow()); EXPECT_EQ(window_->GetWidget(), screen_->GetLocalProcessWidgetAtPoint({100, 100}, {})); EXPECT_EQ(gfx::kNullAcceleratedWidget,
diff --git a/ui/ozone/platform/wayland/host/wayland_window_manager.cc b/ui/ozone/platform/wayland/host/wayland_window_manager.cc index f6dfec8..5d7d32d 100644 --- a/ui/ozone/platform/wayland/host/wayland_window_manager.cc +++ b/ui/ozone/platform/wayland/host/wayland_window_manager.cc
@@ -67,6 +67,17 @@ WaylandWindow* WaylandWindowManager::GetCurrentFocusedWindow() const { for (const auto& entry : window_map_) { WaylandWindow* window = entry.second; + if (window->has_pointer_focus() || window->has_touch_focus() || + window->has_keyboard_focus()) + return window; + } + return nullptr; +} + +WaylandWindow* WaylandWindowManager::GetCurrentPointerOrTouchFocusedWindow() + const { + for (const auto& entry : window_map_) { + WaylandWindow* window = entry.second; if (window->has_pointer_focus() || window->has_touch_focus()) return window; }
diff --git a/ui/ozone/platform/wayland/host/wayland_window_manager.h b/ui/ozone/platform/wayland/host/wayland_window_manager.h index 0c880e3..8908d1d 100644 --- a/ui/ozone/platform/wayland/host/wayland_window_manager.h +++ b/ui/ozone/platform/wayland/host/wayland_window_manager.h
@@ -51,9 +51,12 @@ // Returns a window with largests bounds. WaylandWindow* GetWindowWithLargestBounds() const; - // Returns a current focused window by pointer or touch. + // Returns a current focused window by pointer, touch, or keyboard. WaylandWindow* GetCurrentFocusedWindow() const; + // Returns a current focused window by pointer or touch. + WaylandWindow* GetCurrentPointerOrTouchFocusedWindow() const; + // Returns a current focused window by pointer. WaylandWindow* GetCurrentPointerFocusedWindow() const;
diff --git a/ui/ozone/platform/wayland/host/wayland_window_manager_unittests.cc b/ui/ozone/platform/wayland/host/wayland_window_manager_unittests.cc index b262d31..0e8af0f 100644 --- a/ui/ozone/platform/wayland/host/wayland_window_manager_unittests.cc +++ b/ui/ozone/platform/wayland/host/wayland_window_manager_unittests.cc
@@ -99,6 +99,7 @@ Sync(); EXPECT_FALSE(manager_->GetCurrentFocusedWindow()); + EXPECT_FALSE(manager_->GetCurrentPointerOrTouchFocusedWindow()); EXPECT_FALSE(manager_->GetCurrentPointerFocusedWindow()); auto* pointer = server_.seat()->pointer(); @@ -112,6 +113,8 @@ EXPECT_FALSE(manager_->GetCurrentKeyboardFocusedWindow()); EXPECT_TRUE(window1.get() == manager_->GetCurrentFocusedWindow()); + EXPECT_TRUE(window1.get() == + manager_->GetCurrentPointerOrTouchFocusedWindow()); EXPECT_TRUE(window1.get() == manager_->GetCurrentPointerFocusedWindow()); wl_pointer_send_leave(pointer->resource(), 2, surface->resource()); @@ -119,6 +122,7 @@ Sync(); EXPECT_FALSE(manager_->GetCurrentFocusedWindow()); + EXPECT_FALSE(manager_->GetCurrentPointerOrTouchFocusedWindow()); EXPECT_FALSE(manager_->GetCurrentPointerFocusedWindow()); } @@ -152,7 +156,8 @@ Sync(); - EXPECT_FALSE(manager_->GetCurrentFocusedWindow()); + EXPECT_FALSE(manager_->GetCurrentPointerOrTouchFocusedWindow()); + EXPECT_TRUE(window1.get() == manager_->GetCurrentFocusedWindow()); EXPECT_TRUE(window1.get() == manager_->GetCurrentKeyboardFocusedWindow()); wl_keyboard_send_leave(keyboard->resource(), 2, surface->resource());
diff --git a/ui/views/accessibility/ax_aura_obj_cache.cc b/ui/views/accessibility/ax_aura_obj_cache.cc index df73f76..c1b8a6b 100644 --- a/ui/views/accessibility/ax_aura_obj_cache.cc +++ b/ui/views/accessibility/ax_aura_obj_cache.cc
@@ -143,6 +143,9 @@ RemoveInternal(window, &window_to_id_map_); if (parent && delegate_) delegate_->OnChildWindowRemoved(parent_window_obj); + + if (focused_window_ == window) + focused_window_ = nullptr; } AXAuraObjWrapper* AXAuraObjCache::Get(int32_t id) {
diff --git a/ui/views/accessibility/ax_tree_source_views_unittest.cc b/ui/views/accessibility/ax_tree_source_views_unittest.cc index a2d54aa3..c682448a 100644 --- a/ui/views/accessibility/ax_tree_source_views_unittest.cc +++ b/ui/views/accessibility/ax_tree_source_views_unittest.cc
@@ -12,6 +12,8 @@ #include "testing/gtest/include/gtest/gtest.h" #include "ui/accessibility/ax_tree_data.h" #include "ui/accessibility/platform/ax_unique_id.h" +#include "ui/aura/client/focus_client.h" +#include "ui/aura/test/test_window_delegate.h" #include "ui/gfx/geometry/rect_f.h" #include "ui/views/accessibility/ax_aura_obj_cache.h" #include "ui/views/accessibility/ax_aura_obj_wrapper.h" @@ -167,5 +169,41 @@ EXPECT_EQ(nullptr, cache.GetOrCreate(textfield_)->GetParent()); } +#if BUILDFLAG(ENABLE_DESKTOP_AURA) +class AXTreeSourceViewsDesktopWidgetTest : public AXTreeSourceViewsTest { + public: + AXTreeSourceViewsDesktopWidgetTest() { + set_native_widget_type(ViewsTestBase::NativeWidgetType::kDesktop); + } +}; + +// Tests that no use-after-free when a focused child window is destroyed in +// desktop aura widget. +TEST_F(AXTreeSourceViewsDesktopWidgetTest, FocusedChildWindowDestroyed) { + AXAuraObjCache cache; + AXAuraObjWrapper* root_wrapper = + cache.GetOrCreate(widget_->GetNativeWindow()->GetRootWindow()); + EXPECT_NE(nullptr, root_wrapper); + + aura::test::TestWindowDelegate child_delegate; + aura::Window* child = new aura::Window(&child_delegate); + child->Init(ui::LAYER_NOT_DRAWN); + widget_->GetNativeView()->AddChild(child); + aura::client::GetFocusClient(widget_->GetNativeView())->FocusWindow(child); + + AXAuraObjWrapper* child_wrapper = cache.GetOrCreate(child); + EXPECT_NE(nullptr, child_wrapper); + + // GetFocus() reflects the focused child window. + EXPECT_NE(nullptr, cache.GetFocus()); + + // Close the widget to destroy the child. + widget_.reset(); + + // GetFocus() should return null and no use-after-free to call it. + EXPECT_EQ(nullptr, cache.GetFocus()); +} +#endif // defined(USE_AURA) + } // namespace } // namespace views
diff --git a/ui/views/animation/bounds_animator.cc b/ui/views/animation/bounds_animator.cc index 862a04e..a042e49 100644 --- a/ui/views/animation/bounds_animator.cc +++ b/ui/views/animation/bounds_animator.cc
@@ -16,6 +16,11 @@ #include "ui/views/view.h" #include "ui/views/widget/widget.h" +// This should be after all other #includes. +#if defined(_WINDOWS_) // Detect whether windows.h was included. +#include "base/win/windows_h_disallowed.h" +#endif // defined(_WINDOWS_) + namespace views { BoundsAnimator::BoundsAnimator(View* parent, bool use_transforms)
diff --git a/ui/views/widget/root_view.cc b/ui/views/widget/root_view.cc index 48ec8693..9d09b21 100644 --- a/ui/views/widget/root_view.cc +++ b/ui/views/widget/root_view.cc
@@ -107,14 +107,14 @@ // ui::EventHandler: void OnKeyEvent(ui::KeyEvent* event) override { CHECK_EQ(ui::EP_PRETARGET, event->phase()); +// macOS doesn't have keyboard-triggered context menus. +#if !defined(OS_MAC) if (event->handled()) return; View* v = nullptr; if (owner_->GetFocusManager()) // Can be NULL in unittests. v = owner_->GetFocusManager()->GetFocusedView(); -// macOS doesn't have keyboard-triggered context menus. -#if !defined(OS_MAC) // Special case to handle keyboard-triggered context menus. if (v && v->GetEnabled() && ((event->key_code() == ui::VKEY_APPS) ||